PostgreSQL Source Code git master
Loading...
Searching...
No Matches
check.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_am_d.h"
#include "catalog/pg_authid_d.h"
#include "catalog/pg_class_d.h"
#include "fe_utils/string_utils.h"
#include "mb/pg_wchar.h"
#include "pg_upgrade.h"
#include "common/unicode_version.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_unsupported_encodings (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_not_null_inheritance (ClusterInfo *cluster)
 
static void check_for_gist_inet_ops (ClusterInfo *cluster)
 
static void check_for_new_tablespace_dir (void)
 
static void check_for_user_defined_encoding_conversions (ClusterInfo *cluster)
 
static void check_for_unicode_update (ClusterInfo *cluster)
 
static void check_new_cluster_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 void check_old_cluster_global_names (ClusterInfo *cluster)
 
static chardata_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 charfix_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_inconsistent_notnull (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_gist_inet_ops_check (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_user_defined_encoding_conversions (DbInfo *dbinfo, PGresult *res, void *arg)
 
static void process_unicode_update (DbInfo *dbinfo, PGresult *res, void *arg)
 
static bool unicode_version_changed (ClusterInfo *cluster)
 
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 67 of file check.c.

◆ MANUAL_CHECK

#define MANUAL_CHECK   1

Definition at line 66 of file check.c.

Function Documentation

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 531 of file check.c.

532{
533 /* -- OLD -- */
534
537
538 /*
539 * First check that all databases allow connections since we'll otherwise
540 * fail in later stages.
541 */
543
544 /*
545 * Check for encodings that are no longer supported.
546 */
548
549 /*
550 * Validate database, user, role and tablespace names from the old
551 * cluster. No need to check in 19 or newer as newline and carriage return
552 * are not allowed at the creation time of the object.
553 */
556
557 /*
558 * Extract a list of databases, tables, and logical replication slots from
559 * the old cluster.
560 */
562
564
566
567
568 /*
569 * Check for various failure cases
570 */
574
576 {
577 /*
578 * Logical replication slots can be migrated since PG17. See comments
579 * in get_db_rel_and_slot_infos().
580 */
582
583 /*
584 * Subscriptions and their dependencies can be migrated since PG17.
585 * Before that the logical slots are not upgraded, so we will not be
586 * able to upgrade the logical replication clusters completely.
587 */
590 }
591
593
594 /*
595 * Unicode updates can affect some objects that use expressions with
596 * functions dependent on Unicode.
597 */
599
600 /*
601 * PG 14 changed the function signature of encoding conversion functions.
602 * Conversions from older versions cannot be upgraded automatically
603 * because the user-defined functions used by the encoding conversions
604 * need to be changed to match the new signature.
605 */
608
609 /*
610 * Pre-PG 14 allowed user defined postfix operators, which are not
611 * supported anymore. Verify there are none, iff applicable.
612 */
615
616 /*
617 * PG 14 changed polymorphic functions from anyarray to
618 * anycompatiblearray.
619 */
622
623 /*
624 * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
625 * supported anymore. Verify there are none, iff applicable.
626 */
629
630 /*
631 * Pre-PG 18 allowed child tables to omit not-null constraints that their
632 * parents columns have, but schema restore fails for them. Verify there
633 * are none, iff applicable.
634 */
637
638 /*
639 * The btree_gist extension contains gist_inet_ops and gist_cidr_ops
640 * opclasses that do not reliably give correct answers. We want to
641 * deprecate and eventually remove those, and as a first step v19 marks
642 * them not-opcdefault and instead marks the replacement in-core opclass
643 * "inet_ops" as opcdefault. That creates a problem for pg_upgrade: in
644 * versions where those opclasses were marked opcdefault, pg_dump will
645 * dump indexes using them with no explicit opclass specification, so that
646 * restore would create them using the inet_ops opclass. That would be
647 * incompatible with what's actually in the on-disk files. So refuse to
648 * upgrade if there are any such indexes.
649 */
652
653 /*
654 * While not a check option, we do this now because this is the only time
655 * the old server is running.
656 */
657 if (!user_opts.check)
659
661 stop_postmaster(false);
662}
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition check.c:1581
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition check.c:406
static void check_for_gist_inet_ops(ClusterInfo *cluster)
Definition check.c:1737
static void check_old_cluster_subscription_state(void)
Definition check.c:2325
static void check_for_unicode_update(ClusterInfo *cluster)
Definition check.c:1918
static void check_is_install_user(ClusterInfo *cluster)
Definition check.c:1016
static void check_for_not_null_inheritance(ClusterInfo *cluster)
Definition check.c:1658
static void check_for_connection_status(ClusterInfo *cluster)
Definition check.c:1074
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition check.c:1283
static void check_for_unsupported_encodings(ClusterInfo *cluster)
Definition check.c:1159
static void check_old_cluster_for_valid_slots(void)
Definition check.c:2203
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition check.c:1368
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition check.c:1220
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition check.c:1812
static void check_old_cluster_global_names(ClusterInfo *cluster)
Definition check.c:2432
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition check.c:1456
void generate_old_dump(void)
Definition dump.c:16
void get_loadable_libraries(void)
Definition function.c:77
void get_subscription_info(ClusterInfo *cluster)
Definition info.c:841
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition info.c:279
static pid_t start_postmaster(void)
Definition pg_ctl.c:443
static void stop_postmaster(void)
Definition pg_regress.c:444
ClusterInfo old_cluster
Definition pg_upgrade.c:73
void init_tablespaces(void)
Definition tablespace.c:19
#define GET_MAJOR_VERSION(v)
Definition pg_upgrade.h:27
UserOpts user_opts
Definition option.c:30
uint32 major_version
Definition pg_upgrade.h:283
bool live_check
Definition pg_upgrade.h:318
bool check
Definition pg_upgrade.h:317

References UserOpts::check, check_for_connection_status(), check_for_data_types_usage(), check_for_gist_inet_ops(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_not_null_inheritance(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_unicode_update(), check_for_unsupported_encodings(), 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_global_names(), check_old_cluster_subscription_state(), generate_old_dump(), get_db_rel_and_slot_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_subscription_info(), init_tablespaces(), UserOpts::live_check, ClusterInfo::major_version, old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

◆ check_cluster_compatibility()

void check_cluster_compatibility ( void  )

Definition at line 843 of file check.c.

844{
845 /* get/check pg_control data of servers */
849
851 pg_fatal("When checking a live server, "
852 "the old and new port numbers must be different.");
853}
void get_control_data(ClusterInfo *cluster)
Definition controldata.c:39
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
#define pg_fatal(...)
ClusterInfo new_cluster
Definition pg_upgrade.c:74
unsigned short port
Definition pg_upgrade.h:282
ControlData controldata
Definition pg_upgrade.h:272

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

789{
790 prep_status("Checking cluster versions");
791
792 /* cluster versions should already have been obtained */
795
796 /*
797 * We allow upgrades from/to the same major version for alpha/beta
798 * upgrades
799 */
800
802 pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
803 "10");
804
805 /* Only current PG version is supported as a target */
807 pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
809
810 /*
811 * We can't allow downgrading because we use the target pg_dump, and
812 * pg_dump cannot operate on newer database versions, only current and
813 * older versions.
814 */
816 pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
817
818 /* Ensure binaries match the designated data directories */
821 pg_fatal("Old cluster data and binary directories are from different major versions.");
824 pg_fatal("New cluster data and binary directories are from different major versions.");
825
826 /*
827 * Since from version 18, newly created database clusters always have
828 * 'signed' default char-signedness, it makes less sense to use
829 * --set-char-signedness option for upgrading from version 18 or later.
830 * Users who want to change the default char signedness of the new
831 * cluster, they can use pg_resetwal manually before the upgrade.
832 */
835 pg_fatal("The option %s cannot be used for upgrades from PostgreSQL %s and later.",
836 "--set-char-signedness", "18");
837
838 check_ok();
839}
#define Assert(condition)
Definition c.h:1002
static void check_ok(void)
Definition initdb.c:2138
void prep_status(const char *fmt,...) pg_attribute_printf(1
static int fb(int x)
uint32 bin_version
Definition pg_upgrade.h:285
int char_signedness
Definition pg_upgrade.h:325

References Assert, ClusterInfo::bin_version, UserOpts::char_signedness, check_ok(), fb(), 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 1074 of file check.c.

1075{
1076 int dbnum;
1078 PGresult *dbres;
1079 int ntups;
1080 int i_datname;
1081 int i_datallowconn;
1082 int i_datconnlimit;
1083 FILE *script = NULL;
1084 char output_path[MAXPGPATH];
1085
1086 prep_status("Checking database connection settings");
1087
1088 snprintf(output_path, sizeof(output_path), "%s/%s",
1090 "databases_cannot_connect_to.txt");
1091
1092 conn_template1 = connectToServer(cluster, "template1");
1093
1094 /* get database names */
1096 "SELECT datname, datallowconn, datconnlimit "
1097 "FROM pg_catalog.pg_database");
1098
1099 i_datname = PQfnumber(dbres, "datname");
1100 i_datallowconn = PQfnumber(dbres, "datallowconn");
1101 i_datconnlimit = PQfnumber(dbres, "datconnlimit");
1102
1103 ntups = PQntuples(dbres);
1104 for (dbnum = 0; dbnum < ntups; dbnum++)
1105 {
1106 char *datname = PQgetvalue(dbres, dbnum, i_datname);
1109
1110 if (strcmp(datname, "template0") == 0)
1111 {
1112 /* avoid restore failure when pg_dumpall tries to create template0 */
1113 if (strcmp(datallowconn, "t") == 0)
1114 pg_fatal("template0 must not allow connections, "
1115 "i.e. its pg_database.datallowconn must be false");
1116 }
1117 else
1118 {
1119 /*
1120 * Avoid datallowconn == false databases from being skipped on
1121 * restore, and ensure that no databases are marked invalid with
1122 * datconnlimit == -2.
1123 */
1124 if ((strcmp(datallowconn, "f") == 0) || strcmp(datconnlimit, "-2") == 0)
1125 {
1126 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1127 pg_fatal("could not open file \"%s\": %m", output_path);
1128
1129 fprintf(script, "%s\n", datname);
1130 }
1131 }
1132 }
1133
1134 PQclear(dbres);
1135
1137
1138 if (script)
1139 {
1140 fclose(script);
1141 pg_log(PG_REPORT, "fatal");
1142 pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
1143 "pg_database.datallowconn must be true and pg_database.datconnlimit\n"
1144 "must not be -2. Your installation contains non-template0 databases\n"
1145 "which cannot be connected to. Consider allowing connection for all\n"
1146 "non-template0 databases or drop the databases which do not allow\n"
1147 "connections. A list of databases with the problem is in the file:\n"
1148 " %s", output_path);
1149 }
1150 else
1151 check_ok();
1152}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
void PQfinish(PGconn *conn)
int PQfnumber(const PGresult *res, const char *field_name)
Definition fe-exec.c:3620
#define PQgetvalue
#define PQclear
#define PQntuples
#define MAXPGPATH
NameData datname
Definition pg_database.h:37
bool datallowconn
Definition pg_database.h:52
int32 datconnlimit
Definition pg_database.h:61
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:413
@ PG_REPORT
Definition pg_upgrade.h:259
#define snprintf
Definition port.h:261
char * basedir
Definition pg_upgrade.h:305

References LogOpts::basedir, check_ok(), connectToServer(), datallowconn, datconnlimit, datname, executeQueryOrDie(), fb(), 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 406 of file check.c.

407{
408 PQExpBuffer report = NULL;
412 char **queries = NULL;
413 struct data_type_check_state *states;
414
415 prep_status("Checking data type usage");
416
417 /* Gather number of checks to perform */
418 while (tmp->status != NULL)
419 {
421 tmp++;
422 }
423
424 /* Allocate memory for queries and for task states */
427
428 for (int i = 0; i < n_data_types_usage_checks; i++)
429 {
431
433 {
435
436 /*
437 * Make sure that the check applies to the current cluster version
438 * and skip it if not.
439 */
441 continue;
442 }
444 {
445 if (GET_MAJOR_VERSION(cluster->major_version) > check->threshold_version)
446 continue;
447 }
448 else
450
451 queries[i] = data_type_check_query(i);
452
453 states[i].check = check;
454 states[i].report = &report;
455
457 true, &states[i]);
458 }
459
460 /*
461 * Connect to each database in the cluster and run all defined checks
462 * against that database before trying the next one.
463 */
466
467 if (report)
468 {
469 pg_fatal("Data type checks failed: %s", report->data);
471 }
472
473 for (int i = 0; i < n_data_types_usage_checks; i++)
474 {
475 if (queries[i])
476 pg_free(queries[i]);
477 }
478 pg_free(queries);
479 pg_free(states);
480
481 check_ok();
482}
static char * data_type_check_query(int checknum)
Definition check.c:277
static DataTypesUsageChecks data_types_usage_checks[]
Definition check.c:102
#define ALL_VERSIONS
Definition check.c:67
#define MANUAL_CHECK
Definition check.c:66
static void process_data_type_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:334
void pg_free(void *ptr)
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:67
int i
Definition isn.c:77
UpgradeTask * upgrade_task_create(void)
Definition task.c:117
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition task.c:421
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)
DataTypesUsageVersionCheck version_hook
Definition check.c:58
const char * status
Definition check.c:48
PQExpBuffer * report
Definition check.c:269
DataTypesUsageChecks * check
Definition check.c:267

