PostgreSQL Source Code  git master
check.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_authid_d.h"
#include "catalog/pg_collation.h"
#include "fe_utils/string_utils.h"
#include "mb/pg_wchar.h"
#include "pg_upgrade.h"
Include dependency graph for check.c:

Go to the source code of this file.

Functions

static void check_new_cluster_is_empty (void)
 
static void check_is_install_user (ClusterInfo *cluster)
 
static void check_proper_datallowconn (ClusterInfo *cluster)
 
static void check_for_prepared_transactions (ClusterInfo *cluster)
 
static void check_for_isn_and_int8_passing_mismatch (ClusterInfo *cluster)
 
static void check_for_user_defined_postfix_ops (ClusterInfo *cluster)
 
static void check_for_incompatible_polymorphics (ClusterInfo *cluster)
 
static void check_for_tables_with_oids (ClusterInfo *cluster)
 
static void check_for_composite_data_type_usage (ClusterInfo *cluster)
 
static void check_for_reg_data_type_usage (ClusterInfo *cluster)
 
static void check_for_aclitem_data_type_usage (ClusterInfo *cluster)
 
static void check_for_removed_data_type_usage (ClusterInfo *cluster, const char *version, const char *datatype)
 
static void check_for_jsonb_9_4_usage (ClusterInfo *cluster)
 
static void check_for_pg_role_prefix (ClusterInfo *cluster)
 
static void check_for_new_tablespace_dir (void)
 
static void check_for_user_defined_encoding_conversions (ClusterInfo *cluster)
 
static void check_new_cluster_logical_replication_slots (void)
 
static void check_old_cluster_for_valid_slots (bool live_check)
 
static char * fix_path_separator (char *path)
 
void output_check_banner (bool live_check)
 
void check_and_dump_old_cluster (bool live_check)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (bool live_check)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 

Function Documentation

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 87 of file check.c.

88 {
89  /* -- OLD -- */
90 
91  if (!live_check)
93 
94  /*
95  * Extract a list of databases, tables, and logical replication slots from
96  * the old cluster.
97  */
99 
101 
103 
104 
105  /*
106  * Check for various failure cases
107  */
114 
115  /*
116  * Logical replication slots can be migrated since PG17. See comments atop
117  * get_old_cluster_logical_slot_infos().
118  */
121 
122  /*
123  * PG 16 increased the size of the 'aclitem' type, which breaks the
124  * on-disk format for existing data.
125  */
128 
129  /*
130  * PG 12 removed types abstime, reltime, tinterval.
131  */
133  {
136  check_for_removed_data_type_usage(&old_cluster, "12", "tinterval");
137  }
138 
139  /*
140  * PG 14 changed the function signature of encoding conversion functions.
141  * Conversions from older versions cannot be upgraded automatically
142  * because the user-defined functions used by the encoding conversions
143  * need to be changed to match the new signature.
144  */
147 
148  /*
149  * Pre-PG 14 allowed user defined postfix operators, which are not
150  * supported anymore. Verify there are none, iff applicable.
151  */
154 
155  /*
156  * PG 14 changed polymorphic functions from anyarray to
157  * anycompatiblearray.
158  */
161 
162  /*
163  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
164  * supported anymore. Verify there are none, iff applicable.
165  */
168 
169  /*
170  * PG 12 changed the 'sql_identifier' type storage to be based on name,
171  * not varchar, which breaks on-disk format for existing data. So we need
172  * to prevent upgrade when used in user objects (tables, indexes, ...).
173  */
176 
177  /*
178  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
179  * hash indexes
180  */
182  {
184  if (user_opts.check)
186  }
187 
188  /* 9.5 and below should not have roles starting with pg_ */
191 
195 
196  /* Pre-PG 9.4 had a different 'line' data type internal format */
199 
200  /*
201  * While not a check option, we do this now because this is the only time
202  * the old server is running.
203  */
204  if (!user_opts.check)
206 
207  if (!live_check)
208  stop_postmaster(false);
209 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1045
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1335
static void check_for_composite_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1125
static void check_for_removed_data_type_usage(ClusterInfo *cluster, const char *version, const char *datatype)
Definition: check.c:1271
static void check_old_cluster_for_valid_slots(bool live_check)
Definition: check.c:1548
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:559
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:737
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:819
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:702
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:617
static void check_for_aclitem_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1241
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1391
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:1305
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:918
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1186
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:55
void get_db_rel_and_slot_infos(ClusterInfo *cluster, bool live_check)
Definition: info.c:279
static pid_t start_postmaster(void)
Definition: pg_ctl.c:439
ClusterInfo old_cluster
Definition: pg_upgrade.c:64
void init_tablespaces(void)
Definition: tablespace.c:19
void old_11_check_for_sql_identifier_data_type_usage(ClusterInfo *cluster)
Definition: version.c:365
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
Definition: version.c:180
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
Definition: version.c:220
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:347
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:250
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:127
UserOpts user_opts
Definition: option.c:30
ControlData controldata
Definition: pg_upgrade.h:280
uint32 major_version
Definition: pg_upgrade.h:291
uint32 cat_ver
Definition: pg_upgrade.h:226
bool check
Definition: pg_upgrade.h:320

References ControlData::cat_ver, UserOpts::check, check_for_aclitem_data_type_usage(), check_for_composite_data_type_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_jsonb_9_4_usage(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_for_removed_data_type_usage(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_old_cluster_for_valid_slots(), check_proper_datallowconn(), ClusterInfo::controldata, generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, init_tablespaces(), JSONB_FORMAT_CHANGE_CAT_VER, ClusterInfo::major_version, old_11_check_for_sql_identifier_data_type_usage(), old_9_3_check_for_line_data_type_usage(), old_9_6_check_for_unknown_data_type_usage(), old_9_6_invalidate_hash_indexes(), old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( bool  live_check)

Definition at line 361 of file check.c.

362 {
363  /* get/check pg_control data of servers */
364  get_control_data(&old_cluster, live_check);
365  get_control_data(&new_cluster, false);
367 
368  if (live_check && old_cluster.port == new_cluster.port)
369  pg_fatal("When checking a live server, "
370  "the old and new port numbers must be different.");
371 }
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:656
#define pg_fatal(...)
ClusterInfo new_cluster
Definition: pg_upgrade.c:65
unsigned short port
Definition: pg_upgrade.h:290

References check_control_data(), ClusterInfo::controldata, get_control_data(), new_cluster, old_cluster, pg_fatal, and ClusterInfo::port.

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 318 of file check.c.

319 {
320  prep_status("Checking cluster versions");
321 
322  /* cluster versions should already have been obtained */
325 
326  /*
327  * We allow upgrades from/to the same major version for alpha/beta
328  * upgrades
329  */
330 
332  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
333  "9.2");
334 
335  /* Only current PG version is supported as a target */
337  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
338  PG_MAJORVERSION);
339 
340  /*
341  * We can't allow downgrading because we use the target pg_dump, and
342  * pg_dump cannot operate on newer database versions, only current and
343  * older versions.
344  */
346  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
347 
348  /* Ensure binaries match the designated data directories */
351  pg_fatal("Old cluster data and binary directories are from different major versions.");
354  pg_fatal("New cluster data and binary directories are from different major versions.");
355 
356  check_ok();
357 }
static void check_ok(void)
Definition: initdb.c:2036
Assert(fmt[strlen(fmt) - 1] !='\n')
void prep_status(const char *fmt,...) pg_attribute_printf(1
uint32 bin_version
Definition: pg_upgrade.h:293

References Assert(), ClusterInfo::bin_version, check_ok(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal, and prep_status().

Referenced by main().

◆ check_for_aclitem_data_type_usage()

static void check_for_aclitem_data_type_usage ( ClusterInfo cluster)
static

Definition at line 1241 of file check.c.

1242 {
1243  char output_path[MAXPGPATH];
1244 
1245  prep_status("Checking for incompatible \"%s\" data type in user tables",
1246  "aclitem");
1247 
1248  snprintf(output_path, sizeof(output_path), "tables_using_aclitem.txt");
1249 
1250  if (check_for_data_type_usage(cluster, "pg_catalog.aclitem", output_path))
1251  {
1252  pg_log(PG_REPORT, "fatal");
1253  pg_fatal("Your installation contains the \"aclitem\" data type in user tables.\n"
1254  "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
1255  "so this cluster cannot currently be upgraded. You can drop the\n"
1256  "problem columns and restart the upgrade. A list of the problem\n"
1257  "columns is in the file:\n"
1258  " %s", output_path);
1259  }
1260  else
1261  check_ok();
1262 }
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:110
#define MAXPGPATH
bool check_for_data_type_usage(ClusterInfo *cluster, const char *type_name, const char *output_path)
Definition: version.c:153
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
@ PG_REPORT
Definition: pg_upgrade.h:267
#define snprintf
Definition: port.h:238

References check_for_data_type_usage(), check_ok(), cluster(), MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_composite_data_type_usage()

static void check_for_composite_data_type_usage ( ClusterInfo cluster)
static

Definition at line 1125 of file check.c.

1126 {
1127  bool found;
1128  Oid firstUserOid;
1129  char output_path[MAXPGPATH];
1130  char *base_query;
1131 
1132  prep_status("Checking for system-defined composite types in user tables");
1133 
1134  snprintf(output_path, sizeof(output_path), "%s/%s",
1135  log_opts.basedir,
1136  "tables_using_composite.txt");
1137 
1138  /*
1139  * Look for composite types that were made during initdb *or* belong to
1140  * information_schema; that's important in case information_schema was
1141  * dropped and reloaded.
1142  *
1143  * The cutoff OID here should match the source cluster's value of
1144  * FirstNormalObjectId. We hardcode it rather than using that C #define
1145  * because, if that #define is ever changed, our own version's value is
1146  * NOT what to use. Eventually we may need a test on the source cluster's
1147  * version to select the correct value.
1148  */
1149  firstUserOid = 16384;
1150 
1151  base_query = psprintf("SELECT t.oid FROM pg_catalog.pg_type t "
1152  "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
1153  " WHERE typtype = 'c' AND (t.oid < %u OR nspname = 'information_schema')",
1154  firstUserOid);
1155 
1156  found = check_for_data_types_usage(cluster, base_query, output_path);
1157 
1158  free(base_query);
1159 
1160  if (found)
1161  {
1162  pg_log(PG_REPORT, "fatal");
1163  pg_fatal("Your installation contains system-defined composite types in user tables.\n"
1164  "These type OIDs are not stable across PostgreSQL versions,\n"
1165  "so this cluster cannot currently be upgraded. You can\n"
1166  "drop the problem columns and restart the upgrade.\n"
1167  "A list of the problem columns is in the file:\n"
1168  " %s", output_path);
1169  }
1170  else
1171  check_ok();
1172 }
#define free(a)
Definition: header.h:65
bool check_for_data_types_usage(ClusterInfo *cluster, const char *base_query, const char *output_path)
Definition: version.c:31
LogOpts log_opts
Definition: util.c:17
unsigned int Oid
Definition: postgres_ext.h:31
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
char * basedir
Definition: pg_upgrade.h:308

References LogOpts::basedir, check_for_data_types_usage(), check_ok(), cluster(), free, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), psprintf(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_incompatible_polymorphics()

static void check_for_incompatible_polymorphics ( ClusterInfo cluster)
static

Definition at line 918 of file check.c.

919 {
920  PGresult *res;
921  FILE *script = NULL;
922  char output_path[MAXPGPATH];
923  PQExpBufferData old_polymorphics;
924 
925  prep_status("Checking for incompatible polymorphic functions");
926 
927  snprintf(output_path, sizeof(output_path), "%s/%s",
929  "incompatible_polymorphics.txt");
930 
931  /* The set of problematic functions varies a bit in different versions */
932  initPQExpBuffer(&old_polymorphics);
933 
934  appendPQExpBufferStr(&old_polymorphics,
935  "'array_append(anyarray,anyelement)'"
936  ", 'array_cat(anyarray,anyarray)'"
937  ", 'array_prepend(anyelement,anyarray)'");
938 
939  if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
940  appendPQExpBufferStr(&old_polymorphics,
941  ", 'array_remove(anyarray,anyelement)'"
942  ", 'array_replace(anyarray,anyelement,anyelement)'");
943 
944  if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
945  appendPQExpBufferStr(&old_polymorphics,
946  ", 'array_position(anyarray,anyelement)'"
947  ", 'array_position(anyarray,anyelement,integer)'"
948  ", 'array_positions(anyarray,anyelement)'"
949  ", 'width_bucket(anyelement,anyarray)'");
950 
951  for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
952  {
953  bool db_used = false;
954  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
955  PGconn *conn = connectToServer(cluster, active_db->db_name);
956  int ntups;
957  int i_objkind,
958  i_objname;
959 
960  /*
961  * The query below hardcodes FirstNormalObjectId as 16384 rather than
962  * interpolating that C #define into the query because, if that
963  * #define is ever changed, the cutoff we want to use is the value
964  * used by pre-version 14 servers, not that of some future version.
965  */
967  /* Aggregate transition functions */
968  "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
969  "FROM pg_proc AS p "
970  "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
971  "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
972  "WHERE p.oid >= 16384 "
973  "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
974  "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
975 
976  /* Aggregate final functions */
977  "UNION ALL "
978  "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
979  "FROM pg_proc AS p "
980  "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
981  "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
982  "WHERE p.oid >= 16384 "
983  "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
984  "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
985 
986  /* Operators */
987  "UNION ALL "
988  "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
989  "FROM pg_operator AS op "
990  "WHERE op.oid >= 16384 "
991  "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
992  "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);",
993  old_polymorphics.data,
994  old_polymorphics.data,
995  old_polymorphics.data);
996 
997  ntups = PQntuples(res);
998 
999  i_objkind = PQfnumber(res, "objkind");
1000  i_objname = PQfnumber(res, "objname");
1001 
1002  for (int rowno = 0; rowno < ntups; rowno++)
1003  {
1004  if (script == NULL &&
1005  (script = fopen_priv(output_path, "w")) == NULL)
1006  pg_fatal("could not open file \"%s\": %s",
1007  output_path, strerror(errno));
1008  if (!db_used)
1009  {
1010  fprintf(script, "In database: %s\n", active_db->db_name);
1011  db_used = true;
1012  }
1013 
1014  fprintf(script, " %s: %s\n",
1015  PQgetvalue(res, rowno, i_objkind),
1016  PQgetvalue(res, rowno, i_objname));
1017  }
1018 
1019  PQclear(res);
1020  PQfinish(conn);
1021  }
1022 
1023  if (script)
1024  {
1025  fclose(script);
1026  pg_log(PG_REPORT, "fatal");
1027  pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1028  "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1029  "These user-defined objects must be dropped before upgrading and restored\n"
1030  "afterwards, changing them to refer to the new corresponding functions with\n"
1031  "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1032  "A list of the problematic objects is in the file:\n"
1033  " %s", output_path);
1034  }
1035  else
1036  check_ok();
1037 
1038  termPQExpBuffer(&old_polymorphics);
1039 }
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4602
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3403
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3798
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3511
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:410
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define strerror
Definition: port.h:251
#define fprintf
Definition: port.h:242
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
PGconn * conn
Definition: streamutil.c:54
char * db_name
Definition: pg_upgrade.h:193

References appendPQExpBufferStr(), LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), PQExpBufferData::data, DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, GET_MAJOR_VERSION, initPQExpBuffer(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, strerror, and termPQExpBuffer().

Referenced by check_and_dump_old_cluster().

◆ check_for_isn_and_int8_passing_mismatch()

static void check_for_isn_and_int8_passing_mismatch ( ClusterInfo cluster)
static

Definition at line 737 of file check.c.

738 {
739  int dbnum;
740  FILE *script = NULL;
741  char output_path[MAXPGPATH];
742 
743  prep_status("Checking for contrib/isn with bigint-passing mismatch");
744 
747  {
748  /* no mismatch */
749  check_ok();
750  return;
751  }
752 
753  snprintf(output_path, sizeof(output_path), "%s/%s",
755  "contrib_isn_and_int8_pass_by_value.txt");
756 
757  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
758  {
759  PGresult *res;
760  bool db_used = false;
761  int ntups;
762  int rowno;
763  int i_nspname,
764  i_proname;
765  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
766  PGconn *conn = connectToServer(cluster, active_db->db_name);
767 
768  /* Find any functions coming from contrib/isn */
770  "SELECT n.nspname, p.proname "
771  "FROM pg_catalog.pg_proc p, "
772  " pg_catalog.pg_namespace n "
773  "WHERE p.pronamespace = n.oid AND "
774  " p.probin = '$libdir/isn'");
775 
776  ntups = PQntuples(res);
777  i_nspname = PQfnumber(res, "nspname");
778  i_proname = PQfnumber(res, "proname");
779  for (rowno = 0; rowno < ntups; rowno++)
780  {
781  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
782  pg_fatal("could not open file \"%s\": %s",
783  output_path, strerror(errno));
784  if (!db_used)
785  {
786  fprintf(script, "In database: %s\n", active_db->db_name);
787  db_used = true;
788  }
789  fprintf(script, " %s.%s\n",
790  PQgetvalue(res, rowno, i_nspname),
791  PQgetvalue(res, rowno, i_proname));
792  }
793 
794  PQclear(res);
795 
796  PQfinish(conn);
797  }
798 
799  if (script)
800  {
801  fclose(script);
802  pg_log(PG_REPORT, "fatal");
803  pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
804  "bigint data type. Your old and new clusters pass bigint values\n"
805  "differently so this cluster cannot currently be upgraded. You can\n"
806  "manually dump databases in the old cluster that use \"contrib/isn\"\n"
807  "facilities, drop them, perform the upgrade, and then restore them. A\n"
808  "list of the problem functions is in the file:\n"
809  " %s", output_path);
810  }
811  else
812  check_ok();
813 }
bool float8_pass_by_value
Definition: pg_upgrade.h:245

References LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), ClusterInfo::controldata, DbInfo::db_name, executeQueryOrDie(), ControlData::float8_pass_by_value, fopen_priv, fprintf, log_opts, MAXPGPATH, new_cluster, old_cluster, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_for_jsonb_9_4_usage()

static void check_for_jsonb_9_4_usage ( ClusterInfo cluster)
static

Definition at line 1305 of file check.c.

1306 {
1307  char output_path[MAXPGPATH];
1308 
1309  prep_status("Checking for incompatible \"jsonb\" data type");
1310 
1311  snprintf(output_path, sizeof(output_path), "%s/%s",
1312  log_opts.basedir,
1313  "tables_using_jsonb.txt");
1314 
1315  if (check_for_data_type_usage(cluster, "pg_catalog.jsonb", output_path))
1316  {
1317  pg_log(PG_REPORT, "fatal");
1318  pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
1319  "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
1320  "cluster cannot currently be upgraded. You can\n"
1321  "drop the problem columns and restart the upgrade.\n"
1322  "A list of the problem columns is in the file:\n"
1323  " %s", output_path);
1324  }
1325  else
1326  check_ok();
1327 }

References LogOpts::basedir, check_for_data_type_usage(), check_ok(), cluster(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_new_tablespace_dir()

static void check_for_new_tablespace_dir ( void  )
static

Definition at line 407 of file check.c.

408 {
409  int tblnum;
410  char new_tablespace_dir[MAXPGPATH];
411 
412  prep_status("Checking for new cluster tablespace directories");
413 
414  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
415  {
416  struct stat statbuf;
417 
418  snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
419  os_info.old_tablespaces[tblnum],
421 
422  if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
423  pg_fatal("new cluster tablespace directory already exists: \"%s\"",
424  new_tablespace_dir);
425  }
426 
427  check_ok();
428 }
OSInfo os_info
Definition: pg_upgrade.c:66
const char * tablespace_suffix
Definition: pg_upgrade.h:294
int num_old_tablespaces
Definition: pg_upgrade.h:344
char ** old_tablespaces
Definition: pg_upgrade.h:343
#define stat
Definition: win32_port.h:284

References check_ok(), MAXPGPATH, new_cluster, OSInfo::num_old_tablespaces, OSInfo::old_tablespaces, os_info, pg_fatal, prep_status(), snprintf, stat, and ClusterInfo::tablespace_suffix.

Referenced by check_new_cluster().

◆ check_for_pg_role_prefix()

static void check_for_pg_role_prefix ( ClusterInfo cluster)
static

Definition at line 1335 of file check.c.

1336 {
1337  PGresult *res;
1338  PGconn *conn = connectToServer(cluster, "template1");
1339  int ntups;
1340  int i_roloid;
1341  int i_rolname;
1342  FILE *script = NULL;
1343  char output_path[MAXPGPATH];
1344 
1345  prep_status("Checking for roles starting with \"pg_\"");
1346 
1347  snprintf(output_path, sizeof(output_path), "%s/%s",
1348  log_opts.basedir,
1349  "pg_role_prefix.txt");
1350 
1352  "SELECT oid AS roloid, rolname "
1353  "FROM pg_catalog.pg_roles "
1354  "WHERE rolname ~ '^pg_'");
1355 
1356  ntups = PQntuples(res);
1357  i_roloid = PQfnumber(res, "roloid");
1358  i_rolname = PQfnumber(res, "rolname");
1359  for (int rowno = 0; rowno < ntups; rowno++)
1360  {
1361  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1362  pg_fatal("could not open file \"%s\": %s",
1363  output_path, strerror(errno));
1364  fprintf(script, "%s (oid=%s)\n",
1365  PQgetvalue(res, rowno, i_rolname),
1366  PQgetvalue(res, rowno, i_roloid));
1367  }
1368 
1369  PQclear(res);
1370 
1371  PQfinish(conn);
1372 
1373  if (script)
1374  {
1375  fclose(script);
1376  pg_log(PG_REPORT, "fatal");
1377  pg_fatal("Your installation contains roles starting with \"pg_\".\n"
1378  "\"pg_\" is a reserved prefix for system roles. The cluster\n"
1379  "cannot be upgraded until these roles are renamed.\n"
1380  "A list of roles starting with \"pg_\" is in the file:\n"
1381  " %s", output_path);
1382  }
1383  else
1384  check_ok();
1385 }

References LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), executeQueryOrDie(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_for_prepared_transactions()

static void check_for_prepared_transactions ( ClusterInfo cluster)
static

Definition at line 702 of file check.c.

703 {
704  PGresult *res;
705  PGconn *conn = connectToServer(cluster, "template1");
706 
707  prep_status("Checking for prepared transactions");
708 
710  "SELECT * "
711  "FROM pg_catalog.pg_prepared_xacts");
712 
713  if (PQntuples(res) != 0)
714  {
715  if (cluster == &old_cluster)
716  pg_fatal("The source cluster contains prepared transactions");
717  else
718  pg_fatal("The target cluster contains prepared transactions");
719  }
720 
721  PQclear(res);
722 
723  PQfinish(conn);
724 
725  check_ok();
726 }

References check_ok(), cluster(), conn, connectToServer(), executeQueryOrDie(), old_cluster, pg_fatal, PQclear(), PQfinish(), PQntuples(), prep_status(), and res.

Referenced by check_and_dump_old_cluster(), and check_new_cluster().

◆ check_for_reg_data_type_usage()

static void check_for_reg_data_type_usage ( ClusterInfo cluster)
static

Definition at line 1186 of file check.c.

1187 {
1188  bool found;
1189  char output_path[MAXPGPATH];
1190 
1191  prep_status("Checking for reg* data types in user tables");
1192 
1193  snprintf(output_path, sizeof(output_path), "%s/%s",
1194  log_opts.basedir,
1195  "tables_using_reg.txt");
1196 
1197  /*
1198  * Note: older servers will not have all of these reg* types, so we have
1199  * to write the query like this rather than depending on casts to regtype.
1200  */
1202  "SELECT oid FROM pg_catalog.pg_type t "
1203  "WHERE t.typnamespace = "
1204  " (SELECT oid FROM pg_catalog.pg_namespace "
1205  " WHERE nspname = 'pg_catalog') "
1206  " AND t.typname IN ( "
1207  /* pg_class.oid is preserved, so 'regclass' is OK */
1208  " 'regcollation', "
1209  " 'regconfig', "
1210  " 'regdictionary', "
1211  " 'regnamespace', "
1212  " 'regoper', "
1213  " 'regoperator', "
1214  " 'regproc', "
1215  " 'regprocedure' "
1216  /* pg_authid.oid is preserved, so 'regrole' is OK */
1217  /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
1218  " )",
1219  output_path);
1220 
1221  if (found)
1222  {
1223  pg_log(PG_REPORT, "fatal");
1224  pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
1225  "These data types reference system OIDs that are not preserved by\n"
1226  "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
1227  "drop the problem columns and restart the upgrade.\n"
1228  "A list of the problem columns is in the file:\n"
1229  " %s", output_path);
1230  }
1231  else
1232  check_ok();
1233 }

References LogOpts::basedir, check_for_data_types_usage(), check_ok(), cluster(), log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_removed_data_type_usage()

static void check_for_removed_data_type_usage ( ClusterInfo cluster,
const char *  version,
const char *  datatype 
)
static

Definition at line 1271 of file check.c.

1273 {
1274  char output_path[MAXPGPATH];
1275  char typename[NAMEDATALEN];
1276 
1277  prep_status("Checking for removed \"%s\" data type in user tables",
1278  datatype);
1279 
1280  snprintf(output_path, sizeof(output_path), "tables_using_%s.txt",
1281  datatype);
1282  snprintf(typename, sizeof(typename), "pg_catalog.%s", datatype);
1283 
1284  if (check_for_data_type_usage(cluster, typename, output_path))
1285  {
1286  pg_log(PG_REPORT, "fatal");
1287  pg_fatal("Your installation contains the \"%s\" data type in user tables.\n"
1288  "The \"%s\" type has been removed in PostgreSQL version %s,\n"
1289  "so this cluster cannot currently be upgraded. You can drop the\n"
1290  "problem columns, or change them to another data type, and restart\n"
1291  "the upgrade. A list of the problem columns is in the file:\n"
1292  " %s", datatype, datatype, version, output_path);
1293  }
1294  else
1295  check_ok();
1296 }
#define NAMEDATALEN

References check_for_data_type_usage(), check_ok(), cluster(), MAXPGPATH, NAMEDATALEN, pg_fatal, pg_log(), PG_REPORT, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_tables_with_oids()

static void check_for_tables_with_oids ( ClusterInfo cluster)
static

Definition at line 1045 of file check.c.

