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
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
688 stop_postmaster(false);
689}
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1576
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1620
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:461
static void check_old_cluster_subscription_state(void)
Definition: check.c:1986
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1056
static void check_for_connection_status(ClusterInfo *cluster)
Definition: check.c:1114
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1268
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:1878
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1356
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1202
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1709
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1447
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:68
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:349
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:299
bool live_check
Definition: pg_upgrade.h:330
bool check
Definition: pg_upgrade.h:329

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

859{
860 /* get/check pg_control data of servers */
864
866 pg_fatal("When checking a live server, "
867 "the old and new port numbers must be different.");
868}
void get_control_data(ClusterInfo *cluster)
Definition: controldata.c:37
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:697
#define pg_fatal(...)
ClusterInfo new_cluster
Definition: pg_upgrade.c:69
unsigned short port
Definition: pg_upgrade.h:298
ControlData controldata
Definition: pg_upgrade.h:288

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 /*
842 * Since from version 18, newly created database clusters always have
843 * 'signed' default char-signedness, it makes less sense to use
844 * --set-char-signedness option for upgrading from version 18 or later.
845 * Users who want to change the default char signedness of the new
846 * cluster, they can use pg_resetwal manually before the upgrade.
847 */
850 pg_fatal("%s option cannot be used to upgrade from PostgreSQL %s and later.",
851 "--set-char-signedness", "18");
852
853 check_ok();
854}
Assert(PointerIsAligned(start, uint64))
static void check_ok(void)
Definition: initdb.c:2121
void prep_status(const char *fmt,...) pg_attribute_printf(1
uint32 bin_version
Definition: pg_upgrade.h:301
int char_signedness
Definition: pg_upgrade.h:337

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

Referenced by main().

◆ check_for_connection_status()

static void check_for_connection_status ( ClusterInfo cluster)
static

Definition at line 1114 of file check.c.

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

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 */
496 continue;
497 }
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 */
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 char * data_type_check_query(int checknum)
Definition: check.c:330
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
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 1447 of file check.c.

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

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

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

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

905{
906 int tblnum;
907 char new_tablespace_dir[MAXPGPATH];
908
909 prep_status("Checking for new cluster tablespace directories");
910
911 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
912 {
913 struct stat statbuf;
914
915 snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
916 os_info.old_tablespaces[tblnum],
918
919 if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
920 pg_fatal("new cluster tablespace directory already exists: \"%s\"",
921 new_tablespace_dir);
922 }
923
924 check_ok();
925}
OSInfo os_info
Definition: pg_upgrade.c:70
const char * tablespace_suffix
Definition: pg_upgrade.h:302
int num_old_tablespaces
Definition: pg_upgrade.h:357
char ** old_tablespaces
Definition: pg_upgrade.h:356
#define stat
Definition: win32_port.h:274

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

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

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(), 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 1202 of file check.c.

1203{
1204 PGresult *res;
1205 PGconn *conn = connectToServer(cluster, "template1");
1206
1207 prep_status("Checking for prepared transactions");
1208
1209 res = executeQueryOrDie(conn,
1210 "SELECT * "
1211 "FROM pg_catalog.pg_prepared_xacts");
1212
1213 if (PQntuples(res) != 0)
1214 {
1215 if (cluster == &old_cluster)
1216 pg_fatal("The source cluster contains prepared transactions");
1217 else
1218 pg_fatal("The target cluster contains prepared transactions");
1219 }
1220
1221 PQclear(res);
1222
1223 PQfinish(conn);
1224
1225 check_ok();
1226}

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

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

1577{
1578 UpgradeTaskReport report;
1580 const char *query = "SELECT n.nspname, c.relname "
1581 "FROM pg_catalog.pg_class c, "
1582 " pg_catalog.pg_namespace n "
1583 "WHERE c.relnamespace = n.oid AND "
1584 " c.relhasoids AND"
1585 " n.nspname NOT IN ('pg_catalog')";
1586
1587 prep_status("Checking for tables WITH OIDS");
1588
1589 report.file = NULL;
1590 snprintf(report.path, sizeof(report.path), "%s/%s",
1592 "tables_with_oids.txt");
1593
1595 true, &report);
1597 upgrade_task_free(task);
1598
1599 if (report.file)
1600 {
1601 fclose(report.file);
1602 pg_log(PG_REPORT, "fatal");
1603 pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1604 "supported anymore. Consider removing the oid column using\n"
1605 " ALTER TABLE ... SET WITHOUT OIDS;\n"
1606 "A list of tables with the problem is in the file:\n"
1607 " %s", report.path);
1608 }
1609 else
1610 check_ok();
1611}
static void process_with_oids_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1548

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

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

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

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

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

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