References ALL_VERSIONS, Assert, data_type_check_state::check, check_ok(), PQExpBufferData::data, data_type_check_query(), data_types_usage_checks, destroyPQExpBuffer(), fb(), GET_MAJOR_VERSION, i, MANUAL_CHECK, pg_fatal, pg_free(), pg_malloc0_array, 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_gist_inet_ops()

static void check_for_gist_inet_ops ( ClusterInfo cluster)
static

Definition at line 1737 of file check.c.

1738{
1739 UpgradeTaskReport report;
1741 const char *query = "SELECT nc.nspname, cc.relname "
1742 "FROM pg_catalog.pg_opclass oc, pg_catalog.pg_index i, "
1743 " pg_catalog.pg_class cc, pg_catalog.pg_namespace nc "
1744 "WHERE oc.opcmethod = " CppAsString2(GIST_AM_OID)
1745 " AND oc.opcname IN ('gist_inet_ops', 'gist_cidr_ops')"
1746 " AND oc.opcdefault"
1747 " AND oc.oid = any(i.indclass)"
1748 " AND i.indexrelid = cc.oid AND cc.relnamespace = nc.oid";
1749
1750 prep_status("Checking for uses of gist_inet_ops/gist_cidr_ops");
1751
1752 report.file = NULL;
1753 snprintf(report.path, sizeof(report.path), "%s/%s",
1755 "gist_inet_ops.txt");
1756
1758 true, &report);
1761
1762 if (report.file)
1763 {
1764 fclose(report.file);
1765 pg_log(PG_REPORT, "fatal");
1766 pg_fatal("Your installation contains indexes that use btree_gist extension's\n"
1767 "gist_inet_ops or gist_cidr_ops operator classes, which cannot be\n"
1768 "binary-upgraded. Replace them with indexes that use the built-in GiST\n"
1769 "inet_ops operator class.\n"
1770 "A list of indexes with the problem is in the file:\n"
1771 " %s", report.path);
1772 }
1773 else
1774 check_ok();
1775}
#define CppAsString2(x)
Definition c.h:565
static void process_gist_inet_ops_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1709
char path[MAXPGPATH]
Definition pg_upgrade.h:510

References LogOpts::basedir, check_ok(), CppAsString2, fb(), UpgradeTaskReport::file, log_opts, UpgradeTaskReport::path, pg_fatal, pg_log(), PG_REPORT, prep_status(), process_gist_inet_ops_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_incompatible_polymorphics()

static void check_for_incompatible_polymorphics ( ClusterInfo cluster)
static

Definition at line 1456 of file check.c.

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

References appendPQExpBufferStr(), LogOpts::basedir, check_ok(), fb(), UpgradeTaskReport::file, initPQExpBuffer(), log_opts, UpgradeTaskReport::path, pfree(), pg_fatal, 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 1283 of file check.c.

1284{
1286 UpgradeTaskReport report;
1287 const char *query = "SELECT n.nspname, p.proname "
1288 "FROM pg_catalog.pg_proc p, "
1289 " pg_catalog.pg_namespace n "
1290 "WHERE p.pronamespace = n.oid AND "
1291 " p.probin = '$libdir/isn'";
1292
1293 prep_status("Checking for contrib/isn with bigint-passing mismatch");
1294
1297 {
1298 /* no mismatch */
1299 check_ok();
1300 return;
1301 }
1302
1303 report.file = NULL;
1304 snprintf(report.path, sizeof(report.path), "%s/%s",
1306 "contrib_isn_and_int8_pass_by_value.txt");
1307
1310 true, &report);
1313
1314 if (report.file)
1315 {
1316 fclose(report.file);
1317 pg_log(PG_REPORT, "fatal");
1318 pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
1319 "bigint data type. Your old and new clusters pass bigint values\n"
1320 "differently so this cluster cannot currently be upgraded. You can\n"
1321 "manually dump databases in the old cluster that use \"contrib/isn\"\n"
1322 "facilities, drop them, perform the upgrade, and then restore them. A\n"
1323 "list of the problem functions is in the file:\n"
1324 " %s", report.path);
1325 }
1326 else
1327 check_ok();
1328}
static void process_isn_and_int8_passing_mismatch(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1253
bool float8_pass_by_value
Definition pg_upgrade.h:234

References LogOpts::basedir, check_ok(), ClusterInfo::controldata, fb(), 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 889 of file check.c.

890{
891 int tblnum;
893
894 prep_status("Checking new cluster tablespace directories");
895
897 {
898 struct stat statbuf;
899
903
904 if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
905 pg_fatal("new cluster tablespace directory already exists: \"%s\"",
907 }
908
909 check_ok();
910}
int num_tablespaces
Definition pg_upgrade.h:287
char ** tablespaces
Definition pg_upgrade.h:286
const char * tablespace_suffix
Definition pg_upgrade.h:288
#define stat
Definition win32_port.h:74

References check_ok(), fb(), MAXPGPATH, new_cluster, ClusterInfo::num_tablespaces, pg_fatal, prep_status(), snprintf, stat, ClusterInfo::tablespace_suffix, and ClusterInfo::tablespaces.

Referenced by check_new_cluster().

◆ check_for_not_null_inheritance()

static void check_for_not_null_inheritance ( ClusterInfo cluster)
static

Definition at line 1658 of file check.c.

1659{
1660 UpgradeTaskReport report;
1662 const char *query;
1663
1664 prep_status("Checking for not-null constraint inconsistencies");
1665
1666 report.file = NULL;
1667 snprintf(report.path, sizeof(report.path), "%s/%s",
1669 "not_null_inconsistent_columns.txt");
1670
1671 query = "SELECT nspname, cc.relname, ac.attname "
1672 "FROM pg_catalog.pg_inherits i, pg_catalog.pg_attribute ac, "
1673 " pg_catalog.pg_attribute ap, pg_catalog.pg_class cc, "
1674 " pg_catalog.pg_namespace nc "
1675 "WHERE cc.oid = ac.attrelid AND i.inhrelid = ac.attrelid "
1676 " AND i.inhparent = ap.attrelid AND ac.attname = ap.attname "
1677 " AND cc.relnamespace = nc.oid "
1678 " AND ap.attnum > 0 and ap.attnotnull AND NOT ac.attnotnull";
1679
1683 true, &report);
1686
1687 if (report.file)
1688 {
1689 fclose(report.file);
1690 pg_log(PG_REPORT, "fatal");
1691 pg_fatal("Your installation contains inconsistent NOT NULL constraints.\n"
1692 "If the parent column(s) are NOT NULL, then the child column must\n"
1693 "also be marked NOT NULL, or the upgrade will fail.\n"
1694 "You can fix this by running\n"
1695 " ALTER TABLE tablename ALTER column SET NOT NULL;\n"
1696 "on each column listed in the file:\n"
1697 " %s", report.path);
1698 }
1699 else
1700 check_ok();
1701}
static void process_inconsistent_notnull(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1623

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

Referenced by check_and_dump_old_cluster().

◆ check_for_prepared_transactions()

static void check_for_prepared_transactions ( ClusterInfo cluster)
static

Definition at line 1220 of file check.c.

1221{
1222 PGresult *res;
1223 PGconn *conn = connectToServer(cluster, "template1");
1224
1225 prep_status("Checking for prepared transactions");
1226
1227 res = executeQueryOrDie(conn,
1228 "SELECT * "
1229 "FROM pg_catalog.pg_prepared_xacts");
1230
1231 if (PQntuples(res) != 0)
1232 {
1233 if (cluster == &old_cluster)
1234 pg_fatal("The source cluster contains prepared transactions");
1235 else
1236 pg_fatal("The target cluster contains prepared transactions");
1237 }
1238
1239 PQclear(res);
1240
1241 PQfinish(conn);
1242
1243 check_ok();
1244}
PGconn * conn
Definition streamutil.c:52

References check_ok(), conn, connectToServer(), executeQueryOrDie(), fb(), 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 1581 of file check.c.

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

References LogOpts::basedir, check_ok(), fb(), 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_unicode_update()

static void check_for_unicode_update ( ClusterInfo cluster)
static

Definition at line 1918 of file check.c.

1919{
1920 UpgradeTaskReport report;
1922 const char *query;
1923
1924 /*
1925 * The builtin provider did not exist prior to version 17. While there are
1926 * still problems that could potentially be caught from earlier versions,
1927 * such as an index on NORMALIZE(), we don't check for that here.
1928 */
1929 if (GET_MAJOR_VERSION(cluster->major_version) < 1700)
1930 return;
1931
1932 prep_status("Checking for objects affected by Unicode update");
1933
1935 {
1936 check_ok();
1937 return;
1938 }
1939
1940 report.file = NULL;
1941 snprintf(report.path, sizeof(report.path), "%s/%s",
1943 "unicode_dependent_rels.txt");
1944
1945 query =
1946 /* collations that use built-in Unicode for character semantics */
1947 "WITH collations(collid) AS ( "
1948 " SELECT oid FROM pg_collation "
1949 " WHERE collprovider='b' AND colllocale IN ('C.UTF-8','PG_UNICODE_FAST') "
1950 /* include default collation, if appropriate */
1951 " UNION "
1952 " SELECT 'pg_catalog.default'::regcollation FROM pg_database "
1953 " WHERE datname = current_database() AND "
1954 " datlocprovider='b' AND datlocale IN ('C.UTF-8','PG_UNICODE_FAST') "
1955 "), "
1956 /* functions that use built-in Unicode */
1957 "functions(procid) AS ( "
1958 " SELECT proc.oid FROM pg_proc proc "
1959 " WHERE proname IN ('normalize','unicode_assigned','unicode_version','is_normalized') AND "
1960 " pronamespace='pg_catalog'::regnamespace "
1961 "), "
1962 /* operators that use the input collation for character semantics */
1963 "coll_operators(operid, procid, collid) AS ( "
1964 " SELECT oper.oid, oper.oprcode, collid FROM pg_operator oper, collations "
1965 " WHERE oprname IN ('~', '~*', '!~', '!~*', '~~*', '!~~*') AND "
1966 " oprnamespace='pg_catalog'::regnamespace AND "
1967 " oprright='pg_catalog.text'::pg_catalog.regtype "
1968 "), "
1969 /* functions that use the input collation for character semantics */
1970 "coll_functions(procid, collid) AS ( "
1971 " SELECT proc.oid, collid FROM pg_proc proc, collations "
1972 " WHERE pronamespace='pg_catalog'::regnamespace AND "
1973 " ((proname IN ('lower','initcap','upper','casefold') AND "
1974 " pronargs = 1 AND "
1975 " proargtypes[0] = 'pg_catalog.text'::pg_catalog.regtype) OR "
1976 " (proname = 'substring' AND pronargs = 2 AND "
1977 " proargtypes[0] = 'pg_catalog.text'::pg_catalog.regtype AND "
1978 " proargtypes[1] = 'pg_catalog.text'::pg_catalog.regtype) OR "
1979 " proname LIKE 'regexp_%') "
1980 /* include functions behind the operators listed above */
1981 " UNION "
1982 " SELECT procid, collid FROM coll_operators "
1983 "), "
1984
1985 /*
1986 * Generate patterns to search a pg_node_tree for the above functions and
1987 * operators.
1988 */
1989 "patterns(p) AS ( "
1990 " SELECT '{FUNCEXPR :funcid ' || procid::text || '[ }]' FROM functions "
1991 " UNION "
1992 " SELECT '{OPEXPR :opno ' || operid::text || ' (:\\w+ \\w+ )*' || "
1993 " ':inputcollid ' || collid::text || '[ }]' FROM coll_operators "
1994 " UNION "
1995 " SELECT '{FUNCEXPR :funcid ' || procid::text || ' (:\\w+ \\w+ )*' || "
1996 " ':inputcollid ' || collid::text || '[ }]' FROM coll_functions "
1997 ") "
1998
1999 /*
2000 * Match the patterns against expressions used for relation contents.
2001 */
2002 "SELECT reloid, relkind, nspname, relname "
2003 " FROM ( "
2004 " SELECT conrelid "
2005 " FROM pg_constraint, patterns WHERE conbin::text ~ p "
2006 " UNION "
2007 " SELECT indexrelid "
2008 " FROM pg_index, patterns WHERE indexprs::text ~ p OR indpred::text ~ p "
2009 " UNION "
2010 " SELECT partrelid "
2011 " FROM pg_partitioned_table, patterns WHERE partexprs::text ~ p "
2012 " UNION "
2013 " SELECT ev_class "
2014 " FROM pg_rewrite, pg_class, patterns "
2015 " WHERE ev_class = pg_class.oid AND relkind = 'm' AND ev_action::text ~ p"
2016 " ) s(reloid), pg_class c, pg_namespace n, pg_database d "
2017 " WHERE s.reloid = c.oid AND c.relnamespace = n.oid AND "
2018 " d.datname = current_database() AND "
2019 " d.encoding = pg_char_to_encoding('UTF8');";
2020
2024 true, &report);
2027
2028 if (report.file)
2029 {
2030 fclose(report.file);
2031 report_status(PG_WARNING, "warning");
2032 pg_log(PG_WARNING, "Your installation contains relations that might be affected by a new version of Unicode.\n"
2033 "A list of potentially-affected relations is in the file:\n"
2034 " %s", report.path);
2035 }
2036 else
2037 check_ok();
2038}
static bool unicode_version_changed(ClusterInfo *cluster)
Definition check.c:1893
static void process_unicode_update(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1864
@ PG_WARNING
Definition pg_upgrade.h:260
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2

References LogOpts::basedir, check_ok(), fb(), UpgradeTaskReport::file, GET_MAJOR_VERSION, log_opts, UpgradeTaskReport::path, pg_log(), PG_WARNING, prep_status(), process_unicode_update(), report_status(), snprintf, unicode_version_changed(), upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

Referenced by check_and_dump_old_cluster().

◆ check_for_unsupported_encodings()

static void check_for_unsupported_encodings ( ClusterInfo cluster)
static

Definition at line 1159 of file check.c.

1160{
1161 int i_datname;
1162 int i_encoding;
1163 int ntups;
1164 PGresult *res;
1165 PGconn *conn;
1166 FILE *script = NULL;
1167 char output_path[MAXPGPATH];
1168
1169 prep_status("Checking for unsupported encodings");
1170
1171 snprintf(output_path, sizeof(output_path), "%s/%s",
1173 "databases_unsupported_encoding.txt");
1174
1175 conn = connectToServer(cluster, "template1");
1176
1177 res = executeQueryOrDie(conn,
1178 "SELECT datname, encoding "
1179 "FROM pg_catalog.pg_database");
1180 ntups = PQntuples(res);
1181 i_datname = PQfnumber(res, "datname");
1182 i_encoding = PQfnumber(res, "encoding");
1183 for (int rowno = 0; rowno < ntups; rowno++)
1184 {
1185 char *datname = PQgetvalue(res, rowno, i_datname);
1186 int encoding = atoi(PQgetvalue(res, rowno, i_encoding));
1187
1189 {
1190 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1191 pg_fatal("could not open file \"%s\": %m", output_path);
1192
1193 fprintf(script, "%s\n", datname);
1194 }
1195 }
1196 PQclear(res);
1197 PQfinish(conn);
1198
1199 if (script)
1200 {
1201 fclose(script);
1202 pg_log(PG_REPORT, "fatal");
1203 pg_fatal("Your installation contains databases using encodings that are\n"
1204 "no longer supported. Consider dumping and restoring with UTF8.\n"
1205 "A list of databases with unsupported encodings is in the file:\n"
1206 " %s", output_path);
1207 }
1208 else
1209 check_ok();
1210}
static char * encoding
Definition initdb.c:139
#define PG_VALID_BE_ENCODING(_enc)
Definition pg_wchar.h:134

References LogOpts::basedir, check_ok(), conn, connectToServer(), datname, encoding, executeQueryOrDie(), fb(), fopen_priv, fprintf, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PG_VALID_BE_ENCODING, PQclear, PQfinish(), PQfnumber(), PQgetvalue, PQntuples, prep_status(), and snprintf.

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

1813{
1814 UpgradeTaskReport report;
1816 const char *query;
1817
1818 prep_status("Checking for user-defined encoding conversions");
1819
1820 report.file = NULL;
1821 snprintf(report.path, sizeof(report.path), "%s/%s",
1823 "encoding_conversions.txt");
1824
1825 /*
1826 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1827 * interpolating that C #define into the query because, if that #define is
1828 * ever changed, the cutoff we want to use is the value used by
1829 * pre-version 14 servers, not that of some future version.
1830 */
1831 query = "SELECT c.oid as conoid, c.conname, n.nspname "
1832 "FROM pg_catalog.pg_conversion c, "
1833 " pg_catalog.pg_namespace n "
1834 "WHERE c.connamespace = n.oid AND "
1835 " c.oid >= 16384";
1836
1839 true, &report);
1842
1843 if (report.file)
1844 {
1845 fclose(report.file);
1846 pg_log(PG_REPORT, "fatal");
1847 pg_fatal("Your installation contains user-defined encoding conversions.\n"
1848 "The conversion function parameters changed in PostgreSQL version 14\n"
1849 "so this cluster cannot currently be upgraded. You can remove the\n"
1850 "encoding conversions in the old cluster and restart the upgrade.\n"
1851 "A list of user-defined encoding conversions is in the file:\n"
1852 " %s", report.path);
1853 }
1854 else
1855 check_ok();
1856}
static void process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1784

References LogOpts::basedir, check_ok(), fb(), 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 1368 of file check.c.

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

References LogOpts::basedir, check_ok(), fb(), 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 1016 of file check.c.

1017{
1018 PGresult *res;
1019 PGconn *conn = connectToServer(cluster, "template1");
1020
1021 prep_status("Checking database user is the install user");
1022
1023 /* Can't use pg_authid because only superusers can view it. */
1024 res = executeQueryOrDie(conn,
1025 "SELECT rolsuper, oid "
1026 "FROM pg_catalog.pg_roles "
1027 "WHERE rolname = current_user "
1028 "AND rolname !~ '^pg_'");
1029
1030 /*
1031 * We only allow the install user in the new cluster (see comment below)
1032 * and we preserve pg_authid.oid, so this must be the install user in the
1033 * old cluster too.
1034 */
1035 if (PQntuples(res) != 1 ||
1037 pg_fatal("database user \"%s\" is not the install user",
1038 os_info.user);
1039
1040 PQclear(res);
1041
1042 res = executeQueryOrDie(conn,
1043 "SELECT COUNT(*) "
1044 "FROM pg_catalog.pg_roles "
1045 "WHERE rolname !~ '^pg_'");
1046
1047 if (PQntuples(res) != 1)
1048 pg_fatal("could not determine the number of users");
1049
1050 /*
1051 * We only allow the install user in the new cluster because other defined
1052 * users might match users defined in the old cluster and generate an
1053 * error during pg_dump restore.
1054 */
1055 if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
1056 pg_fatal("Only the install user can be defined in the new cluster.");
1057
1058 PQclear(res);
1059
1060 PQfinish(conn);
1061
1062 check_ok();
1063}
OSInfo os_info
Definition pg_upgrade.c:75
#define atooid(x)
char * user
Definition pg_upgrade.h:342

References atooid, check_ok(), conn, connectToServer(), executeQueryOrDie(), fb(), 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 666 of file check.c.

667{
669
671
673
674 switch (user_opts.transfer_mode)
675 {
678 break;
680 break;
683 break;
686 break;
688
689 /*
690 * We do the hard link check for --swap, too, since it's an easy
691 * way to verify the clusters are in the same file system. This
692 * allows us to take some shortcuts in the file synchronization
693 * step. With some more effort, we could probably support the
694 * separate-file-system use case, but this mode is unlikely to
695 * offer much benefit if we have to copy the files across file
696 * system boundaries.
697 */
699 break;
700 }
701
703
705
707
709
711}
static void check_new_cluster_replication_slots(void)
Definition check.c:2052
static void check_new_cluster_subscription_configuration(void)
Definition check.c:2160
static void check_new_cluster_is_empty(void)
Definition check.c:857
static void check_for_new_tablespace_dir(void)
Definition check.c:889
void check_file_clone(void)
Definition file.c:196
void check_hard_link(transferMode transfer_mode)
Definition file.c:273
void check_copy_file_range(void)
Definition file.c:236
void check_loadable_libraries(void)
Definition function.c:171
@ TRANSFER_MODE_COPY
Definition pg_upgrade.h:245
@ TRANSFER_MODE_LINK
Definition pg_upgrade.h:247
@ TRANSFER_MODE_SWAP
Definition pg_upgrade.h:248
@ TRANSFER_MODE_CLONE
Definition pg_upgrade.h:244
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition pg_upgrade.h:246
transferMode transfer_mode
Definition pg_upgrade.h:320

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_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, TRANSFER_MODE_SWAP, and user_opts.

Referenced by main().

◆ check_new_cluster_is_empty()

static void check_new_cluster_is_empty ( void  )
static

Definition at line 857 of file check.c.

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

References DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, fb(), 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_replication_slots()

static void check_new_cluster_replication_slots ( void  )
static

Definition at line 2052 of file check.c.

2053{
2054 PGresult *res;
2055 PGconn *conn;
2056 int nslots_on_old;
2057 int nslots_on_new;
2058 int rdt_slot_on_new;
2060 char *wal_level;
2061 int i_nslots_on_new;
2063
2064 /*
2065 * Logical slots can be migrated since PG17 and a physical slot
2066 * CONFLICT_DETECTION_SLOT can be migrated since PG19.
2067 */
2069 return;
2070
2072
2073 /*
2074 * Quick return if there are no slots to be migrated and no subscriptions
2075 * have the retain_dead_tuples option enabled.
2076 */
2078 return;
2079
2080 conn = connectToServer(&new_cluster, "template1");
2081
2082 prep_status("Checking new cluster replication slots");
2083
2084 res = executeQueryOrDie(conn, "SELECT %s AS nslots_on_new, %s AS rdt_slot_on_new "
2085 "FROM pg_catalog.pg_replication_slots",
2086 nslots_on_old > 0
2087 ? "COUNT(*) FILTER (WHERE slot_type = 'logical' AND temporary IS FALSE)"
2088 : "0",
2089 old_cluster.sub_retain_dead_tuples
2090 ? "COUNT(*) FILTER (WHERE slot_name = 'pg_conflict_detection')"
2091 : "0");
2092
2093 if (PQntuples(res) != 1)
2094 pg_fatal("could not count the number of replication slots");
2095
2096 i_nslots_on_new = PQfnumber(res, "nslots_on_new");
2097 i_rdt_slot_on_new = PQfnumber(res, "rdt_slot_on_new");
2098
2100
2101 if (nslots_on_new)
2102 {
2104 pg_fatal("expected 0 logical replication slots but found %d",
2106 }
2107
2109
2110 if (rdt_slot_on_new)
2111 {
2113 pg_fatal("replication slot \"%s\" already exists in the new cluster", "pg_conflict_detection");
2114 }
2115
2116 PQclear(res);
2117
2118 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
2119 "WHERE name IN ('wal_level', 'max_replication_slots') "
2120 "ORDER BY name DESC;");
2121
2122 if (PQntuples(res) != 2)
2123 pg_fatal("could not determine parameter settings on new cluster");
2124
2125 wal_level = PQgetvalue(res, 0, 0);
2126
2128 strcmp(wal_level, "minimal") == 0)
2129 pg_fatal("\"wal_level\" must be \"replica\" or \"logical\" but is set to \"%s\"",
2130 wal_level);
2131
2133
2136 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
2137 "logical replication slots in the old cluster plus one additional slot required "
2138 "for retaining conflict detection information (%d)",
2140
2142 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
2143 "logical replication slots (%d) in the old cluster",
2145
2146 PQclear(res);
2147 PQfinish(conn);
2148
2149 check_ok();
2150}
int count_old_cluster_logical_slots(void)
Definition info.c:825
int max_replication_slots
Definition slot.c:161
bool sub_retain_dead_tuples
Definition pg_upgrade.h:290
int wal_level
Definition xlog.c:138

References Assert, check_ok(), conn, connectToServer(), count_old_cluster_logical_slots(), executeQueryOrDie(), fb(), GET_MAJOR_VERSION, ClusterInfo::major_version, max_replication_slots, new_cluster, old_cluster, pg_fatal, PQclear, PQfinish(), PQfnumber(), PQgetvalue, PQntuples, prep_status(), ClusterInfo::sub_retain_dead_tuples, 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 2160 of file check.c.

2161{
2162 PGresult *res;
2163 PGconn *conn;
2165
2166 /* Subscriptions and their dependencies can be migrated since PG17. */
2168 return;
2169
2170 /* Quick return if there are no subscriptions to be migrated. */
2171 if (old_cluster.nsubs == 0)
2172 return;
2173
2174 prep_status("Checking new cluster configuration for subscriptions");
2175
2176 conn = connectToServer(&new_cluster, "template1");
2177
2178 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
2179 "WHERE name = 'max_active_replication_origins';");
2180
2181 if (PQntuples(res) != 1)
2182 pg_fatal("could not determine parameter settings on new cluster");
2183
2186 pg_fatal("\"max_active_replication_origins\" (%d) must be greater than or equal to the number of "
2187 "subscriptions (%d) in the old cluster",
2189
2190 PQclear(res);
2191 PQfinish(conn);
2192
2193 check_ok();
2194}
int max_active_replication_origins
Definition origin.c:106

References check_ok(), conn, connectToServer(), executeQueryOrDie(), fb(), GET_MAJOR_VERSION, ClusterInfo::major_version, max_active_replication_origins, 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 2203 of file check.c.

2204{
2205 char output_path[MAXPGPATH];
2206 FILE *script = NULL;
2207
2208 prep_status("Checking logical replication slots");
2209
2210 snprintf(output_path, sizeof(output_path), "%s/%s",
2212 "invalid_logical_slots.txt");
2213
2214 for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
2215 {
2216 LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
2217
2218 for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
2219 {
2220 LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
2221
2222 /* Is the slot usable? */
2223 if (slot->invalid)
2224 {
2225 if (script == NULL &&
2226 (script = fopen_priv(output_path, "w")) == NULL)
2227 pg_fatal("could not open file \"%s\": %m", output_path);
2228
2229 fprintf(script, "The slot \"%s\" is invalid\n",
2230 slot->slotname);
2231
2232 continue;
2233 }
2234
2235 /*
2236 * Do additional check to ensure that all logical replication
2237 * slots have consumed all the WAL before shutdown.
2238 *
2239 * Note: This can be satisfied only when the old cluster has been
2240 * shut down, so we skip this for live checks.
2241 */
2242 if (!user_opts.live_check && !slot->caught_up)
2243 {
2244 if (script == NULL &&
2245 (script = fopen_priv(output_path, "w")) == NULL)
2246 pg_fatal("could not open file \"%s\": %m", output_path);
2247
2248 fprintf(script,
2249 "The slot \"%s\" has not consumed the WAL yet\n",
2250 slot->slotname);
2251 }
2252
2253 /*
2254 * The name "pg_conflict_detection" (defined as
2255 * CONFLICT_DETECTION_SLOT) has been reserved for logical
2256 * replication conflict detection slot since PG19.
2257 */
2258 if (strcmp(slot->slotname, "pg_conflict_detection") == 0)
2259 {
2260 if (script == NULL &&
2261 (script = fopen_priv(output_path, "w")) == NULL)
2262 pg_fatal("could not open file \"%s\": %m", output_path);
2263
2264 fprintf(script,
2265 "The slot name \"%s\" is reserved\n",
2266 slot->slotname);
2267 }
2268 }
2269 }
2270
2271 if (script)
2272 {
2273 fclose(script);
2274
2275 pg_log(PG_REPORT, "fatal");
2276 pg_fatal("Your installation contains logical replication slots that cannot be upgraded.\n"
2277 "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
2278 "and then restart the upgrade.\n"
2279 "A list of the problematic slots is in the file:\n"
2280 " %s", output_path);
2281 }
2282
2283 check_ok();
2284}
LogicalSlotInfoArr slot_arr
Definition pg_upgrade.h:186
LogicalSlotInfo * slots
Definition pg_upgrade.h:157

References LogOpts::basedir, LogicalSlotInfo::caught_up, check_ok(), ClusterInfo::dbarr, DbInfoArr::dbs, fb(), 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_global_names()

static void check_old_cluster_global_names ( ClusterInfo cluster)
static

Definition at line 2432 of file check.c.

2433{
2434 int i;
2436 PGresult *res;
2437 int ntups;
2438 FILE *script = NULL;
2439 char output_path[MAXPGPATH];
2440 int count = 0;
2441
2442 prep_status("Checking names of databases, roles, and tablespaces");
2443
2444 snprintf(output_path, sizeof(output_path), "%s/%s",
2446 "db_role_tablespace_invalid_names.txt");
2447
2448 conn_template1 = connectToServer(cluster, "template1");
2449
2450 /*
2451 * Get database, user/role and tablespace names from cluster. Can't use
2452 * pg_authid because only superusers can view it.
2453 */
2455 "SELECT datname AS objname, 'database' AS objtype "
2456 "FROM pg_catalog.pg_database UNION ALL "
2457 "SELECT rolname AS objname, 'role' AS objtype "
2458 "FROM pg_catalog.pg_roles UNION ALL "
2459 "SELECT spcname AS objname, 'tablespace' AS objtype "
2460 "FROM pg_catalog.pg_tablespace ORDER BY 2 ");
2461
2462 ntups = PQntuples(res);
2463 for (i = 0; i < ntups; i++)
2464 {
2465 char *objname = PQgetvalue(res, i, 0);
2466 char *objtype = PQgetvalue(res, i, 1);
2467
2468 /* If name has \n or \r, then report it. */
2469 if (strpbrk(objname, "\n\r"))
2470 {
2471 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
2472 pg_fatal("could not open file \"%s\": %m", output_path);
2473
2474 fprintf(script, "%d : %s name = \"%s\"\n", ++count, objtype, objname);
2475 }
2476 }
2477
2478 PQclear(res);
2480
2481 if (script)
2482 {
2483 fclose(script);
2484 pg_log(PG_REPORT, "fatal");
2485 pg_fatal("Your installation contains databases, roles, or tablespaces with names\n"
2486 "with invalid characters (newline or carriage return). To fix this,\n"
2487 "rename these objects.\n"
2488 "A list of all objects with invalid names is in the file:\n"
2489 " %s", output_path);
2490 }
2491 else
2492 check_ok();
2493}

References LogOpts::basedir, check_ok(), connectToServer(), executeQueryOrDie(), fb(), fopen_priv, fprintf, i, log_opts, MAXPGPATH, pg_fatal, pg_log(), PG_REPORT, PQclear, PQfinish(), PQgetvalue, PQntuples, prep_status(), and snprintf.

Referenced by check_and_dump_old_cluster().

◆ check_old_cluster_subscription_state()

static void check_old_cluster_subscription_state ( void  )
static

Definition at line 2325 of file check.c.

2326{
2328 UpgradeTaskReport report;
2329 const char *query;
2330 PGresult *res;
2331 PGconn *conn;
2332 int ntup;
2333
2334 prep_status("Checking subscription state");
2335
2336 report.file = NULL;
2337 snprintf(report.path, sizeof(report.path), "%s/%s",
2339 "subs_invalid.txt");
2340
2341 /*
2342 * Check that all the subscriptions have their respective replication
2343 * origin. This check only needs to run once.
2344 */
2346 res = executeQueryOrDie(conn,
2347 "SELECT d.datname, s.subname "
2348 "FROM pg_catalog.pg_subscription s "
2349 "LEFT OUTER JOIN pg_catalog.pg_replication_origin o "
2350 " ON o.roname = 'pg_' || s.oid "
2351 "INNER JOIN pg_catalog.pg_database d "
2352 " ON d.oid = s.subdbid "
2353 "WHERE o.roname IS NULL;");
2354 ntup = PQntuples(res);
2355 for (int i = 0; i < ntup; i++)
2356 {
2357 if (report.file == NULL &&
2358 (report.file = fopen_priv(report.path, "w")) == NULL)
2359 pg_fatal("could not open file \"%s\": %m", report.path);
2360 fprintf(report.file, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n",
2361 PQgetvalue(res, i, 0),
2362 PQgetvalue(res, i, 1));
2363 }
2364 PQclear(res);
2365 PQfinish(conn);
2366
2367 /*
2368 * We don't allow upgrade if there is a risk of dangling slot or origin
2369 * corresponding to initial sync after upgrade.
2370 *
2371 * A slot/origin not created yet refers to the 'i' (initialize) state,
2372 * while 'r' (ready) state refers to a slot/origin created previously but
2373 * already dropped. These states are supported for pg_upgrade. The other
2374 * states listed below are not supported:
2375 *
2376 * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state would
2377 * retain a replication slot and origin. The sync worker spawned after the
2378 * upgrade cannot drop them because the subscription ID used for the slot
2379 * and origin name no longer matches.
2380 *
2381 * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state would
2382 * retain the replication origin when there is a failure in tablesync
2383 * worker immediately after dropping the replication slot in the
2384 * publisher.
2385 *
2386 * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on a
2387 * relation upgraded while in this state would expect an origin ID with
2388 * the OID of the subscription used before the upgrade, causing it to
2389 * fail.
2390 *
2391 * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and
2392 * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, so we
2393 * need not allow these states.
2394 */
2395 query = "SELECT r.srsubstate, s.subname, n.nspname, c.relname "
2396 "FROM pg_catalog.pg_subscription_rel r "
2397 "LEFT JOIN pg_catalog.pg_subscription s"
2398 " ON r.srsubid = s.oid "
2399 "LEFT JOIN pg_catalog.pg_class c"
2400 " ON r.srrelid = c.oid "
2401 "LEFT JOIN pg_catalog.pg_namespace n"
2402 " ON c.relnamespace = n.oid "
2403 "WHERE r.srsubstate NOT IN ('i', 'r') "
2404 "ORDER BY s.subname";
2405
2407 true, &report);
2408
2411
2412 if (report.file)
2413 {
2414 fclose(report.file);
2415 pg_log(PG_REPORT, "fatal");
2416 pg_fatal("Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n"
2417 "You can allow the initial sync to finish for all relations and then restart the upgrade.\n"
2418 "A list of the problematic subscriptions is in the file:\n"
2419 " %s", report.path);
2420 }
2421 else
2422 check_ok();
2423}
static void process_old_sub_state_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:2292

References LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fb(), 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 918 of file check.c.

919{
920 FILE *script = NULL;
921 int tblnum;
924 char *old_tblspc_suffix;
925
926 *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
928
931
934
935 /* Some people put the new data directory inside the old one. */
937 {
939 "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
940
941 /* Unlink file in case it is left over from a previous run. */
945 return;
946 }
947
948 /*
949 * Some users (oddly) create tablespaces inside the cluster data
950 * directory. We can't create a proper old cluster delete script in that
951 * case.
952 */
954 {
956
960 {
961 /* reproduce warning from CREATE TABLESPACE that is in the log */
963 "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", new_tablespace_dir);
964
965 /* Unlink file in case it is left over from a previous run. */
969 return;
970 }
971 }
972
973 prep_status("Creating script to delete old cluster");
974
975 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
976 pg_fatal("could not open file \"%s\": %m",
978
979#ifndef WIN32
980 /* add shebang header */
981 fprintf(script, "#!/bin/sh\n\n");
982#endif
983
984 /* delete old cluster's default tablespace */
985 fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
987
988 /* delete old cluster's alternate tablespaces */
992 fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
996
997 fclose(script);
998
999#ifndef WIN32
1001 pg_fatal("could not add execute permission to file \"%s\": %m",
1003#endif
1004
1005 check_ok();
1006}
static char * fix_path_separator(char *path)
Definition check.c:492
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
#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
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition path.c:654
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:275
#define S_IRWXU
Definition win32_port.h:305

References canonicalize_path(), check_ok(), fb(), fix_path_separator(), fopen_priv, fprintf, MAXPGPATH, new_cluster, ClusterInfo::num_tablespaces, old_cluster, path_is_prefix_of_path(), PATH_QUOTE, 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(), ClusterInfo::tablespace_suffix, and ClusterInfo::tablespaces.

Referenced by main().

◆ data_type_check_query()

static char * data_type_check_query ( int  checknum)
static

Definition at line 277 of file check.c.

278{
280
281 return psprintf("WITH RECURSIVE oids AS ( "
282 /* start with the type(s) returned by base_query */
283 " %s "
284 " UNION ALL "
285 " SELECT * FROM ( "
286 /* inner WITH because we can only reference the CTE once */
287 " WITH x AS (SELECT oid FROM oids) "
288 /* domains on any type selected so far */
289 " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' "
290 " UNION ALL "
291 /* arrays over any type selected so far */
292 " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' "
293 " UNION ALL "
294 /* composite types containing any type selected so far */
295 " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x "
296 " WHERE t.typtype = 'c' AND "
297 " t.oid = c.reltype AND "
298 " c.oid = a.attrelid AND "
299 " NOT a.attisdropped AND "
300 " a.atttypid = x.oid "
301 " UNION ALL "
302 /* ranges containing any type selected so far */
303 " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x "
304 " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid"
305 " ) foo "
306 ") "
307 /* now look for stored columns of any such type */
308 "SELECT n.nspname, c.relname, a.attname "
309 "FROM pg_catalog.pg_class c, "
310 " pg_catalog.pg_namespace n, "
311 " pg_catalog.pg_attribute a "
312 "WHERE c.oid = a.attrelid AND "
313 " NOT a.attisdropped AND "
314 " a.atttypid IN (SELECT oid FROM oids) AND "
315 " c.relkind IN ("
319 " c.relnamespace = n.oid AND "
320 /* exclude possible orphaned temp tables */
321 " n.nspname !~ '^pg_temp_' AND "
322 " n.nspname !~ '^pg_toast_temp_' AND "
323 /* exclude system catalogs, too */
324 " n.nspname NOT IN ('pg_catalog', 'information_schema')",
325 check->base_query);
326}
const char * base_query
Definition check.c:52

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

Referenced by check_for_data_types_usage().

◆ fix_path_separator()

static char * fix_path_separator ( char path)
static

Definition at line 492 of file check.c.

493{
494#ifdef WIN32
495
496 char *result;
497 char *c;
498
499 result = pg_strdup(path);
500
501 for (c = result; *c != '\0'; c++)
502 if (*c == '/')
503 *c = '\\';
504
505 return result;
506#else
507
508 return path;
509#endif
510}
uint32 result
char * c

References pg_strdup(), and 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 734 of file check.c.

735{
736 /*
737 * We unconditionally start/stop the new server because pg_resetwal -o set
738 * wal_level to 'minimum'. If the user is upgrading standby servers using
739 * the rsync instructions, they will need pg_upgrade to write its final
740 * WAL record showing wal_level as 'replica'.
741 */
743
745
746 stop_postmaster(false);
747}
void report_extension_updates(ClusterInfo *cluster)
Definition version.c:68

References new_cluster, report_extension_updates(), start_postmaster(), and stop_postmaster().

Referenced by main().

◆ output_check_banner()

void output_check_banner ( void  )

Definition at line 513 of file check.c.

514{
516 {
518 "Performing Consistency Checks on Old Live Server\n"
519 "------------------------------------------------");
520 }
521 else
522 {
524 "Performing Consistency Checks\n"
525 "-----------------------------");
526 }
527}

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

