PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
check.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_authid_d.h"
#include "catalog/pg_class_d.h"
#include "fe_utils/string_utils.h"
#include "pg_upgrade.h"
Include dependency graph for check.c:

Go to the source code of this file.

Data Structures

struct  DataTypesUsageChecks
 
struct  data_type_check_state
 

Macros

#define MANUAL_CHECK   1
 
#define ALL_VERSIONS   -1
 

Functions

static void check_new_cluster_is_empty (void)
 
static void check_is_install_user (ClusterInfo *cluster)
 
static void check_for_connection_status (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_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_new_cluster_subscription_configuration (void)
 
static void check_old_cluster_for_valid_slots (void)
 
static void check_old_cluster_subscription_state (void)
 
static char * data_type_check_query (int checknum)
 
static void process_data_type_check (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void check_for_data_types_usage (ClusterInfo *cluster)
 
static char * fix_path_separator (char *path)
 
void output_check_banner (void)
 
void check_and_dump_old_cluster (void)
 
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 (void)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 
static void process_isn_and_int8_passing_mismatch (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_user_defined_postfix_ops (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_incompat_polymorphics (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_with_oids_check (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_user_defined_encoding_conversions (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_old_sub_state_check (DbInfo *dbinfo, PGresult *res, void *arg)
 

Variables

static DataTypesUsageChecks data_types_usage_checks []
 

Macro Definition Documentation

◆ ALL_VERSIONS

#define ALL_VERSIONS   -1

Definition at line 60 of file check.c.

◆ MANUAL_CHECK

#define MANUAL_CHECK   1

Definition at line 59 of file check.c.

Function Documentation

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 586 of file check.c.

587 {
588  /* -- OLD -- */
589 
590  if (!user_opts.live_check)
592 
593  /*
594  * First check that all databases allow connections since we'll otherwise
595  * fail in later stages.
596  */
598 
599  /*
600  * Extract a list of databases, tables, and logical replication slots from
601  * the old cluster.
602  */
604 
606 
608 
609 
610  /*
611  * Check for various failure cases
612  */
616 
618  {
619  /*
620  * Logical replication slots can be migrated since PG17. See comments
621  * atop get_old_cluster_logical_slot_infos().
622  */
624 
625  /*
626  * Subscriptions and their dependencies can be migrated since PG17.
627  * Before that the logical slots are not upgraded, so we will not be
628  * able to upgrade the logical replication clusters completely.
629  */
632  }
633 
635 
636  /*
637  * PG 14 changed the function signature of encoding conversion functions.
638  * Conversions from older versions cannot be upgraded automatically
639  * because the user-defined functions used by the encoding conversions
640  * need to be changed to match the new signature.
641  */
644 
645  /*
646  * Pre-PG 14 allowed user defined postfix operators, which are not
647  * supported anymore. Verify there are none, iff applicable.
648  */
651 
652  /*
653  * PG 14 changed polymorphic functions from anyarray to
654  * anycompatiblearray.
655  */
658 
659  /*
660  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
661  * supported anymore. Verify there are none, iff applicable.
662  */
665 
666  /*
667  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
668  * hash indexes
669  */
671  {
672  if (user_opts.check)
674  }
675 
676  /* 9.5 and below should not have roles starting with pg_ */
679 
680  /*
681  * While not a check option, we do this now because this is the only time
682  * the old server is running.
683  */
684  if (!user_opts.check)
686 
687  if (!user_opts.live_check)
688  stop_postmaster(false);
689 }
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1564
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1608
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:461
static void check_old_cluster_subscription_state(void)
Definition: check.c:1974
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1044
static void check_for_connection_status(ClusterInfo *cluster)
Definition: check.c:1102
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1256
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:1866
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1344
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1190
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1697
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1435
void generate_old_dump(void)
Definition: dump.c:16
void get_loadable_libraries(void)
Definition: function.c:79
void get_subscription_count(ClusterInfo *cluster)
Definition: info.c:758
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition: info.c:280
static pid_t start_postmaster(void)
Definition: pg_ctl.c:440
ClusterInfo old_cluster
Definition: pg_upgrade.c:67
void init_tablespaces(void)
Definition: tablespace.c:19
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:342
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:37
UserOpts user_opts
Definition: option.c:30
uint32 major_version
Definition: pg_upgrade.h:293
bool live_check
Definition: pg_upgrade.h:324
bool check
Definition: pg_upgrade.h:323

References UserOpts::check, check_for_connection_status(), check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), 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_old_cluster_subscription_state(), generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_subscription_count(), init_tablespaces(), UserOpts::live_check, ClusterInfo::major_version, 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 ( void  )

Definition at line 846 of file check.c.

847 {
848  /* get/check pg_control data of servers */
852 
854  pg_fatal("When checking a live server, "
855  "the old and new port numbers must be different.");
856 }
void get_control_data(ClusterInfo *cluster)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:655
#define pg_fatal(...)
ClusterInfo new_cluster
Definition: pg_upgrade.c:68
unsigned short port
Definition: pg_upgrade.h:292
ControlData controldata
Definition: pg_upgrade.h:282

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

Referenced by main().

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 803 of file check.c.

804 {
805  prep_status("Checking cluster versions");
806 
807  /* cluster versions should already have been obtained */
810 
811  /*
812  * We allow upgrades from/to the same major version for alpha/beta
813  * upgrades
814  */
815 
817  pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
818  "9.2");
819 
820  /* Only current PG version is supported as a target */
822  pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
823  PG_MAJORVERSION);
824 
825  /*
826  * We can't allow downgrading because we use the target pg_dump, and
827  * pg_dump cannot operate on newer database versions, only current and
828  * older versions.
829  */
831  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
832 
833  /* Ensure binaries match the designated data directories */
836  pg_fatal("Old cluster data and binary directories are from different major versions.");
839  pg_fatal("New cluster data and binary directories are from different major versions.");
840 
841  check_ok();
842 }
#define Assert(condition)
Definition: c.h:837
static void check_ok(void)
Definition: initdb.c:2091
void prep_status(const char *fmt,...) pg_attribute_printf(1
uint32 bin_version
Definition: pg_upgrade.h:295

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_connection_status()

static void check_for_connection_status ( ClusterInfo cluster)
static

Definition at line 1102 of file check.c.

1103 {
1104  int dbnum;
1105  PGconn *conn_template1;
1106  PGresult *dbres;
1107  int ntups;
1108  int i_datname;
1109  int i_datallowconn;
1110  int i_datconnlimit;
1111  FILE *script = NULL;
1112  char output_path[MAXPGPATH];
1113 
1114  prep_status("Checking database connection settings");
1115 
1116  snprintf(output_path, sizeof(output_path), "%s/%s",
1117  log_opts.basedir,
1118  "databases_cannot_connect_to.txt");
1119 
1120  conn_template1 = connectToServer(cluster, "template1");
1121 
1122  /* get database names */
1123  dbres = executeQueryOrDie(conn_template1,
1124  "SELECT datname, datallowconn, datconnlimit "
1125  "FROM pg_catalog.pg_database");
1126 
1127  i_datname = PQfnumber(dbres, "datname");
1128  i_datallowconn = PQfnumber(dbres, "datallowconn");
1129  i_datconnlimit = PQfnumber(dbres, "datconnlimit");
1130 
1131  ntups = PQntuples(dbres);
1132  for (dbnum = 0; dbnum < ntups; dbnum++)
1133  {
1134  char *datname = PQgetvalue(dbres, dbnum, i_datname);
1135  char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
1136  char *datconnlimit = PQgetvalue(dbres, dbnum, i_datconnlimit);
1137 
1138  if (strcmp(datname, "template0") == 0)
1139  {
1140  /* avoid restore failure when pg_dumpall tries to create template0 */
1141  if (strcmp(datallowconn, "t") == 0)
1142  pg_fatal("template0 must not allow connections, "
1143  "i.e. its pg_database.datallowconn must be false");
1144  }
1145  else
1146  {
1147  /*
1148  * Avoid datallowconn == false databases from being skipped on
1149  * restore, and ensure that no databases are marked invalid with
1150  * datconnlimit == -2.
1151  */
1152  if ((strcmp(datallowconn, "f") == 0) || strcmp(datconnlimit, "-2") == 0)
1153  {
1154  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1155  pg_fatal("could not open file \"%s\": %m", output_path);
1156 
1157  fprintf(script, "%s\n", datname);
1158  }
1159  }
1160  }
1161 
1162  PQclear(dbres);
1163 
1164  PQfinish(conn_template1);
1165 
1166  if (script)
1167  {
1168  fclose(script);
1169  pg_log(PG_REPORT, "fatal");
1170  pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
1171  "pg_database.datallowconn must be true and pg_database.datconnlimit\n"
1172  "must not be -2. Your installation contains non-template0 databases\n"
1173  "which cannot be connected to. Consider allowing connection for all\n"
1174  "non-template0 databases or drop the databases which do not allow\n"
1175  "connections. A list of databases with the problem is in the file:\n"
1176  " %s", output_path);
1177  }
1178  else
1179  check_ok();
1180 }
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:107
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4879
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3589
#define MAXPGPATH
NameData datname
Definition: pg_database.h:35
bool datallowconn
Definition: pg_database.h:50
int32 datconnlimit
Definition: pg_database.h:59
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition: util.c:17
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:419
@ PG_REPORT
Definition: pg_upgrade.h:269
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define snprintf
Definition: port.h:238
#define fprintf
Definition: port.h:242
char * basedir
Definition: pg_upgrade.h:311

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

Referenced by check_and_dump_old_cluster().

◆ check_for_data_types_usage()

static void check_for_data_types_usage ( ClusterInfo cluster)
static

Definition at line 461 of file check.c.

462 {
463  PQExpBuffer report = NULL;
465  int n_data_types_usage_checks = 0;
467  char **queries = NULL;
468  struct data_type_check_state *states;
469 
470  prep_status("Checking data type usage");
471 
472  /* Gather number of checks to perform */
473  while (tmp->status != NULL)
474  {
475  n_data_types_usage_checks++;
476  tmp++;
477  }
478 
479  /* Allocate memory for queries and for task states */
480  queries = pg_malloc0(sizeof(char *) * n_data_types_usage_checks);
481  states = pg_malloc0(sizeof(struct data_type_check_state) * n_data_types_usage_checks);
482 
483  for (int i = 0; i < n_data_types_usage_checks; i++)
484  {
486 
488  {
490 
491  /*
492  * Make sure that the check applies to the current cluster version
493  * and skip it if not.
494  */
495  if (!check->version_hook(cluster))
496  continue;
497  }
498  else if (check->threshold_version != ALL_VERSIONS)
499  {
500  if (GET_MAJOR_VERSION(cluster->major_version) > check->threshold_version)
501  continue;
502  }
503  else
505 
506  queries[i] = data_type_check_query(i);
507 
508  states[i].check = check;
509  states[i].report = &report;
510 
512  true, &states[i]);
513  }
514 
515  /*
516  * Connect to each database in the cluster and run all defined checks
517  * against that database before trying the next one.
518  */
519  upgrade_task_run(task, cluster);
520  upgrade_task_free(task);
521 
522  if (report)
523  {
524  pg_fatal("Data type checks failed: %s", report->data);
526  }
527 
528  for (int i = 0; i < n_data_types_usage_checks; i++)
529  {
530  if (queries[i])
531  pg_free(queries[i]);
532  }
533  pg_free(queries);
534  pg_free(states);
535 
536  check_ok();
537 }
static DataTypesUsageChecks data_types_usage_checks[]
Definition: check.c:95
#define ALL_VERSIONS
Definition: check.c:60
#define MANUAL_CHECK
Definition: check.c:59
static void process_data_type_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:387
static char * data_type_check_query(int checknum)
Definition: check.c:330
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: isn.c:72
UpgradeTask * upgrade_task_create(void)
Definition: task.c:117
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition: task.c:420
void upgrade_task_free(UpgradeTask *task)
Definition: task.c:133
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition: task.c:151
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:114
int threshold_version
Definition: check.c:49
DataTypesUsageVersionCheck version_hook
Definition: check.c:51
const char * status
Definition: check.c:41
PQExpBuffer * report
Definition: check.c:322
DataTypesUsageChecks * check
Definition: check.c:320

References ALL_VERSIONS, Assert, data_type_check_state::check, check_ok(), cluster(), PQExpBufferData::data, data_type_check_query(), data_types_usage_checks, destroyPQExpBuffer(), GET_MAJOR_VERSION, i, MANUAL_CHECK, pg_fatal, pg_free(), pg_malloc0(), prep_status(), process_data_type_check(), data_type_check_state::report, DataTypesUsageChecks::status, DataTypesUsageChecks::threshold_version, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), upgrade_task_run(), and DataTypesUsageChecks::version_hook.

Referenced by check_and_dump_old_cluster().

◆ check_for_incompatible_polymorphics()

static void check_for_incompatible_polymorphics ( ClusterInfo cluster)
static

Definition at line 1435 of file check.c.

1436 {
1437  PQExpBufferData old_polymorphics;
1438  UpgradeTask *task = upgrade_task_create();
1439  UpgradeTaskReport report;
1440  char *query;
1441 
1442  prep_status("Checking for incompatible polymorphic functions");
1443 
1444  report.file = NULL;
1445  snprintf(report.path, sizeof(report.path), "%s/%s",
1446  log_opts.basedir,
1447  "incompatible_polymorphics.txt");
1448 
1449  /* The set of problematic functions varies a bit in different versions */
1450  initPQExpBuffer(&old_polymorphics);
1451 
1452  appendPQExpBufferStr(&old_polymorphics,
1453  "'array_append(anyarray,anyelement)'"
1454  ", 'array_cat(anyarray,anyarray)'"
1455  ", 'array_prepend(anyelement,anyarray)'");
1456 
1457  if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
1458  appendPQExpBufferStr(&old_polymorphics,
1459  ", 'array_remove(anyarray,anyelement)'"
1460  ", 'array_replace(anyarray,anyelement,anyelement)'");
1461 
1462  if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
1463  appendPQExpBufferStr(&old_polymorphics,
1464  ", 'array_position(anyarray,anyelement)'"
1465  ", 'array_position(anyarray,anyelement,integer)'"
1466  ", 'array_positions(anyarray,anyelement)'"
1467  ", 'width_bucket(anyelement,anyarray)'");
1468 
1469  /*
1470  * The query below hardcodes FirstNormalObjectId as 16384 rather than
1471  * interpolating that C #define into the query because, if that #define is
1472  * ever changed, the cutoff we want to use is the value used by
1473  * pre-version 14 servers, not that of some future version.
1474  */
1475 
1476  /* Aggregate transition functions */
1477  query = psprintf("SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1478  "FROM pg_proc AS p "
1479  "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1480  "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1481  "WHERE p.oid >= 16384 "
1482  "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1483  "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1484 
1485  /* Aggregate final functions */
1486  "UNION ALL "
1487  "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1488  "FROM pg_proc AS p "
1489  "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1490  "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1491  "WHERE p.oid >= 16384 "
1492  "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1493  "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1494 
1495  /* Operators */
1496  "UNION ALL "
1497  "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1498  "FROM pg_operator AS op "
1499  "WHERE op.oid >= 16384 "
1500  "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
1501  "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[])",
1502  old_polymorphics.data,
1503  old_polymorphics.data,
1504  old_polymorphics.data);
1505 
1507  true, &report);
1508  upgrade_task_run(task, cluster);
1509  upgrade_task_free(task);
1510 
1511  if (report.file)
1512  {
1513  fclose(report.file);
1514  pg_log(PG_REPORT, "fatal");
1515  pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1516  "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1517  "These user-defined objects must be dropped before upgrading and restored\n"
1518  "afterwards, changing them to refer to the new corresponding functions with\n"
1519  "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1520  "A list of the problematic objects is in the file:\n"
1521  " %s", report.path);
1522  }
1523  else
1524  check_ok();
1525 
1526  termPQExpBuffer(&old_polymorphics);
1527  pg_free(query);
1528 }
static void process_incompat_polymorphics(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1403
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
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
char path[MAXPGPATH]
Definition: pg_upgrade.h:516

References appendPQExpBufferStr(), LogOpts::basedir, check_ok(), cluster(), PQExpBufferData::data, UpgradeTaskReport::file, GET_MAJOR_VERSION, initPQExpBuffer(), log_opts, UpgradeTaskReport::path, pg_fatal, pg_free(), pg_log(), PG_REPORT, prep_status(), process_incompat_polymorphics(), psprintf(), snprintf, termPQExpBuffer(), upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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 1256 of file check.c.

1257 {
1258  UpgradeTask *task;
1259  UpgradeTaskReport report;
1260  const char *query = "SELECT n.nspname, p.proname "
1261  "FROM pg_catalog.pg_proc p, "
1262  " pg_catalog.pg_namespace n "
1263  "WHERE p.pronamespace = n.oid AND "
1264  " p.probin = '$libdir/isn'";
1265 
1266  prep_status("Checking for contrib/isn with bigint-passing mismatch");
1267 
1270  {
1271  /* no mismatch */
1272  check_ok();
1273  return;
1274  }
1275 
1276  report.file = NULL;
1277  snprintf(report.path, sizeof(report.path), "%s/%s",
1278  log_opts.basedir,
1279  "contrib_isn_and_int8_pass_by_value.txt");
1280 
1281  task = upgrade_task_create();
1283  true, &report);
1284  upgrade_task_run(task, cluster);
1285  upgrade_task_free(task);
1286 
1287  if (report.file)
1288  {
1289  fclose(report.file);
1290  pg_log(PG_REPORT, "fatal");
1291  pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
1292  "bigint data type. Your old and new clusters pass bigint values\n"
1293  "differently so this cluster cannot currently be upgraded. You can\n"
1294  "manually dump databases in the old cluster that use \"contrib/isn\"\n"
1295  "facilities, drop them, perform the upgrade, and then restore them. A\n"
1296  "list of the problem functions is in the file:\n"
1297  " %s", report.path);
1298  }
1299  else
1300  check_ok();
1301 }
static void process_isn_and_int8_passing_mismatch(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1223
bool float8_pass_by_value
Definition: pg_upgrade.h:246

References LogOpts::basedir, check_ok(), cluster(), ClusterInfo::controldata, UpgradeTaskReport::file, ControlData::float8_pass_by_value, log_opts, new_cluster, old_cluster, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, prep_status(), process_isn_and_int8_passing_mismatch(), snprintf, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

Referenced by check_and_dump_old_cluster().

◆ check_for_new_tablespace_dir()

static void check_for_new_tablespace_dir ( void  )
static

Definition at line 892 of file check.c.

893 {
894  int tblnum;
895  char new_tablespace_dir[MAXPGPATH];
896 
897  prep_status("Checking for new cluster tablespace directories");
898 
899  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
900  {
901  struct stat statbuf;
902 
903  snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
904  os_info.old_tablespaces[tblnum],
906 
907  if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
908  pg_fatal("new cluster tablespace directory already exists: \"%s\"",
909  new_tablespace_dir);
910  }
911 
912  check_ok();
913 }
OSInfo os_info
Definition: pg_upgrade.c:69
const char * tablespace_suffix
Definition: pg_upgrade.h:296
int num_old_tablespaces
Definition: pg_upgrade.h:347
char ** old_tablespaces
Definition: pg_upgrade.h:346
#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 1608 of file check.c.

1609 {
1610  PGresult *res;
1611  PGconn *conn = connectToServer(cluster, "template1");
1612  int ntups;
1613  int i_roloid;
1614  int i_rolname;
1615  FILE *script = NULL;
1616  char output_path[MAXPGPATH];
1617 
1618  prep_status("Checking for roles starting with \"pg_\"");
1619 
1620  snprintf(output_path, sizeof(output_path), "%s/%s",
1621  log_opts.basedir,
1622  "pg_role_prefix.txt");
1623 
1625  "SELECT oid AS roloid, rolname "
1626  "FROM pg_catalog.pg_roles "
1627  "WHERE rolname ~ '^pg_'");
1628 
1629  ntups = PQntuples(res);
1630  i_roloid = PQfnumber(res, "roloid");
1631  i_rolname = PQfnumber(res, "rolname");
1632  for (int rowno = 0; rowno < ntups; rowno++)
1633  {
1634  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1635  pg_fatal("could not open file \"%s\": %m", output_path);
1636  fprintf(script, "%s (oid=%s)\n",
1637  PQgetvalue(res, rowno, i_rolname),
1638  PQgetvalue(res, rowno, i_roloid));
1639  }
1640 
1641  PQclear(res);
1642 
1643  PQfinish(conn);
1644 
1645  if (script)
1646  {
1647  fclose(script);
1648  pg_log(PG_REPORT, "fatal");
1649  pg_fatal("Your installation contains roles starting with \"pg_\".\n"
1650  "\"pg_\" is a reserved prefix for system roles. The cluster\n"
1651  "cannot be upgraded until these roles are renamed.\n"
1652  "A list of roles starting with \"pg_\" is in the file:\n"
1653  " %s", output_path);
1654  }
1655  else
1656  check_ok();
1657 }
PGconn * conn
Definition: streamutil.c:53

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, and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_for_prepared_transactions()

static void check_for_prepared_transactions ( ClusterInfo cluster)
static

Definition at line 1190 of file check.c.

1191 {
1192  PGresult *res;
1193  PGconn *conn = connectToServer(cluster, "template1");
1194 
1195  prep_status("Checking for prepared transactions");
1196 
1198  "SELECT * "
1199  "FROM pg_catalog.pg_prepared_xacts");
1200 
1201  if (PQntuples(res) != 0)
1202  {
1203  if (cluster == &old_cluster)
1204  pg_fatal("The source cluster contains prepared transactions");
1205  else
1206  pg_fatal("The target cluster contains prepared transactions");
1207  }
1208 
1209  PQclear(res);
1210 
1211  PQfinish(conn);
1212 
1213  check_ok();
1214 }

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_tables_with_oids()

static void check_for_tables_with_oids ( ClusterInfo cluster)
static

Definition at line 1564 of file check.c.

1565 {
1566  UpgradeTaskReport report;
1567  UpgradeTask *task = upgrade_task_create();
1568  const char *query = "SELECT n.nspname, c.relname "
1569  "FROM pg_catalog.pg_class c, "
1570  " pg_catalog.pg_namespace n "
1571  "WHERE c.relnamespace = n.oid AND "
1572  " c.relhasoids AND"
1573  " n.nspname NOT IN ('pg_catalog')";
1574 
1575  prep_status("Checking for tables WITH OIDS");
1576 
1577  report.file = NULL;
1578  snprintf(report.path, sizeof(report.path), "%s/%s",
1579  log_opts.basedir,
1580  "tables_with_oids.txt");
1581 
1583  true, &report);
1584  upgrade_task_run(task, cluster);
1585  upgrade_task_free(task);
1586 
1587  if (report.file)
1588  {
1589  fclose(report.file);
1590  pg_log(PG_REPORT, "fatal");
1591  pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1592  "supported anymore. Consider removing the oid column using\n"
1593  " ALTER TABLE ... SET WITHOUT OIDS;\n"
1594  "A list of tables with the problem is in the file:\n"
1595  " %s", report.path);
1596  }
1597  else
1598  check_ok();
1599 }
static void process_with_oids_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1536

References LogOpts::basedir, check_ok(), cluster(), UpgradeTaskReport::file, log_opts, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, prep_status(), process_with_oids_check(), snprintf, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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 1697 of file check.c.

1698 {
1699  UpgradeTaskReport report;
1700  UpgradeTask *task = upgrade_task_create();
1701  const char *query;
1702 
1703  prep_status("Checking for user-defined encoding conversions");
1704 
1705  report.file = NULL;
1706  snprintf(report.path, sizeof(report.path), "%s/%s",
1707  log_opts.basedir,
1708  "encoding_conversions.txt");
1709 
1710  /*
1711  * The query below hardcodes FirstNormalObjectId as 16384 rather than
1712  * interpolating that C #define into the query because, if that #define is
1713  * ever changed, the cutoff we want to use is the value used by
1714  * pre-version 14 servers, not that of some future version.
1715  */
1716  query = "SELECT c.oid as conoid, c.conname, n.nspname "
1717  "FROM pg_catalog.pg_conversion c, "
1718  " pg_catalog.pg_namespace n "
1719  "WHERE c.connamespace = n.oid AND "
1720  " c.oid >= 16384";
1721 
1722  upgrade_task_add_step(task, query,
1724  true, &report);
1725  upgrade_task_run(task, cluster);
1726  upgrade_task_free(task);
1727 
1728  if (report.file)
1729  {
1730  fclose(report.file);
1731  pg_log(PG_REPORT, "fatal");
1732  pg_fatal("Your installation contains user-defined encoding conversions.\n"
1733  "The conversion function parameters changed in PostgreSQL version 14\n"
1734  "so this cluster cannot currently be upgraded. You can remove the\n"
1735  "encoding conversions in the old cluster and restart the upgrade.\n"
1736  "A list of user-defined encoding conversions is in the file:\n"
1737  " %s", report.path);
1738  }
1739  else
1740  check_ok();
1741 }
static void process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1666

References LogOpts::basedir, check_ok(), cluster(), UpgradeTaskReport::file, log_opts, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, prep_status(), process_user_defined_encoding_conversions(), snprintf, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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 1344 of file check.c.

1345 {
1346  UpgradeTaskReport report;
1347  UpgradeTask *task = upgrade_task_create();
1348  const char *query;
1349 
1350  /*
1351  * The query below hardcodes FirstNormalObjectId as 16384 rather than
1352  * interpolating that C #define into the query because, if that #define is
1353  * ever changed, the cutoff we want to use is the value used by
1354  * pre-version 14 servers, not that of some future version.
1355  */
1356  query = "SELECT o.oid AS oproid, "
1357  " n.nspname AS oprnsp, "
1358  " o.oprname, "
1359  " tn.nspname AS typnsp, "
1360  " t.typname "
1361  "FROM pg_catalog.pg_operator o, "
1362  " pg_catalog.pg_namespace n, "
1363  " pg_catalog.pg_type t, "
1364  " pg_catalog.pg_namespace tn "
1365  "WHERE o.oprnamespace = n.oid AND "
1366  " o.oprleft = t.oid AND "
1367  " t.typnamespace = tn.oid AND "
1368  " o.oprright = 0 AND "
1369  " o.oid >= 16384";
1370 
1371  prep_status("Checking for user-defined postfix operators");
1372 
1373  report.file = NULL;
1374  snprintf(report.path, sizeof(report.path), "%s/%s",
1375  log_opts.basedir,
1376  "postfix_ops.txt");
1377 
1379  true, &report);
1380  upgrade_task_run(task, cluster);
1381  upgrade_task_free(task);
1382 
1383  if (report.file)
1384  {
1385  fclose(report.file);
1386  pg_log(PG_REPORT, "fatal");
1387  pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
1388  "supported anymore. Consider dropping the postfix operators and replacing\n"
1389  "them with prefix operators or function calls.\n"
1390  "A list of user-defined postfix operators is in the file:\n"
1391  " %s", report.path);
1392  }
1393  else
1394  check_ok();
1395 }
static void process_user_defined_postfix_ops(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1309

References LogOpts::basedir, check_ok(), cluster(), UpgradeTaskReport::file, log_opts, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, prep_status(), process_user_defined_postfix_ops(), snprintf, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

Referenced by check_and_dump_old_cluster().

◆ check_is_install_user()

static void check_is_install_user ( ClusterInfo cluster)
static

Definition at line 1044 of file check.c.

1045 {
1046  PGresult *res;
1047  PGconn *conn = connectToServer(cluster, "template1");
1048 
1049  prep_status("Checking database user is the install user");
1050 
1051  /* Can't use pg_authid because only superusers can view it. */
1053  "SELECT rolsuper, oid "
1054  "FROM pg_catalog.pg_roles "
1055  "WHERE rolname = current_user "
1056  "AND rolname !~ '^pg_'");
1057 
1058  /*
1059  * We only allow the install user in the new cluster (see comment below)
1060  * and we preserve pg_authid.oid, so this must be the install user in the
1061  * old cluster too.
1062  */
1063  if (PQntuples(res) != 1 ||
1064  atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
1065  pg_fatal("database user \"%s\" is not the install user",
1066  os_info.user);
1067 
1068  PQclear(res);
1069 
1071  "SELECT COUNT(*) "
1072  "FROM pg_catalog.pg_roles "
1073  "WHERE rolname !~ '^pg_'");
1074 
1075  if (PQntuples(res) != 1)
1076  pg_fatal("could not determine the number of users");
1077 
1078  /*
1079  * We only allow the install user in the new cluster because other defined
1080  * users might match users defined in the old cluster and generate an
1081  * error during pg_dump restore.
1082  */
1083  if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
1084  pg_fatal("Only the install user can be defined in the new cluster.");
1085 
1086  PQclear(res);
1087 
1088  PQfinish(conn);
1089 
1090  check_ok();
1091 }
#define atooid(x)
Definition: postgres_ext.h:42
char * user
Definition: pg_upgrade.h:344

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 693 of file check.c.