References atooid, check_ok(), cluster(), conn, connectToServer(), executeQueryOrDie(), new_cluster, os_info, pg_fatal, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), prep_status(), 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 {
705 break;
707 break;
710 break;
713 break;
714 }
715
717
719
721
723
725}
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1762
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1835
static void check_new_cluster_is_empty(void)
Definition: check.c:872
static void check_for_new_tablespace_dir(void)
Definition: check.c:904
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:262
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:264
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:261
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition: pg_upgrade.h:263
transferMode transfer_mode
Definition: pg_upgrade.h:332

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

873{
874 int dbnum;
875
876 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
877 {
878 int relnum;
879 RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
880
881 for (relnum = 0; relnum < rel_arr->nrels;
882 relnum++)
883 {
884 /* pg_largeobject and its index should be skipped */
885 if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
886 pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
888 rel_arr->rels[relnum].nspname,
889 rel_arr->rels[relnum].relname);
890 }
891 }
892}
DbInfoArr dbarr
Definition: pg_upgrade.h:290
DbInfo * dbs
Definition: pg_upgrade.h:220
char * db_name
Definition: pg_upgrade.h:199
RelInfoArr rel_arr
Definition: pg_upgrade.h:202
RelInfo * rels
Definition: pg_upgrade.h:153
char * nspname
Definition: pg_upgrade.h:140
char * relname
Definition: pg_upgrade.h:141

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

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

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

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(), and prep_status().

Referenced by check_new_cluster().

◆ check_old_cluster_for_valid_slots()

static void check_old_cluster_for_valid_slots ( void  )
static