752{
754
757 {
761 }
762
764 "Some statistics are not transferred by pg_upgrade.\n"
765 "Once you start the new server, consider running these two commands:\n"
766 " %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n"
767 " %s/vacuumdb %s--all --analyze-only",
770
773 "Running this script will delete the old cluster's data files:\n"
774 " %s",
776 else
778 "Could not create a script to delete the old cluster's data files\n"
779 "because user-defined tablespaces or the new cluster's data directory\n"
780 "exist in the old cluster directory. The old cluster's contents must\n"
781 "be deleted manually.");
782
784}
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendShellString(PQExpBuffer buf, const char *str)
char * bindir
Definition pg_upgrade.h:278
bool user_specified
Definition pg_upgrade.h:343

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, fb(), 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 334 of file check.c.

335{
337 int ntups = PQntuples(res);
339 int i_nspname = PQfnumber(res, "nspname");
340 int i_relname = PQfnumber(res, "relname");
341 int i_attname = PQfnumber(res, "attname");
342 FILE *script = NULL;
343
344 if (ntups == 0)
345 return;
346
347 snprintf(output_path, sizeof(output_path), "%s/%s",
349 state->check->report_filename);
350
351 /*
352 * Make sure we have a buffer to save reports to now that we found a first
353 * failing check.
354 */
355 if (*state->report == NULL)
356 *state->report = createPQExpBuffer();
357
358 /*
359 * If this is the first time we see an error for the check in question
360 * then print a status message of the failure.
361 */
362 if (!state->result)
363 {
364 pg_log(PG_REPORT, "failed check: %s", _(state->check->status));
365 appendPQExpBuffer(*state->report, "\n%s\n%s\n %s\n",
366 _(state->check->report_text),
367 _("A list of the problem columns is in the file:"),
369 }
370 state->result = true;
371
372 if ((script = fopen_priv(output_path, "a")) == NULL)
373 pg_fatal("could not open file \"%s\": %m", output_path);
374
375 fprintf(script, "In database: %s\n", dbinfo->db_name);
376
377 for (int rowno = 0; rowno < ntups; rowno++)
378 fprintf(script, " %s.%s.%s\n",
381 PQgetvalue(res, rowno, i_attname));
382
383 fclose(script);
384}
Datum arg
Definition elog.c:1323
#define _(x)
Definition elog.c:96
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)

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

