public inbox for [email protected]
help / color / mirror / Atom feedFrom: Jacob Champion <[email protected]>
To: Tom Lane <[email protected]>
Cc: Jelte Fennema-Nio <[email protected]>
Cc: [email protected]
Cc: Andrew Dunstan <[email protected]>
Cc: Nathan Bossart <[email protected]>
Subject: Re: pgsql: libpq: Grease the protocol by default
Date: Tue, 24 Feb 2026 12:29:02 -0800
Message-ID: <CAOYmi+mFbpQ50KjV48-M0YarZjHDLEXXtqhzy-BuXseRPU5D9Q@mail.gmail.com> (raw)
In-Reply-To: <CAOYmi+=J2BtChfaRSo7YnWe=O2OOwA43vAte+67XDMAaZQ-=Pg@mail.gmail.com>
References: <[email protected]>
<CAOYmi+=4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ@mail.gmail.com>
<[email protected]>
<CAOYmi+k8ENYkErqSEYEqW39YWPfe_ii7g5Acm1c9asNuRMriNg@mail.gmail.com>
<[email protected]>
<CAOYmi+mtFBsB2zePSvbpa-2Zb-+V5bov_t2BzkGH7vfKX0ny_w@mail.gmail.com>
<[email protected]>
<CAOYmi+kC3AN0QJKT0OunHCmi4UU7-15eu7w-DY5ckOgHiQE1QA@mail.gmail.com>
<[email protected]>
<CAOYmi+=96EGcQnY2w99yLeARHsbvgT_2Bv1hjXKUziykMzMhtA@mail.gmail.com>
<CAOYmi+=6AFrYm5LaPc=ECyLp2uh1-Y8xLA-dRBJE82JLRdiQ5g@mail.gmail.com>
<[email protected]>
<CAOYmi+=J2BtChfaRSo7YnWe=O2OOwA43vAte+67XDMAaZQ-=Pg@mail.gmail.com>
On Tue, Feb 24, 2026 at 10:58 AM Jacob Champion
<[email protected]> wrote:
> We do store (the major version part of) `pg_ctl --version` at some
> point, which we could improve upon, but I agree that adding additional
> complexity here doesn't actually give us any benefit.
Okay, here are the patches I propose. The ones for 18-HEAD check for
PG10 and below, and 14-17 additionally check that libpq >= 18, before
adding max_protocol_version=3.0.
I smoke-tested upgrades from 9.2, 10.1, and 11.0 for all six branches,
and then re-ran that test matrix with pg_upgrade linked against a
greased libpq.
--Jacob
Attachments:
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.patch (5.0K, 2-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.patch)
download | inline diff:
From e2a69ee5f96f64ea94f62f9085591129899b3b7c Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/task.c | 2 ++
src/bin/pg_upgrade/version.c | 18 ++++++++++++++++++
5 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index ec018e4f292..1d767bbda2d 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -501,6 +501,7 @@ unsigned int str2uint(const char *str);
/* version.c */
bool jsonb_9_4_check_applicable(ClusterInfo *cluster);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
bool check_mode);
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index e4c9349311a..f47c8d06211 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s --no-sync -f \"%s/%s\"",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
log_opts.dumpdir,
GLOBALS_DUMP_FILE);
@@ -43,6 +44,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index eeeac3153f0..1eb8bc97c05 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -71,6 +71,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/task.c b/src/bin/pg_upgrade/task.c
index d4cd487bad0..3d958527528 100644
--- a/src/bin/pg_upgrade/task.c
+++ b/src/bin/pg_upgrade/task.c
@@ -188,6 +188,8 @@ start_conn(const ClusterInfo *cluster, UpgradeTaskSlot *slot)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
slot->conn = PQconnectStart(conn_opts.data);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index e709262837e..047670d4acb 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -28,6 +28,24 @@ jsonb_9_4_check_applicable(ClusterInfo *cluster)
return false;
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.18.patch (5.0K, 3-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.18.patch)
download | inline diff:
From 3ba57656ee69d84ca7065a90f3077b499604a6d6 Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/task.c | 2 ++
src/bin/pg_upgrade/version.c | 18 ++++++++++++++++++
5 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index 69c965bb7d0..22057c22901 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -493,6 +493,7 @@ unsigned int str2uint(const char *str);
/* version.c */
bool jsonb_9_4_check_applicable(ClusterInfo *cluster);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
bool check_mode);
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 55f6e7b4d9c..806bf3bef97 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s --no-sync -f \"%s/%s\"",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
log_opts.dumpdir,
GLOBALS_DUMP_FILE);
@@ -43,6 +44,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index 7eb15bc7d5a..43e6797e14c 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -71,6 +71,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/task.c b/src/bin/pg_upgrade/task.c
index ee0e2457152..a19ea8445a0 100644
--- a/src/bin/pg_upgrade/task.c
+++ b/src/bin/pg_upgrade/task.c
@@ -188,6 +188,8 @@ start_conn(const ClusterInfo *cluster, UpgradeTaskSlot *slot)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
slot->conn = PQconnectStart(conn_opts.data);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index 3ad5a991a30..56f3dc693fb 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -28,6 +28,24 @@ jsonb_9_4_check_applicable(ClusterInfo *cluster)
return false;
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.17.patch (4.9K, 4-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.17.patch)
download | inline diff:
From 1e421e723831bc12f4ab23aa2ede8520bb9c072d Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/version.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index e2b99b49fab..5ad693eaa70 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -482,6 +482,7 @@ unsigned int str2uint(const char *str);
/* version.c */
bool jsonb_9_4_check_applicable(ClusterInfo *cluster);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
bool check_mode);
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 29fb45b9289..b14c4ce0ee2 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s -f \"%s/%s\"",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
log_opts.dumpdir,
GLOBALS_DUMP_FILE);
@@ -43,6 +44,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index b223d5afddf..107e2676397 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -71,6 +71,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index 2de6dffccda..276ead84e3f 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -28,6 +28,37 @@ jsonb_9_4_check_applicable(ClusterInfo *cluster)
return false;
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * Back-branch-specific complication: for libpq versions prior to PG18,
+ * max_protocol_version isn't supported. But we also don't need to worry
+ * about newer protocol versions being used in that case, so just lie and
+ * return true.
+ *
+ * (Checking for a libpq version that's newer than this branch looks very
+ * strange, but distributions are allowed to link older pg_upgrade
+ * binaries against the newest release of libpq.)
+ */
+ if (PQlibVersion() < 180000)
+ return true;
+
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.16.patch (5.1K, 5-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.16.patch)
download | inline diff:
From 3b5e43a02c680f7e179b09f1d653e7cf6538dbca Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/version.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index 7afa96716ec..44aad96de7b 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -456,6 +456,7 @@ bool check_for_data_types_usage(ClusterInfo *cluster,
bool check_for_data_type_usage(ClusterInfo *cluster,
const char *type_name,
const char *output_path);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster);
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 6c8c82dca89..a698519029e 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s -f \"%s/%s\"",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
log_opts.dumpdir,
GLOBALS_DUMP_FILE);
@@ -43,6 +44,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index 0bc3d2806b8..75d40626b48 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -71,6 +71,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index 403a6d7cfaa..e869d526ba1 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -241,6 +241,37 @@ old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
check_ok();
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * Back-branch-specific complication: for libpq versions prior to PG18,
+ * max_protocol_version isn't supported. But we also don't need to worry
+ * about newer protocol versions being used in that case, so just lie and
+ * return true.
+ *
+ * (Checking for a libpq version that's newer than this branch looks very
+ * strange, but distributions are allowed to link older pg_upgrade
+ * binaries against the newest release of libpq.)
+ */
+ if (PQlibVersion() < 180000)
+ return true;
+
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.15.patch (5.1K, 6-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.15.patch)
download | inline diff:
From 1f2cbbdefac2841de1a67d3feec18eaeaed719b3 Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/version.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index 19ca68ed619..803acc696ef 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -449,6 +449,7 @@ bool check_for_data_types_usage(ClusterInfo *cluster,
bool check_for_data_type_usage(ClusterInfo *cluster,
const char *type_name,
const char *output_path);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster);
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 29b9e44f782..f7d6a537b4f 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s -f \"%s/%s\"",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
log_opts.dumpdir,
GLOBALS_DUMP_FILE);
@@ -43,6 +44,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index 265137e86bf..df165efac40 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -71,6 +71,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index 20c61072a42..fa6b945869d 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -241,6 +241,37 @@ old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
check_ok();
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * Back-branch-specific complication: for libpq versions prior to PG18,
+ * max_protocol_version isn't supported. But we also don't need to worry
+ * about newer protocol versions being used in that case, so just lie and
+ * return true.
+ *
+ * (Checking for a libpq version that's newer than this branch looks very
+ * strange, but distributions are allowed to link older pg_upgrade
+ * binaries against the newest release of libpq.)
+ */
+ if (PQlibVersion() < 180000)
+ return true;
+
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
[application/octet-stream] v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.14.patch (5.1K, 7-v2-0001-pg_upgrade-Use-max_protocol_version-3.0-for-older.14.patch)
download | inline diff:
From 79b399178807bad11d3c3aa8a6cbd47d014f718e Mon Sep 17 00:00:00 2001
From: Jacob Champion <[email protected]>
Date: Mon, 23 Feb 2026 15:28:32 -0800
Subject: [PATCH v2] pg_upgrade: Use max_protocol_version=3.0 for older servers
The grease patch in 4966bd3ed found its first problem: prior to the
February 2018 patch releases, no server knew how to negotiate protocol
versions, so pg_upgrade needs to take that into account when speaking to
those older servers.
This will be true even after the grease feature is reverted; we don't
need anyone to trip over this again in the future. Backpatch so that all
supported versions of pg_upgrade can gracefully handle an update to the
default protocol version. (This is needed for any distributions that
link older binaries against newer libpqs, such as Debian.) Branches
prior to 18 need an additional version check, for the existence of
max_protocol_version.
Per buildfarm member crake.
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14
---
src/bin/pg_upgrade/pg_upgrade.h | 1 +
src/bin/pg_upgrade/dump.c | 6 +++++-
src/bin/pg_upgrade/server.c | 2 ++
src/bin/pg_upgrade/version.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index e647e71ecaf..14f9cb522db 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -446,6 +446,7 @@ bool check_for_data_types_usage(ClusterInfo *cluster,
bool check_for_data_type_usage(ClusterInfo *cluster,
const char *type_name,
const char *output_path);
+bool protocol_negotiation_supported(const ClusterInfo *cluster);
void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
bool check_mode);
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c
index 90060d0f8eb..ee0ace082ca 100644
--- a/src/bin/pg_upgrade/dump.c
+++ b/src/bin/pg_upgrade/dump.c
@@ -21,9 +21,10 @@ generate_old_dump(void)
/* run new pg_dumpall binary for globals */
exec_prog(UTILITY_LOG_FILE, NULL, true, true,
- "\"%s/pg_dumpall\" %s --globals-only --quote-all-identifiers "
+ "\"%s/pg_dumpall\" %s%s --globals-only --quote-all-identifiers "
"--binary-upgrade %s -f %s",
new_cluster.bindir, cluster_conn_opts(&old_cluster),
+ protocol_negotiation_supported(&old_cluster) ? "" : " -d \"max_protocol_version=3.0\"",
log_opts.verbose ? "--verbose" : "",
GLOBALS_DUMP_FILE);
check_ok();
@@ -42,6 +43,9 @@ generate_old_dump(void)
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
appendConnStrVal(&connstr, old_db->db_name);
+ if (!protocol_negotiation_supported(&old_cluster))
+ appendPQExpBufferStr(&connstr, " max_protocol_version=3.0");
+
initPQExpBuffer(&escaped_connstr);
appendShellString(&escaped_connstr, connstr.data);
termPQExpBuffer(&connstr);
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index 7fed0ae1086..f49f3013c38 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -70,6 +70,8 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
appendPQExpBufferStr(&conn_opts, " host=");
appendConnStrVal(&conn_opts, cluster->sockdir);
}
+ if (!protocol_negotiation_supported(cluster))
+ appendPQExpBufferStr(&conn_opts, " max_protocol_version=3.0");
conn = PQconnectdb(conn_opts.data);
termPQExpBuffer(&conn_opts);
diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c
index ccb012657be..48fecae47f4 100644
--- a/src/bin/pg_upgrade/version.c
+++ b/src/bin/pg_upgrade/version.c
@@ -325,6 +325,37 @@ old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
check_ok();
}
+/*
+ * Older servers can't support newer protocol versions, so their connection
+ * strings will need to lock max_protocol_version to 3.0.
+ */
+bool
+protocol_negotiation_supported(const ClusterInfo *cluster)
+{
+ /*
+ * Back-branch-specific complication: for libpq versions prior to PG18,
+ * max_protocol_version isn't supported. But we also don't need to worry
+ * about newer protocol versions being used in that case, so just lie and
+ * return true.
+ *
+ * (Checking for a libpq version that's newer than this branch looks very
+ * strange, but distributions are allowed to link older pg_upgrade
+ * binaries against the newest release of libpq.)
+ */
+ if (PQlibVersion() < 180000)
+ return true;
+
+ /*
+ * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
+ * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
+ * has information about the major version number. To ensure we can still
+ * upgrade older unpatched servers, just assume anything prior to PG11
+ * can't negotiate. It's not possible for those servers to make use of
+ * newer protocols anyway, so nothing is lost.
+ */
+ return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
+}
+
/*
* old_9_6_invalidate_hash_indexes()
* 9.6 -> 10
--
2.34.1
view thread (27+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: pgsql: libpq: Grease the protocol by default
In-Reply-To: <CAOYmi+mFbpQ50KjV48-M0YarZjHDLEXXtqhzy-BuXseRPU5D9Q@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox