]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pg_upgrade: Use max_protocol_version=3.0 for older servers
authorJacob Champion <jchampion@postgresql.org>
Tue, 24 Feb 2026 22:01:46 +0000 (14:01 -0800)
committerJacob Champion <jchampion@postgresql.org>
Tue, 24 Feb 2026 22:01:46 +0000 (14:01 -0800)
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 <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAOYmi%2B%3D4QhCjssfNEoZVK8LPtWxnfkwT5p-PAeoxtG9gpNjqOQ%40mail.gmail.com
Backpatch-through: 14

src/bin/pg_upgrade/dump.c
src/bin/pg_upgrade/pg_upgrade.h
src/bin/pg_upgrade/server.c
src/bin/pg_upgrade/version.c

index 29fb45b928923b8debf89bdd43b9251e123aed70..b14c4ce0ee25f70492bd862684996ae134e95ea3 100644 (file)
@@ -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);
index e2b99b49fabe67a4e079691a84941ae044016fce..5ad693eaa70904bf37162e91bb745eae5e3797e8 100644 (file)
@@ -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);
 
index b223d5afddfffd91e33e531b2990b48991bed883..107e26763975daffbc8a1d2b2f6cc575587ff280 100644 (file)
@@ -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);
index 2de6dffccdab4d7ab039b7e3da46c3604e4c6615..93e7464f2752cd405e248d1345194742ecb459ae 100644 (file)
@@ -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: in 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