Referenced by check_for_data_types_usage().

◆ process_gist_inet_ops_check()

static void process_gist_inet_ops_check ( DbInfo dbinfo,
PGresult res,
void arg 
)
static

Definition at line 1709 of file check.c.

1710{
1712 int ntups = PQntuples(res);
1713 int i_nspname = PQfnumber(res, "nspname");
1714 int i_relname = PQfnumber(res, "relname");
1715
1716 if (ntups == 0)
1717 return;
1718
1719 if (report->file == NULL &&
1720 (report->file = fopen_priv(report->path, "w")) == NULL)
1721 pg_fatal("could not open file \"%s\": %m", report->path);
1722
1723 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1724
1725 for (int rowno = 0; rowno < ntups; rowno++)
1726 fprintf(report->file, " %s.%s\n",
1727 PQgetvalue(res, rowno, i_nspname),
1728 PQgetvalue(res, rowno, i_relname));
1729}

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

Referenced by check_for_gist_inet_ops().

◆ process_incompat_polymorphics()

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

Definition at line 1427 of file check.c.

1428{
1430 int ntups = PQntuples(res);
1431 int i_objkind = PQfnumber(res, "objkind");
1432 int i_objname = PQfnumber(res, "objname");
1433
1434 if (ntups == 0)
1435 return;
1436
1437 if (report->file == NULL &&
1438 (report->file = fopen_priv(report->path, "w")) == NULL)
1439 pg_fatal("could not open file \"%s\": %m", report->path);
1440
1441 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1442
1443 for (int rowno = 0; rowno < ntups; rowno++)
1444 fprintf(report->file, " %s: %s\n",
1445 PQgetvalue(res, rowno, i_objkind),
1446 PQgetvalue(res, rowno, i_objname));
1447}

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

Referenced by check_for_incompatible_polymorphics().

◆ process_inconsistent_notnull()

static void process_inconsistent_notnull ( DbInfo dbinfo,
PGresult res,
void arg 
)
static

Definition at line 1623 of file check.c.

1624{
1626 int ntups = PQntuples(res);
1627 int i_nspname = PQfnumber(res, "nspname");
1628 int i_relname = PQfnumber(res, "relname");
1629 int i_attname = PQfnumber(res, "attname");
1630
1631 if (ntups == 0)
1632 return;
1633
1634 if (report->file == NULL &&
1635 (report->file = fopen_priv(report->path, "w")) == NULL)
1636 pg_fatal("could not open file \"%s\": %m", report->path);
1637
1638 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1639
1640 for (int rowno = 0; rowno < ntups; rowno++)
1641 {
1642 fprintf(report->file, " %s.%s.%s\n",
1643 PQgetvalue(res, rowno, i_nspname),
1644 PQgetvalue(res, rowno, i_relname),
1645 PQgetvalue(res, rowno, i_attname));
1646 }
1647}

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

Referenced by check_for_not_null_inheritance().

◆ process_isn_and_int8_passing_mismatch()

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

Definition at line 1253 of file check.c.

1254{
1255 int ntups = PQntuples(res);
1256 int i_nspname = PQfnumber(res, "nspname");
1257 int i_proname = PQfnumber(res, "proname");
1259
1260 if (ntups == 0)
1261 return;
1262
1263 if (report->file == NULL &&
1264 (report->file = fopen_priv(report->path, "w")) == NULL)
1265 pg_fatal("could not open file \"%s\": %m", report->path);
1266
1267 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1268
1269 for (int rowno = 0; rowno < ntups; rowno++)
1270 fprintf(report->file, " %s.%s\n",
1271 PQgetvalue(res, rowno, i_nspname),
1272 PQgetvalue(res, rowno, i_proname));
1273}

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

Referenced by check_for_isn_and_int8_passing_mismatch().

◆ process_old_sub_state_check()

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

Definition at line 2292 of file check.c.

2293{
2295 int ntups = PQntuples(res);
2296 int i_srsubstate = PQfnumber(res, "srsubstate");
2297 int i_subname = PQfnumber(res, "subname");
2298 int i_nspname = PQfnumber(res, "nspname");
2299 int i_relname = PQfnumber(res, "relname");
2300
2301 if (ntups == 0)
2302 return;
2303
2304 if (report->file == NULL &&
2305 (report->file = fopen_priv(report->path, "w")) == NULL)
2306 pg_fatal("could not open file \"%s\": %m", report->path);
2307
2308 for (int i = 0; i < ntups; i++)
2309 fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n",
2310 PQgetvalue(res, i, i_srsubstate),
2311 dbinfo->db_name,
2312 PQgetvalue(res, i, i_subname),
2313 PQgetvalue(res, i, i_nspname),
2314 PQgetvalue(res, i, i_relname));
2315}

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

Referenced by check_old_cluster_subscription_state().

◆ process_unicode_update()

static void process_unicode_update ( DbInfo dbinfo,
PGresult res,
void arg 
)
static

Definition at line 1864 of file check.c.

1865{
1867 int ntups = PQntuples(res);
1868 int i_reloid = PQfnumber(res, "reloid");
1869 int i_nspname = PQfnumber(res, "nspname");
1870 int i_relname = PQfnumber(res, "relname");
1871
1872 if (ntups == 0)
1873 return;
1874
1875 if (report->file == NULL &&
1876 (report->file = fopen_priv(report->path, "w")) == NULL)
1877 pg_fatal("could not open file \"%s\": %m", report->path);
1878
1879 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1880
1881 for (int rowno = 0; rowno < ntups; rowno++)
1882 fprintf(report->file, " (oid=%s) %s.%s\n",
1883 PQgetvalue(res, rowno, i_reloid),
1884 PQgetvalue(res, rowno, i_nspname),
1885 PQgetvalue(res, rowno, i_relname));
1886}

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

Referenced by check_for_unicode_update().

◆ process_user_defined_encoding_conversions()

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

Definition at line 1784 of file check.c.

1785{
1787 int ntups = PQntuples(res);
1788 int i_conoid = PQfnumber(res, "conoid");
1789 int i_conname = PQfnumber(res, "conname");
1790 int i_nspname = PQfnumber(res, "nspname");
1791
1792 if (ntups == 0)
1793 return;
1794
1795 if (report->file == NULL &&
1796 (report->file = fopen_priv(report->path, "w")) == NULL)
1797 pg_fatal("could not open file \"%s\": %m", report->path);
1798
1799 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1800
1801 for (int rowno = 0; rowno < ntups; rowno++)
1802 fprintf(report->file, " (oid=%s) %s.%s\n",
1803 PQgetvalue(res, rowno, i_conoid),
1804 PQgetvalue(res, rowno, i_nspname),
1805 PQgetvalue(res, rowno, i_conname));
1806}

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

Referenced by check_for_user_defined_encoding_conversions().

◆ process_user_defined_postfix_ops()

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

Definition at line 1336 of file check.c.