1046 {
1047  int dbnum;
1048  FILE *script = NULL;
1049  char output_path[MAXPGPATH];
1050 
1051  prep_status("Checking for tables WITH OIDS");
1052 
1053  snprintf(output_path, sizeof(output_path), "%s/%s",
1054  log_opts.basedir,
1055  "tables_with_oids.txt");
1056 
1057  /* Find any tables declared WITH OIDS */
1058  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1059  {
1060  PGresult *res;
1061  bool db_used = false;
1062  int ntups;
1063  int rowno;
1064  int i_nspname,
1065  i_relname;
1066  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1067  PGconn *conn = connectToServer(cluster, active_db->db_name);
1068 
1070  "SELECT n.nspname, c.relname "
1071  "FROM pg_catalog.pg_class c, "
1072  " pg_catalog.pg_namespace n "
1073  "WHERE c.relnamespace = n.oid AND "
1074  " c.relhasoids AND"
1075  " n.nspname NOT IN ('pg_catalog')");
1076 
1077  ntups = PQntuples(res);
1078  i_nspname = PQfnumber(res, "nspname");
1079  i_relname = PQfnumber(res, "relname");
1080  for (rowno = 0; rowno < ntups; rowno++)
1081  {
1082  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1083  pg_fatal("could not open file \"%s\": %s",
1084  output_path, strerror(errno));
1085  if (!db_used)
1086  {
1087  fprintf(script, "In database: %s\n", active_db->db_name);
1088  db_used = true;
1089  }
1090  fprintf(script, " %s.%s\n",
1091  PQgetvalue(res, rowno, i_nspname),
1092  PQgetvalue(res, rowno, i_relname));
1093  }
1094 
1095  PQclear(res);
1096 
1097  PQfinish(conn);
1098  }
1099 
1100  if (script)
1101  {
1102  fclose(script);
1103  pg_log(PG_REPORT, "fatal");
1104  pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1105  "supported anymore. Consider removing the oid column using\n"
1106  " ALTER TABLE ... SET WITHOUT OIDS;\n"
1107  "A list of tables with the problem is in the file:\n"
1108  " %s", output_path);
1109  }
1110  else
1111  check_ok();
1112 }

References LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_for_user_defined_encoding_conversions()

static void check_for_user_defined_encoding_conversions ( ClusterInfo cluster)
static

Definition at line 1391 of file check.c.

1392 {
1393  int dbnum;
1394  FILE *script = NULL;
1395  char output_path[MAXPGPATH];
1396 
1397  prep_status("Checking for user-defined encoding conversions");
1398 
1399  snprintf(output_path, sizeof(output_path), "%s/%s",
1400  log_opts.basedir,
1401  "encoding_conversions.txt");
1402 
1403  /* Find any user defined encoding conversions */
1404  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1405  {
1406  PGresult *res;
1407  bool db_used = false;
1408  int ntups;
1409  int rowno;
1410  int i_conoid,
1411  i_conname,
1412  i_nspname;
1413  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1414  PGconn *conn = connectToServer(cluster, active_db->db_name);
1415 
1416  /*
1417  * The query below hardcodes FirstNormalObjectId as 16384 rather than
1418  * interpolating that C #define into the query because, if that
1419  * #define is ever changed, the cutoff we want to use is the value
1420  * used by pre-version 14 servers, not that of some future version.
1421  */
1423  "SELECT c.oid as conoid, c.conname, n.nspname "
1424  "FROM pg_catalog.pg_conversion c, "
1425  " pg_catalog.pg_namespace n "
1426  "WHERE c.connamespace = n.oid AND "
1427  " c.oid >= 16384");
1428  ntups = PQntuples(res);
1429  i_conoid = PQfnumber(res, "conoid");
1430  i_conname = PQfnumber(res, "conname");
1431  i_nspname = PQfnumber(res, "nspname");
1432  for (rowno = 0; rowno < ntups; rowno++)
1433  {
1434  if (script == NULL &&
1435  (script = fopen_priv(output_path, "w")) == NULL)
1436  pg_fatal("could not open file \"%s\": %s",
1437  output_path, strerror(errno));
1438  if (!db_used)
1439  {
1440  fprintf(script, "In database: %s\n", active_db->db_name);
1441  db_used = true;
1442  }
1443  fprintf(script, " (oid=%s) %s.%s\n",
1444  PQgetvalue(res, rowno, i_conoid),
1445  PQgetvalue(res, rowno, i_nspname),
1446  PQgetvalue(res, rowno, i_conname));
1447  }
1448 
1449  PQclear(res);
1450 
1451  PQfinish(conn);
1452  }
1453 
1454  if (script)
1455  {
1456  fclose(script);
1457  pg_log(PG_REPORT, "fatal");
1458  pg_fatal("Your installation contains user-defined encoding conversions.\n"
1459  "The conversion function parameters changed in PostgreSQL version 14\n"
1460  "so this cluster cannot currently be upgraded. You can remove the\n"
1461  "encoding conversions in the old cluster and restart the upgrade.\n"
1462  "A list of user-defined encoding conversions is in the file:\n"
1463  " %s", output_path);
1464  }
1465  else
1466  check_ok();
1467 }

References LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_for_user_defined_postfix_ops()

static void check_for_user_defined_postfix_ops ( ClusterInfo cluster)
static

Definition at line 819 of file check.c.

820 {
821  int dbnum;
822  FILE *script = NULL;
823  char output_path[MAXPGPATH];
824 
825  prep_status("Checking for user-defined postfix operators");
826 
827  snprintf(output_path, sizeof(output_path), "%s/%s",
829  "postfix_ops.txt");
830 
831  /* Find any user defined postfix operators */
832  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
833  {
834  PGresult *res;
835  bool db_used = false;
836  int ntups;
837  int rowno;
838  int i_oproid,
839  i_oprnsp,
840  i_oprname,
841  i_typnsp,
842  i_typname;
843  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
844  PGconn *conn = connectToServer(cluster, active_db->db_name);
845 
846  /*
847  * The query below hardcodes FirstNormalObjectId as 16384 rather than
848  * interpolating that C #define into the query because, if that
849  * #define is ever changed, the cutoff we want to use is the value
850  * used by pre-version 14 servers, not that of some future version.
851  */
853  "SELECT o.oid AS oproid, "
854  " n.nspname AS oprnsp, "
855  " o.oprname, "
856  " tn.nspname AS typnsp, "
857  " t.typname "
858  "FROM pg_catalog.pg_operator o, "
859  " pg_catalog.pg_namespace n, "
860  " pg_catalog.pg_type t, "
861  " pg_catalog.pg_namespace tn "
862  "WHERE o.oprnamespace = n.oid AND "
863  " o.oprleft = t.oid AND "
864  " t.typnamespace = tn.oid AND "
865  " o.oprright = 0 AND "
866  " o.oid >= 16384");
867  ntups = PQntuples(res);
868  i_oproid = PQfnumber(res, "oproid");
869  i_oprnsp = PQfnumber(res, "oprnsp");
870  i_oprname = PQfnumber(res, "oprname");
871  i_typnsp = PQfnumber(res, "typnsp");
872  i_typname = PQfnumber(res, "typname");
873  for (rowno = 0; rowno < ntups; rowno++)
874  {
875  if (script == NULL &&
876  (script = fopen_priv(output_path, "w")) == NULL)
877  pg_fatal("could not open file \"%s\": %s",
878  output_path, strerror(errno));
879  if (!db_used)
880  {
881  fprintf(script, "In database: %s\n", active_db->db_name);
882  db_used = true;
883  }
884  fprintf(script, " (oid=%s) %s.%s (%s.%s, NONE)\n",
885  PQgetvalue(res, rowno, i_oproid),
886  PQgetvalue(res, rowno, i_oprnsp),
887  PQgetvalue(res, rowno, i_oprname),
888  PQgetvalue(res, rowno, i_typnsp),
889  PQgetvalue(res, rowno, i_typname));
890  }
891 
892  PQclear(res);
893 
894  PQfinish(conn);
895  }
896 
897  if (script)
898  {
899  fclose(script);
900  pg_log(PG_REPORT, "fatal");
901  pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
902  "supported anymore. Consider dropping the postfix operators and replacing\n"
903  "them with prefix operators or function calls.\n"
904  "A list of user-defined postfix operators is in the file:\n"
905  " %s", output_path);
906  }
907  else
908  check_ok();
909 }

References LogOpts::basedir, check_ok(), cluster(), conn, connectToServer(), DbInfo::db_name, executeQueryOrDie(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), res, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_is_install_user()

static void check_is_install_user ( ClusterInfo cluster)
static

Definition at line 559 of file check.c.

560 {
561  PGresult *res;
562  PGconn *conn = connectToServer(cluster, "template1");
563 
564  prep_status("Checking database user is the install user");
565 
566  /* Can't use pg_authid because only superusers can view it. */
568  "SELECT rolsuper, oid "
569  "FROM pg_catalog.pg_roles "
570  "WHERE rolname = current_user "
571  "AND rolname !~ '^pg_'");
572 
573  /*
574  * We only allow the install user in the new cluster (see comment below)
575  * and we preserve pg_authid.oid, so this must be the install user in the
576  * old cluster too.
577  */
578  if (PQntuples(res) != 1 ||
579  atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
580  pg_fatal("database user \"%s\" is not the install user",
581  os_info.user);
582 
583  PQclear(res);
584 
586  "SELECT COUNT(*) "
587  "FROM pg_catalog.pg_roles "
588  "WHERE rolname !~ '^pg_'");
589 
590  if (PQntuples(res) != 1)
591  pg_fatal("could not determine the number of users");
592 
593  /*
594  * We only allow the install user in the new cluster because other defined
595  * users might match users defined in the old cluster and generate an
596  * error during pg_dump restore.
597  */
598  if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
599  pg_fatal("Only the install user can be defined in the new cluster.");
600 
601  PQclear(res);
602 
603  PQfinish(conn);
604 
605  check_ok();
606 }
#define atooid(x)
Definition: postgres_ext.h:42
char * user
Definition: pg_upgrade.h:341

References atooid, check_ok(), cluster(), conn, connectToServer(), executeQueryOrDie(), new_cluster, os_info, pg_fatal, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), prep_status(), res, and OSInfo::user.

Referenced by check_and_dump_old_cluster(), and check_new_cluster().

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 213 of file check.c.

214 {
216 
218 
220 
221  switch (user_opts.transfer_mode)
222  {
223  case TRANSFER_MODE_CLONE:
225  break;
226  case TRANSFER_MODE_COPY:
227  break;
228  case TRANSFER_MODE_LINK:
229  check_hard_link();
230  break;
231  }
232 
234 
236 
238 
240 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1476
static void check_new_cluster_is_empty(void)
Definition: check.c:375
static void check_for_new_tablespace_dir(void)
Definition: check.c:407
void check_file_clone(void)
Definition: file.c:320
void check_hard_link(void)
Definition: file.c:362
void check_loadable_libraries(void)
Definition: function.c:146
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:255
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:256
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:254
transferMode transfer_mode
Definition: pg_upgrade.h:323

References check_file_clone(), check_for_new_tablespace_dir(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), check_new_cluster_logical_replication_slots(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

◆ check_new_cluster_is_empty()

static void check_new_cluster_is_empty ( void  )
static

Definition at line 375 of file check.c.

376 {
377  int dbnum;
378 
379  for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
380  {
381  int relnum;
382  RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
383 
384  for (relnum = 0; relnum < rel_arr->nrels;
385  relnum++)
386  {
387  /* pg_largeobject and its index should be skipped */
388  if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
389  pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
390  new_cluster.dbarr.dbs[dbnum].db_name,
391  rel_arr->rels[relnum].nspname,
392  rel_arr->rels[relnum].relname);
393  }
394  }
395 }
DbInfoArr dbarr
Definition: pg_upgrade.h:282
DbInfo * dbs
Definition: pg_upgrade.h:214
RelInfoArr rel_arr
Definition: pg_upgrade.h:196
RelInfo * rels
Definition: pg_upgrade.h:149
char * nspname
Definition: pg_upgrade.h:136
char * relname
Definition: pg_upgrade.h:137

References DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, DbInfoArr::ndbs, new_cluster, RelInfoArr::nrels, RelInfo::nspname, pg_fatal, DbInfo::rel_arr, RelInfo::relname, and RelInfoArr::rels.

Referenced by check_new_cluster().

◆ check_new_cluster_logical_replication_slots()

static void check_new_cluster_logical_replication_slots ( void  )
static

Definition at line 1476 of file check.c.

1477 {
1478  PGresult *res;
1479  PGconn *conn;
1480  int nslots_on_old;
1481  int nslots_on_new;
1483  char *wal_level;
1484 
1485  /* Logical slots can be migrated since PG17. */
1487  return;
1488 
1489  nslots_on_old = count_old_cluster_logical_slots();
1490 
1491  /* Quick return if there are no logical slots to be migrated. */
1492  if (nslots_on_old == 0)
1493  return;
1494 
1495  conn = connectToServer(&new_cluster, "template1");
1496 
1497  prep_status("Checking for new cluster logical replication slots");
1498 
1499  res = executeQueryOrDie(conn, "SELECT count(*) "
1500  "FROM pg_catalog.pg_replication_slots "
1501  "WHERE slot_type = 'logical' AND "
1502  "temporary IS FALSE;");
1503 
1504  if (PQntuples(res) != 1)
1505  pg_fatal("could not count the number of logical replication slots");
1506 
1507  nslots_on_new = atoi(PQgetvalue(res, 0, 0));
1508 
1509  if (nslots_on_new)
1510  pg_fatal("Expected 0 logical replication slots but found %d.",
1511  nslots_on_new);
1512 
1513  PQclear(res);
1514 
1515  res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1516  "WHERE name IN ('wal_level', 'max_replication_slots') "
1517  "ORDER BY name DESC;");
1518 
1519  if (PQntuples(res) != 2)
1520  pg_fatal("could not determine parameter settings on new cluster");
1521 
1522  wal_level = PQgetvalue(res, 0, 0);
1523 
1524  if (strcmp(wal_level, "logical") != 0)
1525  pg_fatal("wal_level must be \"logical\", but is set to \"%s\"",
1526  wal_level);
1527 
1528  max_replication_slots = atoi(PQgetvalue(res, 1, 0));
1529 
1530  if (nslots_on_old > max_replication_slots)
1531  pg_fatal("max_replication_slots (%d) must be greater than or equal to the number of "
1532  "logical replication slots (%d) on the old cluster",
1533  max_replication_slots, nslots_on_old);
1534 
1535  PQclear(res);
1536  PQfinish(conn);
1537 
1538  check_ok();
1539 }
int count_old_cluster_logical_slots(void)
Definition: info.c:723
int max_replication_slots
Definition: slot.c:102
int wal_level
Definition: xlog.c:134