694 {
696 
698 
700 
701  switch (user_opts.transfer_mode)
702  {
703  case TRANSFER_MODE_CLONE:
705  break;
706  case TRANSFER_MODE_COPY:
707  break;
710  break;
711  case TRANSFER_MODE_LINK:
712  check_hard_link();
713  break;
714  }
715 
717 
719 
721 
723 
725 }
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1750
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1823
static void check_new_cluster_is_empty(void)
Definition: check.c:860
static void check_for_new_tablespace_dir(void)
Definition: check.c:892
void check_file_clone(void)
Definition: file.c:360
void check_hard_link(void)
Definition: file.c:437
void check_copy_file_range(void)
Definition: file.c:400
void check_loadable_libraries(void)
Definition: function.c:165
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:256
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:258
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:255
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition: pg_upgrade.h:257
transferMode transfer_mode
Definition: pg_upgrade.h:326

References check_copy_file_range(), 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(), check_new_cluster_subscription_configuration(), get_db_rel_and_slot_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_CLONE, TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, 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 860 of file check.c.

861 {
862  int dbnum;
863 
864  for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
865  {
866  int relnum;
867  RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
868 
869  for (relnum = 0; relnum < rel_arr->nrels;
870  relnum++)
871  {
872  /* pg_largeobject and its index should be skipped */
873  if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
874  pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
875  new_cluster.dbarr.dbs[dbnum].db_name,
876  rel_arr->rels[relnum].nspname,
877  rel_arr->rels[relnum].relname);
878  }
879  }
880 }
DbInfoArr dbarr
Definition: pg_upgrade.h:284
DbInfo * dbs
Definition: pg_upgrade.h:215
char * db_name
Definition: pg_upgrade.h:194
RelInfoArr rel_arr
Definition: pg_upgrade.h:197
RelInfo * rels
Definition: pg_upgrade.h:148
char * nspname
Definition: pg_upgrade.h:135
char * relname
Definition: pg_upgrade.h:136

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 1750 of file check.c.

1751 {
1752  PGresult *res;
1753  PGconn *conn;
1754  int nslots_on_old;
1755  int nslots_on_new;
1757  char *wal_level;
1758 
1759  /* Logical slots can be migrated since PG17. */
1761  return;
1762 
1763  nslots_on_old = count_old_cluster_logical_slots();
1764 
1765  /* Quick return if there are no logical slots to be migrated. */
1766  if (nslots_on_old == 0)
1767  return;
1768 
1769  conn = connectToServer(&new_cluster, "template1");
1770 
1771  prep_status("Checking for new cluster logical replication slots");
1772 
1773  res = executeQueryOrDie(conn, "SELECT count(*) "
1774  "FROM pg_catalog.pg_replication_slots "
1775  "WHERE slot_type = 'logical' AND "
1776  "temporary IS FALSE;");
1777 
1778  if (PQntuples(res) != 1)
1779  pg_fatal("could not count the number of logical replication slots");
1780 
1781  nslots_on_new = atoi(PQgetvalue(res, 0, 0));
1782 
1783  if (nslots_on_new)
1784  pg_fatal("expected 0 logical replication slots but found %d",
1785  nslots_on_new);
1786 
1787  PQclear(res);
1788 
1789  res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1790  "WHERE name IN ('wal_level', 'max_replication_slots') "
1791  "ORDER BY name DESC;");
1792 
1793  if (PQntuples(res) != 2)
1794  pg_fatal("could not determine parameter settings on new cluster");
1795 
1796  wal_level = PQgetvalue(res, 0, 0);
1797 
1798  if (strcmp(wal_level, "logical") != 0)
1799  pg_fatal("\"wal_level\" must be \"logical\" but is set to \"%s\"",
1800  wal_level);
1801 
1802  max_replication_slots = atoi(PQgetvalue(res, 1, 0));
1803 
1804  if (nslots_on_old > max_replication_slots)
1805  pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
1806  "logical replication slots (%d) on the old cluster",
1807  max_replication_slots, nslots_on_old);
1808 
1809  PQclear(res);
1810  PQfinish(conn);
1811 
1812  check_ok();
1813 }
int count_old_cluster_logical_slots(void)
Definition: info.c:742
int max_replication_slots
Definition: slot.c:141
int wal_level
Definition: xlog.c:131

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_new_cluster_subscription_configuration()

static void check_new_cluster_subscription_configuration ( void  )
static

Definition at line 1823 of file check.c.

1824 {
1825  PGresult *res;
1826  PGconn *conn;
1828 
1829  /* Subscriptions and their dependencies can be migrated since PG17. */
1831  return;
1832 
1833  /* Quick return if there are no subscriptions to be migrated. */
1834  if (old_cluster.nsubs == 0)
1835  return;
1836 
1837  prep_status("Checking for new cluster configuration for subscriptions");
1838 
1839  conn = connectToServer(&new_cluster, "template1");
1840 
1841  res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1842  "WHERE name = 'max_replication_slots';");
1843 
1844  if (PQntuples(res) != 1)
1845  pg_fatal("could not determine parameter settings on new cluster");
1846 
1847  max_replication_slots = atoi(PQgetvalue(res, 0, 0));
1849  pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
1850  "subscriptions (%d) on the old cluster",
1852 
1853  PQclear(res);
1854  PQfinish(conn);
1855 
1856  check_ok();
1857 }

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

Referenced by check_new_cluster().

◆ check_old_cluster_for_valid_slots()

static void check_old_cluster_for_valid_slots ( void  )
static

Definition at line 1866 of file check.c.

1867 {
1868  char output_path[MAXPGPATH];
1869  FILE *script = NULL;
1870 
1871  prep_status("Checking for valid logical replication slots");
1872 
1873  snprintf(output_path, sizeof(output_path), "%s/%s",
1874  log_opts.basedir,
1875  "invalid_logical_slots.txt");
1876 
1877  for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1878  {
1879  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
1880 
1881  for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
1882  {
1883  LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
1884 
1885  /* Is the slot usable? */
1886  if (slot->invalid)
1887  {
1888  if (script == NULL &&
1889  (script = fopen_priv(output_path, "w")) == NULL)
1890  pg_fatal("could not open file \"%s\": %m", output_path);
1891 
1892  fprintf(script, "The slot \"%s\" is invalid\n",
1893  slot->slotname);
1894 
1895  continue;
1896  }
1897 
1898  /*
1899  * Do additional check to ensure that all logical replication
1900  * slots have consumed all the WAL before shutdown.
1901  *
1902  * Note: This can be satisfied only when the old cluster has been
1903  * shut down, so we skip this for live checks.
1904  */
1905  if (!user_opts.live_check && !slot->caught_up)
1906  {
1907  if (script == NULL &&
1908  (script = fopen_priv(output_path, "w")) == NULL)
1909  pg_fatal("could not open file \"%s\": %m", output_path);
1910 
1911  fprintf(script,
1912  "The slot \"%s\" has not consumed the WAL yet\n",
1913  slot->slotname);
1914  }
1915  }
1916  }
1917 
1918  if (script)
1919  {
1920  fclose(script);
1921 
1922  pg_log(PG_REPORT, "fatal");
1923  pg_fatal("Your installation contains logical replication slots that cannot be upgraded.\n"
1924  "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
1925  "and then restart the upgrade.\n"
1926  "A list of the problematic slots is in the file:\n"
1927  " %s", output_path);
1928  }
1929 
1930  check_ok();
1931 }
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:198
LogicalSlotInfo * slots
Definition: pg_upgrade.h:169

