From 1b2773179f31b25bc560e06a35970fdd9b1a6d90 Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Tue, 24 Feb 2026 14:01:41 -0800 Subject: [PATCH] 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. Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com Backpatch-through: 14 --- src/bin/pg_upgrade/dump.c | 6 +++++- src/bin/pg_upgrade/pg_upgrade.h | 1 + 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/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/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/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