References check_ok(), conn, connectToServer(), count_old_cluster_logical_slots(), executeQueryOrDie(), GET_MAJOR_VERSION, ClusterInfo::major_version, max_replication_slots, new_cluster, old_cluster, pg_fatal, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), prep_status(), res, and wal_level.

Referenced by check_new_cluster().

◆ check_old_cluster_for_valid_slots()

static void check_old_cluster_for_valid_slots ( bool  live_check)
static

Definition at line 1548 of file check.c.

1549 {
1550  char output_path[MAXPGPATH];
1551  FILE *script = NULL;
1552 
1553  prep_status("Checking for valid logical replication slots");
1554 
1555  snprintf(output_path, sizeof(output_path), "%s/%s",
1556  log_opts.basedir,
1557  "invalid_logical_slots.txt");
1558 
1559  for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1560  {
1561  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
1562 
1563  for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
1564  {
1565  LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
1566 
1567  /* Is the slot usable? */
1568  if (slot->invalid)
1569  {
1570  if (script == NULL &&
1571  (script = fopen_priv(output_path, "w")) == NULL)
1572  pg_fatal("could not open file \"%s\": %s",
1573  output_path, strerror(errno));
1574 
1575  fprintf(script, "The slot \"%s\" is invalid\n",
1576  slot->slotname);
1577 
1578  continue;
1579  }
1580 
1581  /*
1582  * Do additional check to ensure that all logical replication
1583  * slots have consumed all the WAL before shutdown.
1584  *
1585  * Note: This can be satisfied only when the old cluster has been
1586  * shut down, so we skip this for live checks.
1587  */
1588  if (!live_check && !slot->caught_up)
1589  {
1590  if (script == NULL &&
1591  (script = fopen_priv(output_path, "w")) == NULL)
1592  pg_fatal("could not open file \"%s\": %s",
1593  output_path, strerror(errno));
1594 
1595  fprintf(script,
1596  "The slot \"%s\" has not consumed the WAL yet\n",
1597  slot->slotname);
1598  }
1599  }
1600  }
1601 
1602  if (script)
1603  {
1604  fclose(script);
1605 
1606  pg_log(PG_REPORT, "fatal");
1607  pg_fatal("Your installation contains logical replication slots that can't be upgraded.\n"
1608  "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
1609  "and then restart the upgrade.\n"
1610  "A list of the problematic slots is in the file:\n"
1611  " %s", output_path);
1612  }
1613 
1614  check_ok();
1615 }
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:197
LogicalSlotInfo * slots
Definition: pg_upgrade.h:168

References LogOpts::basedir, LogicalSlotInfo::caught_up, check_ok(), ClusterInfo::dbarr, DbInfoArr::dbs, fopen_priv, fprintf, LogicalSlotInfo::invalid, log_opts, MAXPGPATH, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, old_cluster, pg_fatal, pg_log(), PG_REPORT, prep_status(), DbInfo::slot_arr, LogicalSlotInfo::slotname, LogicalSlotInfoArr::slots, snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ check_proper_datallowconn()

static void check_proper_datallowconn ( ClusterInfo cluster)
static

Definition at line 617 of file check.c.

618 {
619  int dbnum;
620  PGconn *conn_template1;
621  PGresult *dbres;
622  int ntups;
623  int i_datname;
624  int i_datallowconn;
625  FILE *script = NULL;
626  char output_path[MAXPGPATH];
627 
628  prep_status("Checking database connection settings");
629 
630  snprintf(output_path, sizeof(output_path), "%s/%s",
632  "databases_with_datallowconn_false.txt");
633 
634  conn_template1 = connectToServer(cluster, "template1");
635 
636  /* get database names */
637  dbres = executeQueryOrDie(conn_template1,
638  "SELECT datname, datallowconn "
639  "FROM pg_catalog.pg_database");
640 
641  i_datname = PQfnumber(dbres, "datname");
642  i_datallowconn = PQfnumber(dbres, "datallowconn");
643 
644  ntups = PQntuples(dbres);
645  for (dbnum = 0; dbnum < ntups; dbnum++)
646  {
647  char *datname = PQgetvalue(dbres, dbnum, i_datname);
648  char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
649 
650  if (strcmp(datname, "template0") == 0)
651  {
652  /* avoid restore failure when pg_dumpall tries to create template0 */
653  if (strcmp(datallowconn, "t") == 0)
654  pg_fatal("template0 must not allow connections, "
655  "i.e. its pg_database.datallowconn must be false");
656  }
657  else
658  {
659  /*
660  * avoid datallowconn == false databases from being skipped on
661  * restore
662  */
663  if (strcmp(datallowconn, "f") == 0)
664  {
665  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
666  pg_fatal("could not open file \"%s\": %s",
667  output_path, strerror(errno));
668 
669  fprintf(script, "%s\n", datname);
670  }
671  }
672  }
673 
674  PQclear(dbres);
675 
676  PQfinish(conn_template1);
677 
678  if (script)
679  {
680  fclose(script);
681  pg_log(PG_REPORT, "fatal");
682  pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
683  "pg_database.datallowconn must be true. Your installation contains\n"
684  "non-template0 databases with their pg_database.datallowconn set to\n"
685  "false. Consider allowing connection for all non-template0 databases\n"
686  "or drop the databases which do not allow connections. A list of\n"
687  "databases with the problem is in the file:\n"
688  " %s", output_path);
689  }
690  else
691  check_ok();
692 }
NameData datname
Definition: pg_database.h:35
bool datallowconn
Definition: pg_database.h:50

References LogOpts::basedir, check_ok(), cluster(), connectToServer(), datallowconn, datname, executeQueryOrDie(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), snprintf, and strerror.

Referenced by check_and_dump_old_cluster().

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 436 of file check.c.