References LogOpts::basedir, LogicalSlotInfo::caught_up, check_ok(), ClusterInfo::dbarr, DbInfoArr::dbs, fopen_priv, fprintf, LogicalSlotInfo::invalid, UserOpts::live_check, 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 user_opts.

Referenced by check_and_dump_old_cluster().

◆ check_old_cluster_subscription_state()

static void check_old_cluster_subscription_state ( void  )
static

Definition at line 1974 of file check.c.

1975 {
1976  UpgradeTask *task = upgrade_task_create();
1977  UpgradeTaskReport report;
1978  const char *query;
1979  PGresult *res;
1980  PGconn *conn;
1981  int ntup;
1982 
1983  prep_status("Checking for subscription state");
1984 
1985  report.file = NULL;
1986  snprintf(report.path, sizeof(report.path), "%s/%s",
1987  log_opts.basedir,
1988  "subs_invalid.txt");
1989 
1990  /*
1991  * Check that all the subscriptions have their respective replication
1992  * origin. This check only needs to run once.
1993  */
1996  "SELECT d.datname, s.subname "
1997  "FROM pg_catalog.pg_subscription s "
1998  "LEFT OUTER JOIN pg_catalog.pg_replication_origin o "
1999  " ON o.roname = 'pg_' || s.oid "
2000  "INNER JOIN pg_catalog.pg_database d "
2001  " ON d.oid = s.subdbid "
2002  "WHERE o.roname IS NULL;");
2003  ntup = PQntuples(res);
2004  for (int i = 0; i < ntup; i++)
2005  {
2006  if (report.file == NULL &&
2007  (report.file = fopen_priv(report.path, "w")) == NULL)
2008  pg_fatal("could not open file \"%s\": %m", report.path);
2009  fprintf(report.file, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n",
2010  PQgetvalue(res, i, 0),
2011  PQgetvalue(res, i, 1));
2012  }
2013  PQclear(res);
2014  PQfinish(conn);
2015 
2016  /*
2017  * We don't allow upgrade if there is a risk of dangling slot or origin
2018  * corresponding to initial sync after upgrade.
2019  *
2020  * A slot/origin not created yet refers to the 'i' (initialize) state,
2021  * while 'r' (ready) state refers to a slot/origin created previously but
2022  * already dropped. These states are supported for pg_upgrade. The other
2023  * states listed below are not supported:
2024  *
2025  * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state would
2026  * retain a replication slot, which could not be dropped by the sync
2027  * worker spawned after the upgrade because the subscription ID used for
2028  * the slot name won't match anymore.
2029  *
2030  * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state would
2031  * retain the replication origin when there is a failure in tablesync
2032  * worker immediately after dropping the replication slot in the
2033  * publisher.
2034  *
2035  * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on a
2036  * relation upgraded while in this state would expect an origin ID with
2037  * the OID of the subscription used before the upgrade, causing it to
2038  * fail.
2039  *
2040  * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and
2041  * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, so we
2042  * need not allow these states.
2043  */
2044  query = "SELECT r.srsubstate, s.subname, n.nspname, c.relname "
2045  "FROM pg_catalog.pg_subscription_rel r "
2046  "LEFT JOIN pg_catalog.pg_subscription s"
2047  " ON r.srsubid = s.oid "
2048  "LEFT JOIN pg_catalog.pg_class c"
2049  " ON r.srrelid = c.oid "
2050  "LEFT JOIN pg_catalog.pg_namespace n"
2051  " ON c.relnamespace = n.oid "
2052  "WHERE r.srsubstate NOT IN ('i', 'r') "
2053  "ORDER BY s.subname";
2054 
2056  true, &report);
2057 
2058  upgrade_task_run(task, &old_cluster);
2059  upgrade_task_free(task);
2060 
2061  if (report.file)
2062  {
2063  fclose(report.file);
2064  pg_log(PG_REPORT, "fatal");
2065  pg_fatal("Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n"
2066  "You can allow the initial sync to finish for all relations and then restart the upgrade.\n"
2067  "A list of the problematic subscriptions is in the file:\n"
2068  " %s", report.path);
2069  }
2070  else
2071  check_ok();
2072 }
static void process_old_sub_state_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1939

References LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), UpgradeTaskReport::file, fopen_priv, fprintf, i, log_opts, old_cluster, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), prep_status(), process_old_sub_state_check(), res, snprintf, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

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 921 of file check.c.

922 {
923  FILE *script = NULL;
924  int tblnum;
925  char old_cluster_pgdata[MAXPGPATH],
926  new_cluster_pgdata[MAXPGPATH];
927 
928  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
930 
931  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
932  canonicalize_path(old_cluster_pgdata);
933 
934  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
935  canonicalize_path(new_cluster_pgdata);
936 
937  /* Some people put the new data directory inside the old one. */
938  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
939  {
941  "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
942 
943  /* Unlink file in case it is left over from a previous run. */
944  unlink(*deletion_script_file_name);
945  pg_free(*deletion_script_file_name);
946  *deletion_script_file_name = NULL;
947  return;
948  }
949 
950  /*
951  * Some users (oddly) create tablespaces inside the cluster data
952  * directory. We can't create a proper old cluster delete script in that
953  * case.
954  */
955  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
956  {
957  char old_tablespace_dir[MAXPGPATH];
958 
959  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
960  canonicalize_path(old_tablespace_dir);
961  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
962  {
963  /* reproduce warning from CREATE TABLESPACE that is in the log */
965  "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
966 
967  /* Unlink file in case it is left over from a previous run. */
968  unlink(*deletion_script_file_name);
969  pg_free(*deletion_script_file_name);
970  *deletion_script_file_name = NULL;
971  return;
972  }
973  }
974 
975  prep_status("Creating script to delete old cluster");
976 
977  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
978  pg_fatal("could not open file \"%s\": %m",
979  *deletion_script_file_name);
980 
981 #ifndef WIN32
982  /* add shebang header */
983  fprintf(script, "#!/bin/sh\n\n");
984 #endif
985 
986  /* delete old cluster's default tablespace */
987  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
989 
990  /* delete old cluster's alternate tablespaces */
991  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
992  {
993  /*
994  * Do the old cluster's per-database directories share a directory
995  * with a new version-specific tablespace?
996  */
997  if (strlen(old_cluster.tablespace_suffix) == 0)
998  {
999  /* delete per-database directories */
1000  int dbnum;
1001 
1002  fprintf(script, "\n");
1003 
1004  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1005  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
1008  PATH_QUOTE);
1009  }
1010  else
1011  {
1012  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
1013 
1014  /*
1015  * Simply delete the tablespace directory, which might be ".old"
1016  * or a version-specific subdirectory.
1017  */
1018  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1020  fix_path_separator(suffix_path), PATH_QUOTE);
1021  pfree(suffix_path);
1022  }
1023  }
1024 
1025  fclose(script);
1026 
1027 #ifndef WIN32
1028  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1029  pg_fatal("could not add execute permission to file \"%s\": %m",
1030  *deletion_script_file_name);
1031 #endif
1032 
1033  check_ok();
1034 }
static char * fix_path_separator(char *path)
Definition: check.c:547
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pfree(void *pointer)
Definition: mcxt.c:1521
#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:270
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:560
void canonicalize_path(char *path)
Definition: path.c:265
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * pgdata
Definition: pg_upgrade.h:285
Oid db_oid
Definition: pg_upgrade.h:193
#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, strlcpy(), and ClusterInfo::tablespace_suffix.

