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/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/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