1337{
1339 int ntups = PQntuples(res);
1340 int i_oproid = PQfnumber(res, "oproid");
1341 int i_oprnsp = PQfnumber(res, "oprnsp");
1342 int i_oprname = PQfnumber(res, "oprname");
1343 int i_typnsp = PQfnumber(res, "typnsp");
1344 int i_typname = PQfnumber(res, "typname");
1345
1346 if (ntups == 0)
1347 return;
1348
1349 if (report->file == NULL &&
1350 (report->file = fopen_priv(report->path, "w")) == NULL)
1351 pg_fatal("could not open file \"%s\": %m", report->path);
1352
1353 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1354
1355 for (int rowno = 0; rowno < ntups; rowno++)
1356 fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n",
1357 PQgetvalue(res, rowno, i_oproid),
1358 PQgetvalue(res, rowno, i_oprnsp),
1359 PQgetvalue(res, rowno, i_oprname),
1360 PQgetvalue(res, rowno, i_typnsp),
1361 PQgetvalue(res, rowno, i_typname));
1362}

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

Referenced by check_for_user_defined_postfix_ops().

◆ process_with_oids_check()

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

Definition at line 1555 of file check.c.

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

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

Referenced by check_for_tables_with_oids().

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 715 of file check.c.

716{
717 if (user_opts.check)
718 {
719 pg_log(PG_REPORT, "\n*Clusters are compatible*");
720 /* stops new cluster */
721 stop_postmaster(false);
722
724 exit(0);
725 }
726
727 pg_log(PG_REPORT, "\n"
728 "If pg_upgrade fails after this point, you must re-initdb the\n"
729 "new cluster before continuing.");
730}
void cleanup_output_dirs(void)
Definition util.c:63

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

Referenced by main().

◆ unicode_version_changed()

static bool unicode_version_changed ( ClusterInfo cluster)
static

Definition at line 1893 of file check.c.

1894{
1896 PGresult *res;
1897 char *old_unicode_version;
1898 bool unicode_updated;
1899
1900 res = executeQueryOrDie(conn_template1, "SELECT unicode_version()");
1901 old_unicode_version = PQgetvalue(res, 0, 0);
1903
1904 PQclear(res);
1906
1907 return unicode_updated;
1908}
#define PG_UNICODE_VERSION

References connectToServer(), executeQueryOrDie(), fb(), PG_UNICODE_VERSION, PQclear, PQfinish(), and PQgetvalue.

Referenced by check_for_unicode_update().

Variable Documentation

◆ data_types_usage_checks

DataTypesUsageChecks data_types_usage_checks[]
static

Definition at line 102 of file check.c.

103{
104 /*
105 * Look for composite types that were made during initdb *or* belong to
106 * information_schema; that's important in case information_schema was
107 * dropped and reloaded.
108 *
109 * The cutoff OID here should match the source cluster's value of
110 * FirstNormalObjectId. We hardcode it rather than using that C #define
111 * because, if that #define is ever changed, our own version's value is
112 * NOT what to use. Eventually we may need a test on the source cluster's
113 * version to select the correct value.
114 */
115 {
116 .status = gettext_noop("Checking for system-defined composite types in user tables"),
117 .report_filename = "tables_using_composite.txt",
118 .base_query =
119 "SELECT t.oid FROM pg_catalog.pg_type t "
120 "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
121 " WHERE typtype = 'c' AND (t.oid < 16384 OR nspname = 'information_schema')",
122 .report_text =
123 gettext_noop("Your installation contains system-defined composite types in user tables.\n"
124 "These type OIDs are not stable across PostgreSQL versions,\n"
125 "so this cluster cannot currently be upgraded. You can drop the\n"
126 "problem columns and restart the upgrade.\n"),
127 .threshold_version = ALL_VERSIONS
128 },
129
130 /*
131 * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid
132 * pg_enum.oid
133 *
134 * Many of the reg* data types reference system catalog info that is not
135 * preserved, and hence these data types cannot be used in user tables
136 * upgraded by pg_upgrade.
137 */
138 {
139 .status = gettext_noop("Checking for reg* data types in user tables"),
140 .report_filename = "tables_using_reg.txt",
141
142 /*
143 * Note: older servers will not have all of these reg* types, so we
144 * have to write the query like this rather than depending on casts to
145 * regtype.
146 */
147 .base_query =
148 "SELECT oid FROM pg_catalog.pg_type t "
149 "WHERE t.typnamespace = "
150 " (SELECT oid FROM pg_catalog.pg_namespace "
151 " WHERE nspname = 'pg_catalog') "
152 " AND t.typname IN ( "
153 /* pg_class.oid is preserved, so 'regclass' is OK */
154 " 'regcollation', "
155 " 'regconfig', "
156 /* pg_database.oid is preserved, so 'regdatabase' is OK */
157 " 'regdictionary', "
158 " 'regnamespace', "
159 " 'regoper', "
160 " 'regoperator', "
161 " 'regproc', "
162 " 'regprocedure' "
163 /* pg_authid.oid is preserved, so 'regrole' is OK */
164 /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
165 " )",
166 .report_text =
167 gettext_noop("Your installation contains one of the reg* data types in user tables.\n"
168 "These data types reference system OIDs that are not preserved by\n"
169 "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
170 "drop the problem columns and restart the upgrade.\n"),
171 .threshold_version = ALL_VERSIONS
172 },
173
174 /*
175 * PG 16 increased the size of the 'aclitem' type, which breaks the
176 * on-disk format for existing data.
177 */
178 {
179 .status = gettext_noop("Checking for incompatible \"aclitem\" data type"),
180 .report_filename = "tables_using_aclitem.txt",
181 .base_query =
182 "SELECT 'pg_catalog.aclitem'::pg_catalog.regtype AS oid",
183 .report_text =
184 gettext_noop("Your installation contains the \"aclitem\" data type in user tables.\n"
185 "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
186 "so this cluster cannot currently be upgraded. You can drop the\n"
187 "problem columns and restart the upgrade.\n"),
188 .threshold_version = 1500
189 },
190
191 /*
192 * PG 12 changed the 'sql_identifier' type storage to be based on name,
193 * not varchar, which breaks on-disk format for existing data. So we need
194 * to prevent upgrade when used in user objects (tables, indexes, ...). In
195 * 12, the sql_identifier data type was switched from name to varchar,
196 * which does affect the storage (name is by-ref, but not varlena). This
197 * means user tables using sql_identifier for columns are broken because
198 * the on-disk format is different.
199 */
200 {
201 .status = gettext_noop("Checking for invalid \"sql_identifier\" user columns"),
202 .report_filename = "tables_using_sql_identifier.txt",
203 .base_query =
204 "SELECT 'information_schema.sql_identifier'::pg_catalog.regtype AS oid",
205 .report_text =
206 gettext_noop("Your installation contains the \"sql_identifier\" data type in user tables.\n"
207 "The on-disk format for this data type has changed, so this\n"
208 "cluster cannot currently be upgraded. You can drop the problem\n"
209 "columns and restart the upgrade.\n"),
210 .threshold_version = 1100
211 },
212
213 /*
214 * PG 12 removed types abstime, reltime, tinterval.
215 */
216 {
217 .status = gettext_noop("Checking for removed \"abstime\" data type in user tables"),
218 .report_filename = "tables_using_abstime.txt",
219 .base_query =
220 "SELECT 'pg_catalog.abstime'::pg_catalog.regtype AS oid",
221 .report_text =
222 gettext_noop("Your installation contains the \"abstime\" data type in user tables.\n"
223 "The \"abstime\" type has been removed in PostgreSQL version 12,\n"
224 "so this cluster cannot currently be upgraded. You can drop the\n"
225 "problem columns, or change them to another data type, and restart\n"
226 "the upgrade.\n"),
227 .threshold_version = 1100
228 },
229 {
230 .status = gettext_noop("Checking for removed \"reltime\" data type in user tables"),
231 .report_filename = "tables_using_reltime.txt",
232 .base_query =
233 "SELECT 'pg_catalog.reltime'::pg_catalog.regtype AS oid",
234 .report_text =
235 gettext_noop("Your installation contains the \"reltime\" data type in user tables.\n"
236 "The \"reltime\" type has been removed in PostgreSQL version 12,\n"
237 "so this cluster cannot currently be upgraded. You can drop the\n"
238 "problem columns, or change them to another data type, and restart\n"
239 "the upgrade.\n"),
240 .threshold_version = 1100
241 },
242 {
243 .status = gettext_noop("Checking for removed \"tinterval\" data type in user tables"),
244 .report_filename = "tables_using_tinterval.txt",
245 .base_query =
246 "SELECT 'pg_catalog.tinterval'::pg_catalog.regtype AS oid",
247 .report_text =
248 gettext_noop("Your installation contains the \"tinterval\" data type in user tables.\n"
249 "The \"tinterval\" type has been removed in PostgreSQL version 12,\n"
250 "so this cluster cannot currently be upgraded. You can drop the\n"
251 "problem columns, or change them to another data type, and restart\n"
252 "the upgrade.\n"),
253 .threshold_version = 1100
254 },
255
256 /* End of checks marker, must remain last */
257 {
258 NULL, NULL, NULL, NULL, 0, NULL
259 }
260};
#define gettext_noop(x)
Definition c.h:1325

Referenced by check_for_data_types_usage(), and data_type_check_query().