diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c index cce5ff0c79c..6a3a5f39d95 100644 --- a/contrib/pg_upgrade/check.c +++ b/contrib/pg_upgrade/check.c @@ -118,18 +118,38 @@ check_new_cluster(void) { set_locale_and_encoding(&new_cluster); + check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata); + get_db_and_rel_infos(&new_cluster); check_new_cluster_is_empty(); - check_for_prepared_transactions(&new_cluster); + check_old_cluster_has_new_cluster_dbs(); check_loadable_libraries(); - check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata); - if (user_opts.transfer_mode == TRANSFER_MODE_LINK) check_hard_link(); + + check_is_super_user(&new_cluster); + + /* + * We don't restore our own user, so both clusters must match have + * matching install-user oids. + */ + if (old_cluster.install_role_oid != new_cluster.install_role_oid) + pg_log(PG_FATAL, + "Old and new cluster install users have different values for pg_authid.oid.\n"); + + /* + * We only allow the install user in the new cluster because other + * defined users might match users defined in the old cluster and + * generate an error during pg_dump restore. + */ + if (new_cluster.role_count != 1) + pg_log(PG_FATAL, "Only the install user can be defined in the new cluster.\n"); + + check_for_prepared_transactions(&new_cluster); } @@ -485,7 +505,7 @@ create_script_for_old_cluster_deletion( /* * check_is_super_user() * - * Make sure we are the super-user. + * Check we are superuser, and out user id and user count */ static void check_is_super_user(ClusterInfo *cluster) @@ -497,7 +517,7 @@ check_is_super_user(ClusterInfo *cluster) /* Can't use pg_authid because only superusers can view it. */ res = executeQueryOrDie(conn, - "SELECT rolsuper " + "SELECT rolsuper, oid " "FROM pg_catalog.pg_roles " "WHERE rolname = current_user"); @@ -505,6 +525,19 @@ check_is_super_user(ClusterInfo *cluster) pg_log(PG_FATAL, "database user \"%s\" is not a superuser\n", os_info.user); + cluster->install_role_oid = atooid(PQgetvalue(res, 0, 1)); + + PQclear(res); + + res = executeQueryOrDie(conn, + "SELECT COUNT(*) " + "FROM pg_catalog.pg_roles "); + + if (PQntuples(res) != 1) + pg_log(PG_FATAL, "could not determine the number of users\n"); + + cluster->role_count = atoi(PQgetvalue(res, 0, 0)); + PQclear(res); PQfinish(conn); diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c index abd3d5f8a2a..e8b48a4fab0 100644 --- a/contrib/pg_upgrade/pg_upgrade.c +++ b/contrib/pg_upgrade/pg_upgrade.c @@ -29,7 +29,7 @@ * We control all assignments of pg_enum.oid because these oids are stored * in user tables as enum values. * - * We control all assignments of pg_auth.oid because these oids are stored + * We control all assignments of pg_authid.oid because these oids are stored * in pg_largeobject_metadata. */ diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h index 204749b6509..40f03d666f3 100644 --- a/contrib/pg_upgrade/pg_upgrade.h +++ b/contrib/pg_upgrade/pg_upgrade.h @@ -187,6 +187,8 @@ typedef struct char major_version_str[64]; /* string PG_VERSION of cluster */ uint32 bin_version; /* version returned from pg_ctl */ Oid pg_database_oid; /* OID of pg_database relation */ + Oid install_role_oid; /* OID of connected role */ + Oid role_count; /* number of roles defined in the cluster */ char *tablespace_suffix; /* directory specification */ } ClusterInfo;