Referenced by main().

◆ data_type_check_query()

static char* data_type_check_query ( int  checknum)
static

Definition at line 330 of file check.c.

331 {
332  DataTypesUsageChecks *check = &data_types_usage_checks[checknum];
333 
334  return psprintf("WITH RECURSIVE oids AS ( "
335  /* start with the type(s) returned by base_query */
336  " %s "
337  " UNION ALL "
338  " SELECT * FROM ( "
339  /* inner WITH because we can only reference the CTE once */
340  " WITH x AS (SELECT oid FROM oids) "
341  /* domains on any type selected so far */
342  " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' "
343  " UNION ALL "
344  /* arrays over any type selected so far */
345  " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' "
346  " UNION ALL "
347  /* composite types containing any type selected so far */
348  " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x "
349  " WHERE t.typtype = 'c' AND "
350  " t.oid = c.reltype AND "
351  " c.oid = a.attrelid AND "
352  " NOT a.attisdropped AND "
353  " a.atttypid = x.oid "
354  " UNION ALL "
355  /* ranges containing any type selected so far */
356  " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x "
357  " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid"
358  " ) foo "
359  ") "
360  /* now look for stored columns of any such type */
361  "SELECT n.nspname, c.relname, a.attname "
362  "FROM pg_catalog.pg_class c, "
363  " pg_catalog.pg_namespace n, "
364  " pg_catalog.pg_attribute a "
365  "WHERE c.oid = a.attrelid AND "
366  " NOT a.attisdropped AND "
367  " a.atttypid IN (SELECT oid FROM oids) AND "
368  " c.relkind IN ("
369  CppAsString2(RELKIND_RELATION) ", "
370  CppAsString2(RELKIND_MATVIEW) ", "
371  CppAsString2(RELKIND_INDEX) ") AND "
372  " c.relnamespace = n.oid AND "
373  /* exclude possible orphaned temp tables */
374  " n.nspname !~ '^pg_temp_' AND "
375  " n.nspname !~ '^pg_toast_temp_' AND "
376  /* exclude system catalogs, too */
377  " n.nspname NOT IN ('pg_catalog', 'information_schema')",
378  check->base_query);
379 }
#define CppAsString2(x)
Definition: c.h:342
const char * base_query
Definition: check.c:45

References DataTypesUsageChecks::base_query, CppAsString2, data_types_usage_checks, and psprintf().

Referenced by check_for_data_types_usage().

◆ fix_path_separator()

static char* fix_path_separator ( char *  path)
static

Definition at line 547 of file check.c.

548 {
549 #ifdef WIN32
550 
551  char *result;
552  char *c;
553 
554  result = pg_strdup(path);
555 
556  for (c = result; *c != '\0'; c++)
557  if (*c == '/')
558  *c = '\\';
559 
560  return result;
561 #else
562 
563  return path;
564 #endif
565 }
char * c

References pg_strdup(), and data_type_check_state::result.

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 748 of file check.c.

749 {
750  /*
751  * We unconditionally start/stop the new server because pg_resetwal -o set
752  * wal_level to 'minimum'. If the user is upgrading standby servers using
753  * the rsync instructions, they will need pg_upgrade to write its final
754  * WAL record showing wal_level as 'replica'.
755  */
757 
758  /* Reindex hash indexes for old < 10.0 */
761 
763 
764  stop_postmaster(false);
765 }
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:179

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 ( void  )

Definition at line 568 of file check.c.

569 {
570  if (user_opts.live_check)
571  {
573  "Performing Consistency Checks on Old Live Server\n"
574  "------------------------------------------------");
575  }
576  else
577  {
579  "Performing Consistency Checks\n"
580  "-----------------------------");
581  }
582 }

References UserOpts::live_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 769 of file check.c.

770 {
771  PQExpBufferData user_specification;
772 
773  initPQExpBuffer(&user_specification);
775  {
776  appendPQExpBufferStr(&user_specification, "-U ");
777  appendShellString(&user_specification, os_info.user);
778  appendPQExpBufferChar(&user_specification, ' ');
779  }
780 
782  "Optimizer statistics are not transferred by pg_upgrade.\n"
783  "Once you start the new server, consider running:\n"
784  " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
785 
786  if (deletion_script_file_name)
788  "Running this script will delete the old cluster's data files:\n"
789  " %s",
790  deletion_script_file_name);
791  else
793  "Could not create a script to delete the old cluster's data files\n"
794  "because user-defined tablespaces or the new cluster's data directory\n"
795  "exist in the old cluster directory. The old cluster's contents must\n"
796  "be deleted manually.");
797 
798  termPQExpBuffer(&user_specification);
799 }
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:288
bool user_specified
Definition: pg_upgrade.h:345

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().

◆ process_data_type_check()

static void process_data_type_check ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 387 of file check.c.

388 {
390  int ntups = PQntuples(res);
391  char output_path[MAXPGPATH];
392  int i_nspname = PQfnumber(res, "nspname");
393  int i_relname = PQfnumber(res, "relname");
394  int i_attname = PQfnumber(res, "attname");
395  FILE *script = NULL;
396 
398 
399  if (ntups == 0)
400  return;
401 
402  snprintf(output_path, sizeof(output_path), "%s/%s",
404  state->check->report_filename);
405 
406  /*
407  * Make sure we have a buffer to save reports to now that we found a first
408  * failing check.
409  */
410  if (*state->report == NULL)
411  *state->report = createPQExpBuffer();
412 
413  /*
414  * If this is the first time we see an error for the check in question
415  * then print a status message of the failure.
416  */
417  if (!state->result)
418  {
419  pg_log(PG_REPORT, "failed check: %s", _(state->check->status));
420  appendPQExpBuffer(*state->report, "\n%s\n%s %s\n",
421  _(state->check->report_text),
422  _("A list of the problem columns is in the file:"),
423  output_path);
424  }
425  state->result = true;
426 
427  if ((script = fopen_priv(output_path, "a")) == NULL)
428  pg_fatal("could not open file \"%s\": %m", output_path);
429 
430  fprintf(script, "In database: %s\n", dbinfo->db_name);
431 
432  for (int rowno = 0; rowno < ntups; rowno++)
433  fprintf(script, " %s.%s.%s\n",
434  PQgetvalue(res, rowno, i_nspname),
435  PQgetvalue(res, rowno, i_relname),
436  PQgetvalue(res, rowno, i_attname));
437 
438  fclose(script);
439 }
#define AssertVariableIsOfType(varname, typename)
Definition: c.h:960
#define _(x)
Definition: elog.c:90
void * arg
static struct LogicalRepInfo * dbinfo
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: pg_upgrade.h:500
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
Definition: regguts.h:323

