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: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:815
static void check_ok(void)
Definition: initdb.c:2119
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",
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
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4939
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
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:419
@ PG_REPORT
Definition: pg_upgrade.h:269
#define snprintf
Definition: port.h:238
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 */
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 1435 of file check.c.

1436{
1437 PQExpBufferData old_polymorphics;
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",
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);
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",
1279 "contrib_isn_and_int8_pass_by_value.txt");
1280
1281 task = upgrade_task_create();
1283 true, &report);
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: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 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",
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;
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",
1580 "tables_with_oids.txt");
1581
1583 true, &report);
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;
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",
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);
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;
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",
1376 "postfix_ops.txt");
1377
1379 true, &report);
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:43
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 {
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: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\"",
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",
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{
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",
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
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: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:349
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 "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:938
#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(), process_data_type_check(), res, 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 1403 of file check.c.

1404{
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(), process_incompat_polymorphics(), and res.

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 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");
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(), process_isn_and_int8_passing_mismatch(), and res.

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

1940{
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(), process_old_sub_state_check(), and res.

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

1667{
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(), process_user_defined_encoding_conversions(), and res.

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

1310{
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(), process_user_defined_postfix_ops(), and res.

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

1537{
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(), process_with_oids_check(), and res.

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