437 {
438  FILE *script = NULL;
439  int tblnum;
440  char old_cluster_pgdata[MAXPGPATH],
441  new_cluster_pgdata[MAXPGPATH];
442 
443  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
445 
446  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
447  canonicalize_path(old_cluster_pgdata);
448 
449  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
450  canonicalize_path(new_cluster_pgdata);
451 
452  /* Some people put the new data directory inside the old one. */
453  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
454  {
456  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
457 
458  /* Unlink file in case it is left over from a previous run. */
459  unlink(*deletion_script_file_name);
460  pg_free(*deletion_script_file_name);
461  *deletion_script_file_name = NULL;
462  return;
463  }
464 
465  /*
466  * Some users (oddly) create tablespaces inside the cluster data
467  * directory. We can't create a proper old cluster delete script in that
468  * case.
469  */
470  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
471  {
472  char old_tablespace_dir[MAXPGPATH];
473 
474  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
475  canonicalize_path(old_tablespace_dir);
476  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
477  {
478  /* reproduce warning from CREATE TABLESPACE that is in the log */
480  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
481 
482  /* Unlink file in case it is left over from a previous run. */
483  unlink(*deletion_script_file_name);
484  pg_free(*deletion_script_file_name);
485  *deletion_script_file_name = NULL;
486  return;
487  }
488  }
489 
490  prep_status("Creating script to delete old cluster");
491 
492  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
493  pg_fatal("could not open file \"%s\": %s",
494  *deletion_script_file_name, strerror(errno));
495 
496 #ifndef WIN32
497  /* add shebang header */
498  fprintf(script, "#!/bin/sh\n\n");
499 #endif
500 
501  /* delete old cluster's default tablespace */
502  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
504 
505  /* delete old cluster's alternate tablespaces */
506  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
507  {
508  /*
509  * Do the old cluster's per-database directories share a directory
510  * with a new version-specific tablespace?
511  */
512  if (strlen(old_cluster.tablespace_suffix) == 0)
513  {
514  /* delete per-database directories */
515  int dbnum;
516 
517  fprintf(script, "\n");
518 
519  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
520  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
523  PATH_QUOTE);
524  }
525  else
526  {
527  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
528 
529  /*
530  * Simply delete the tablespace directory, which might be ".old"
531  * or a version-specific subdirectory.
532  */
533  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
535  fix_path_separator(suffix_path), PATH_QUOTE);
536  pfree(suffix_path);
537  }
538  }
539 
540  fclose(script);
541 
542 #ifndef WIN32
543  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
544  pg_fatal("could not add execute permission to file \"%s\": %s",
545  *deletion_script_file_name, strerror(errno));
546 #endif
547 
548  check_ok();
549 }
static char * fix_path_separator(char *path)
Definition: check.c:48
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void pfree(void *pointer)
Definition: mcxt.c:1456
#define PATH_SEPARATOR
Definition: pg_upgrade.h:82
#define RMDIR_CMD
Definition: pg_upgrade.h:85
#define SCRIPT_EXT
Definition: pg_upgrade.h:87
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:86
#define PATH_QUOTE
Definition: pg_upgrade.h:83
@ PG_WARNING
Definition: pg_upgrade.h:268
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:559
void canonicalize_path(char *path)
Definition: path.c:264
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * pgdata
Definition: pg_upgrade.h:283
Oid db_oid
Definition: pg_upgrade.h:192
#define S_IRWXU
Definition: win32_port.h:298

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, DbInfoArr::ndbs, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, PATH_SEPARATOR, pfree(), pg_fatal, pg_free(), pg_log(), pg_strdup(), PG_WARNING, ClusterInfo::pgdata, prep_status(), psprintf(), RMDIR_CMD, S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, strerror, strlcpy(), and ClusterInfo::tablespace_suffix.

Referenced by main().

◆ fix_path_separator()

static char* fix_path_separator ( char *  path)
static

Definition at line 48 of file check.c.

49 {
50 #ifdef WIN32
51 
52  char *result;
53  char *c;
54 
55  result = pg_strdup(path);
56 
57  for (c = result; *c != '\0'; c++)
58  if (*c == '/')
59  *c = '\\';
60 
61  return result;
62 #else
63 
64  return path;
65 #endif
66 }
char * c

References pg_strdup().

Referenced by create_script_for_old_cluster_deletion().

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 263 of file check.c.

264 {
265  /*
266  * We unconditionally start/stop the new server because pg_resetwal -o set
267  * wal_level to 'minimum'. If the user is upgrading standby servers using
268  * the rsync instructions, they will need pg_upgrade to write its final
269  * WAL record showing wal_level as 'replica'.
270  */
272 
273  /* Reindex hash indexes for old < 10.0 */
276 
278 
279  stop_postmaster(false);
280 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:396

References GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_9_6_invalidate_hash_indexes(), old_cluster, report_extension_updates(), start_postmaster(), and stop_postmaster().

Referenced by main().

◆ output_check_banner()

void output_check_banner ( bool  live_check)

Definition at line 69 of file check.c.

70 {
71  if (user_opts.check && live_check)
72  {
74  "Performing Consistency Checks on Old Live Server\n"
75  "------------------------------------------------");
76  }
77  else
78  {
80  "Performing Consistency Checks\n"
81  "-----------------------------");
82  }
83 }

References UserOpts::check, pg_log(), PG_REPORT, and user_opts.

Referenced by main().

◆ output_completion_banner()

void output_completion_banner ( char *  deletion_script_file_name)

Definition at line 284 of file check.c.

285 {
286  PQExpBufferData user_specification;
287 
288  initPQExpBuffer(&user_specification);
290  {
291  appendPQExpBufferStr(&user_specification, "-U ");
292  appendShellString(&user_specification, os_info.user);
293  appendPQExpBufferChar(&user_specification, ' ');
294  }
295 
297  "Optimizer statistics are not transferred by pg_upgrade.\n"
298  "Once you start the new server, consider running:\n"
299  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
300 
301  if (deletion_script_file_name)
303  "Running this script will delete the old cluster's data files:\n"
304  " %s",
305  deletion_script_file_name);
306  else
308  "Could not create a script to delete the old cluster's data files\n"
309  "because user-defined tablespaces or the new cluster's data directory\n"
310  "exist in the old cluster directory. The old cluster's contents must\n"
311  "be deleted manually.");
312 
313  termPQExpBuffer(&user_specification);
314 }
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
char * bindir
Definition: pg_upgrade.h:286
bool user_specified
Definition: pg_upgrade.h:342

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, PQExpBufferData::data, initPQExpBuffer(), new_cluster, os_info, pg_log(), PG_REPORT, termPQExpBuffer(), OSInfo::user, and OSInfo::user_specified.

Referenced by main().

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 244 of file check.c.

245 {
246  if (user_opts.check)
247  {
248  pg_log(PG_REPORT, "\n*Clusters are compatible*");
249  /* stops new cluster */
250  stop_postmaster(false);
251 
253  exit(0);
254  }
255 
256  pg_log(PG_REPORT, "\n"
257  "If pg_upgrade fails after this point, you must re-initdb the\n"
258  "new cluster before continuing.");
259 }
exit(1)
void cleanup_output_dirs(void)
Definition: util.c:63

References UserOpts::check, cleanup_output_dirs(), exit(), pg_log(), PG_REPORT, stop_postmaster(), and user_opts.

Referenced by main().