Definition at line 1878 of file check.c.

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

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

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

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(), 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 933 of file check.c.

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

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{
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:363
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{
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 "Some optimizer statistics may not have been 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:582
char * bindir
Definition: pg_upgrade.h:294
bool user_specified
Definition: pg_upgrade.h:355

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:952
#define _(x)
Definition: elog.c:90
void * arg
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: pg_upgrade.h:510
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::db_name, fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQfnumber(), PQgetvalue(), PQntuples(), process_data_type_check(), and snprintf.

Referenced by check_for_data_types_usage(), and process_data_type_check().

◆ process_incompat_polymorphics()

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

Definition at line 1415 of file check.c.

1416{
1418 int ntups = PQntuples(res);
1419 int i_objkind = PQfnumber(res, "objkind");
1420 int i_objname = PQfnumber(res, "objname");
1421
1424
1425 if (ntups == 0)
1426 return;
1427
1428 if (report->file == NULL &&
1429 (report->file = fopen_priv(report->path, "w")) == NULL)
1430 pg_fatal("could not open file \"%s\": %m", report->path);
1431
1432 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1433
1434 for (int rowno = 0; rowno < ntups; rowno++)
1435 fprintf(report->file, " %s: %s\n",
1436 PQgetvalue(res, rowno, i_objkind),
1437 PQgetvalue(res, rowno, i_objname));
1438}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_incompat_polymorphics().

Referenced by check_for_incompatible_polymorphics(), and process_incompat_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 1235 of file check.c.

1236{
1237 int ntups = PQntuples(res);
1238 int i_nspname = PQfnumber(res, "nspname");
1239 int i_proname = PQfnumber(res, "proname");
1241
1244
1245 if (ntups == 0)
1246 return;
1247
1248 if (report->file == NULL &&
1249 (report->file = fopen_priv(report->path, "w")) == NULL)
1250 pg_fatal("could not open file \"%s\": %m", report->path);
1251
1252 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1253
1254 for (int rowno = 0; rowno < ntups; rowno++)
1255 fprintf(report->file, " %s.%s\n",
1256 PQgetvalue(res, rowno, i_nspname),
1257 PQgetvalue(res, rowno, i_proname));
1258}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_isn_and_int8_passing_mismatch().

Referenced by check_for_isn_and_int8_passing_mismatch(), and process_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 1951 of file check.c.

1952{
1954 int ntups = PQntuples(res);
1955 int i_srsubstate = PQfnumber(res, "srsubstate");
1956 int i_subname = PQfnumber(res, "subname");
1957 int i_nspname = PQfnumber(res, "nspname");
1958 int i_relname = PQfnumber(res, "relname");
1959
1961
1962 if (ntups == 0)
1963 return;
1964
1965 if (report->file == NULL &&
1966 (report->file = fopen_priv(report->path, "w")) == NULL)
1967 pg_fatal("could not open file \"%s\": %m", report->path);
1968
1969 for (int i = 0; i < ntups; i++)
1970 fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n",
1971 PQgetvalue(res, i, i_srsubstate),
1972 dbinfo->db_name,
1973 PQgetvalue(res, i, i_subname),
1974 PQgetvalue(res, i, i_nspname),
1975 PQgetvalue(res, i, i_relname));
1976}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, i, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_old_sub_state_check().

Referenced by check_old_cluster_subscription_state(), and process_old_sub_state_check().

◆ process_user_defined_encoding_conversions()

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

Definition at line 1678 of file check.c.

1679{
1681 int ntups = PQntuples(res);
1682 int i_conoid = PQfnumber(res, "conoid");
1683 int i_conname = PQfnumber(res, "conname");
1684 int i_nspname = PQfnumber(res, "nspname");
1685
1688
1689 if (ntups == 0)
1690 return;
1691
1692 if (report->file == NULL &&
1693 (report->file = fopen_priv(report->path, "w")) == NULL)
1694 pg_fatal("could not open file \"%s\": %m", report->path);
1695
1696 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1697
1698 for (int rowno = 0; rowno < ntups; rowno++)
1699 fprintf(report->file, " (oid=%s) %s.%s\n",
1700 PQgetvalue(res, rowno, i_conoid),
1701 PQgetvalue(res, rowno, i_nspname),
1702 PQgetvalue(res, rowno, i_conname));
1703}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_user_defined_encoding_conversions().

Referenced by check_for_user_defined_encoding_conversions(), and process_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 1321 of file check.c.

1322{
1324 int ntups = PQntuples(res);
1325 int i_oproid = PQfnumber(res, "oproid");
1326 int i_oprnsp = PQfnumber(res, "oprnsp");
1327 int i_oprname = PQfnumber(res, "oprname");
1328 int i_typnsp = PQfnumber(res, "typnsp");
1329 int i_typname = PQfnumber(res, "typname");
1330
1333
1334 if (ntups == 0)
1335 return;
1336
1337 if (report->file == NULL &&
1338 (report->file = fopen_priv(report->path, "w")) == NULL)
1339 pg_fatal("could not open file \"%s\": %m", report->path);
1340
1341 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1342
1343 for (int rowno = 0; rowno < ntups; rowno++)
1344 fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n",
1345 PQgetvalue(res, rowno, i_oproid),
1346 PQgetvalue(res, rowno, i_oprnsp),
1347 PQgetvalue(res, rowno, i_oprname),
1348 PQgetvalue(res, rowno, i_typnsp),
1349 PQgetvalue(res, rowno, i_typname));
1350}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_user_defined_postfix_ops().

Referenced by check_for_user_defined_postfix_ops(), and process_user_defined_postfix_ops().

◆ process_with_oids_check()

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

Definition at line 1548 of file check.c.

1549{
1551 int ntups = PQntuples(res);
1552 int i_nspname = PQfnumber(res, "nspname");
1553 int i_relname = PQfnumber(res, "relname");
1554
1556
1557 if (ntups == 0)
1558 return;
1559
1560 if (report->file == NULL &&
1561 (report->file = fopen_priv(report->path, "w")) == NULL)
1562 pg_fatal("could not open file \"%s\": %m", report->path);
1563
1564 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1565
1566 for (int rowno = 0; rowno < ntups; rowno++)
1567 fprintf(report->file, " %s.%s\n",
1568 PQgetvalue(res, rowno, i_nspname),
1569 PQgetvalue(res, rowno, i_relname));
1570}

References arg, AssertVariableIsOfType, DbInfo::db_name, UpgradeTaskReport::file, fopen_priv, fprintf, UpgradeTaskReport::path, pg_fatal, PQfnumber(), PQgetvalue(), PQntuples(), and process_with_oids_check().

Referenced by check_for_tables_with_oids(), and process_with_oids_check().

◆ 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}
void cleanup_output_dirs(void)
Definition: util.c:63

References UserOpts::check, cleanup_output_dirs(), 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().