References _, appendPQExpBuffer(), arg, AssertVariableIsOfType, LogOpts::basedir, createPQExpBuffer(), dbinfo, fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQfnumber(), PQgetvalue(), PQntuples(), res, and snprintf.

Referenced by check_for_data_types_usage().

◆ process_incompat_polymorphics()

static void process_incompat_polymorphics ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1403 of file check.c.

1404 {
1405  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1406  int ntups = PQntuples(res);
1407  int i_objkind = PQfnumber(res, "objkind");
1408  int i_objname = PQfnumber(res, "objname");
1409 
1412 
1413  if (ntups == 0)
1414  return;
1415 
1416  if (report->file == NULL &&
1417  (report->file = fopen_priv(report->path, "w")) == NULL)
1418  pg_fatal("could not open file \"%s\": %m", report->path);
1419 
1420  fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1421 
1422  for (int rowno = 0; rowno < ntups; rowno++)
1423  fprintf(report->file, " %s: %s\n",
1424  PQgetvalue(res, rowno, i_objkind),
1425  PQgetvalue(res, rowno, i_objname));
1426 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_for_incompatible_polymorphics().

◆ process_isn_and_int8_passing_mismatch()

static void process_isn_and_int8_passing_mismatch ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1223 of file check.c.

1224 {
1225  int ntups = PQntuples(res);
1226  int i_nspname = PQfnumber(res, "nspname");
1227  int i_proname = PQfnumber(res, "proname");
1228  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1229 
1232 
1233  if (ntups == 0)
1234  return;
1235 
1236  if (report->file == NULL &&
1237  (report->file = fopen_priv(report->path, "w")) == NULL)
1238  pg_fatal("could not open file \"%s\": %m", report->path);
1239 
1240  fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1241 
1242  for (int rowno = 0; rowno < ntups; rowno++)
1243  fprintf(report->file, " %s.%s\n",
1244  PQgetvalue(res, rowno, i_nspname),
1245  PQgetvalue(res, rowno, i_proname));
1246 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_for_isn_and_int8_passing_mismatch().

◆ process_old_sub_state_check()

static void process_old_sub_state_check ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1939 of file check.c.

1940 {
1941  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1942  int ntups = PQntuples(res);
1943  int i_srsubstate = PQfnumber(res, "srsubstate");
1944  int i_subname = PQfnumber(res, "subname");
1945  int i_nspname = PQfnumber(res, "nspname");
1946  int i_relname = PQfnumber(res, "relname");
1947 
1949 
1950  if (ntups == 0)
1951  return;
1952 
1953  if (report->file == NULL &&
1954  (report->file = fopen_priv(report->path, "w")) == NULL)
1955  pg_fatal("could not open file \"%s\": %m", report->path);
1956 
1957  for (int i = 0; i < ntups; i++)
1958  fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n",
1959  PQgetvalue(res, i, i_srsubstate),
1960  dbinfo->db_name,
1961  PQgetvalue(res, i, i_subname),
1962  PQgetvalue(res, i, i_nspname),
1963  PQgetvalue(res, i, i_relname));
1964 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, i, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_old_cluster_subscription_state().

◆ process_user_defined_encoding_conversions()

static void process_user_defined_encoding_conversions ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1666 of file check.c.

1667 {
1668  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1669  int ntups = PQntuples(res);
1670  int i_conoid = PQfnumber(res, "conoid");
1671  int i_conname = PQfnumber(res, "conname");
1672  int i_nspname = PQfnumber(res, "nspname");
1673 
1676 
1677  if (ntups == 0)
1678  return;
1679 
1680  if (report->file == NULL &&
1681  (report->file = fopen_priv(report->path, "w")) == NULL)
1682  pg_fatal("could not open file \"%s\": %m", report->path);
1683 
1684  fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1685 
1686  for (int rowno = 0; rowno < ntups; rowno++)
1687  fprintf(report->file, " (oid=%s) %s.%s\n",
1688  PQgetvalue(res, rowno, i_conoid),
1689  PQgetvalue(res, rowno, i_nspname),
1690  PQgetvalue(res, rowno, i_conname));
1691 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_for_user_defined_encoding_conversions().

◆ process_user_defined_postfix_ops()

static void process_user_defined_postfix_ops ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1309 of file check.c.

1310 {
1311  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1312  int ntups = PQntuples(res);
1313  int i_oproid = PQfnumber(res, "oproid");
1314  int i_oprnsp = PQfnumber(res, "oprnsp");
1315  int i_oprname = PQfnumber(res, "oprname");
1316  int i_typnsp = PQfnumber(res, "typnsp");
1317  int i_typname = PQfnumber(res, "typname");
1318 
1321 
1322  if (ntups == 0)
1323  return;
1324 
1325  if (report->file == NULL &&
1326  (report->file = fopen_priv(report->path, "w")) == NULL)
1327  pg_fatal("could not open file \"%s\": %m", report->path);
1328 
1329  fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1330 
1331  for (int rowno = 0; rowno < ntups; rowno++)
1332  fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n",
1333  PQgetvalue(res, rowno, i_oproid),
1334  PQgetvalue(res, rowno, i_oprnsp),
1335  PQgetvalue(res, rowno, i_oprname),
1336  PQgetvalue(res, rowno, i_typnsp),
1337  PQgetvalue(res, rowno, i_typname));
1338 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_for_user_defined_postfix_ops().

◆ process_with_oids_check()

static void process_with_oids_check ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 1536 of file check.c.

1537 {
1538  UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1539  int ntups = PQntuples(res);
1540  int i_nspname = PQfnumber(res, "nspname");
1541  int i_relname = PQfnumber(res, "relname");
1542 
1544 
1545  if (ntups == 0)
1546  return;
1547 
1548  if (report->file == NULL &&
1549  (report->file = fopen_priv(report->path, "w")) == NULL)
1550  pg_fatal("could not open file \"%s\": %m", report->path);
1551 
1552  fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1553 
1554  for (int rowno = 0; rowno < ntups; rowno++)
1555  fprintf(report->file, " %s.%s\n",
1556  PQgetvalue(res, rowno, i_nspname),
1557  PQgetvalue(res, rowno, i_relname));
1558 }

References arg, AssertVariableIsOfType, dbinfo, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and res.

Referenced by check_for_tables_with_oids().

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 729 of file check.c.

730 {
731  if (user_opts.check)
732  {
733  pg_log(PG_REPORT, "\n*Clusters are compatible*");
734  /* stops new cluster */
735  stop_postmaster(false);
736 
738  exit(0);
739  }
740 
741  pg_log(PG_REPORT, "\n"
742  "If pg_upgrade fails after this point, you must re-initdb the\n"
743  "new cluster before continuing.");
744 }
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().

Variable Documentation

◆ data_types_usage_checks

DataTypesUsageChecks data_types_usage_checks[]
static

Definition at line 95 of file check.c.

Referenced by check_for_data_types_usage(), and data_type_check_query().