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

◆ MANUAL_CHECK

#define MANUAL_CHECK   1

Definition at line 67 of file check.c.

Function Documentation

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( void  )

Definition at line 593 of file check.c.

594{
595 /* -- OLD -- */
596
599
600 /*
601 * First check that all databases allow connections since we'll otherwise
602 * fail in later stages.
603 */
605
606 /*
607 * Check for encodings that are no longer supported.
608 */
610
611 /*
612 * Validate database, user, role and tablespace names from the old
613 * cluster. No need to check in 19 or newer as newline and carriage return
614 * are not allowed at the creation time of the object.
615 */
618
619 /*
620 * Extract a list of databases, tables, and logical replication slots from
621 * the old cluster.
622 */
624
626
628
629
630 /*
631 * Check for various failure cases
632 */
636
638 {
639 /*
640 * Logical replication slots can be migrated since PG17. See comments
641 * in get_db_rel_and_slot_infos().
642 */
644
645 /*
646 * Subscriptions and their dependencies can be migrated since PG17.
647 * Before that the logical slots are not upgraded, so we will not be
648 * able to upgrade the logical replication clusters completely.
649 */
652 }
653
655
656 /*
657 * Unicode updates can affect some objects that use expressions with
658 * functions dependent on Unicode.
659 */
661
662 /*
663 * PG 14 changed the function signature of encoding conversion functions.
664 * Conversions from older versions cannot be upgraded automatically
665 * because the user-defined functions used by the encoding conversions
666 * need to be changed to match the new signature.
667 */
670
671 /*
672 * Pre-PG 14 allowed user defined postfix operators, which are not
673 * supported anymore. Verify there are none, iff applicable.
674 */
677
678 /*
679 * PG 14 changed polymorphic functions from anyarray to
680 * anycompatiblearray.
681 */
684
685 /*
686 * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
687 * supported anymore. Verify there are none, iff applicable.
688 */
691
692 /*
693 * Pre-PG 18 allowed child tables to omit not-null constraints that their
694 * parents columns have, but schema restore fails for them. Verify there
695 * are none, iff applicable.
696 */
699
700 /*
701 * The btree_gist extension contains gist_inet_ops and gist_cidr_ops
702 * opclasses that do not reliably give correct answers. We want to
703 * deprecate and eventually remove those, and as a first step v19 marks
704 * them not-opcdefault and instead marks the replacement in-core opclass
705 * "inet_ops" as opcdefault. That creates a problem for pg_upgrade: in
706 * versions where those opclasses were marked opcdefault, pg_dump will
707 * dump indexes using them with no explicit opclass specification, so that
708 * restore would create them using the inet_ops opclass. That would be
709 * incompatible with what's actually in the on-disk files. So refuse to
710 * upgrade if there are any such indexes.
711 */
714
715 /*
716 * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
717 * hash indexes
718 */
720 {
721 if (user_opts.check)
723 }
724
725 /* 9.5 and below should not have roles starting with pg_ */
728
729 /*
730 * While not a check option, we do this now because this is the only time
731 * the old server is running.
732 */
733 if (!user_opts.check)
735
737 stop_postmaster(false);
738}
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition check.c:1677
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition check.c:1879
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition check.c:468
static void check_for_gist_inet_ops(ClusterInfo *cluster)
Definition check.c:1833
static void check_old_cluster_subscription_state(void)
Definition check.c:2478
static void check_for_unicode_update(ClusterInfo *cluster)
Definition check.c:2071
static void check_is_install_user(ClusterInfo *cluster)
Definition check.c:1110
static void check_for_not_null_inheritance(ClusterInfo *cluster)
Definition check.c:1754
static void check_for_connection_status(ClusterInfo *cluster)
Definition check.c:1168
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition check.c:1377
static void check_for_unsupported_encodings(ClusterInfo *cluster)
Definition check.c:1253
static void check_old_cluster_for_valid_slots(void)
Definition check.c:2356
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition check.c:1462
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition check.c:1314
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition check.c:1965
static void check_old_cluster_global_names(ClusterInfo *cluster)
Definition check.c:2585
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition check.c:1550
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:840
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition info.c:279
static pid_t start_postmaster(void)
Definition pg_ctl.c:441
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
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition version.c:55
UserOpts user_opts
Definition option.c:30
uint32 major_version
Definition pg_upgrade.h:307
bool live_check
Definition pg_upgrade.h:342
bool check
Definition pg_upgrade.h:341

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

938{
939 /* get/check pg_control data of servers */
943
945 pg_fatal("When checking a live server, "
946 "the old and new port numbers must be different.");
947}
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:306
ControlData controldata
Definition pg_upgrade.h:296

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

883{
884 prep_status("Checking cluster versions");
885
886 /* cluster versions should already have been obtained */
889
890 /*
891 * We allow upgrades from/to the same major version for alpha/beta
892 * upgrades
893 */
894
896 pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
897 "9.2");
898
899 /* Only current PG version is supported as a target */
901 pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
903
904 /*
905 * We can't allow downgrading because we use the target pg_dump, and
906 * pg_dump cannot operate on newer database versions, only current and
907 * older versions.
908 */
910 pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
911
912 /* Ensure binaries match the designated data directories */
915 pg_fatal("Old cluster data and binary directories are from different major versions.");
918 pg_fatal("New cluster data and binary directories are from different major versions.");
919
920 /*
921 * Since from version 18, newly created database clusters always have
922 * 'signed' default char-signedness, it makes less sense to use
923 * --set-char-signedness option for upgrading from version 18 or later.
924 * Users who want to change the default char signedness of the new
925 * cluster, they can use pg_resetwal manually before the upgrade.
926 */
929 pg_fatal("The option %s cannot be used for upgrades from PostgreSQL %s and later.",
930 "--set-char-signedness", "18");
931
932 check_ok();
933}
#define Assert(condition)
Definition c.h:943
static void check_ok(void)
Definition initdb.c:2132
void prep_status(const char *fmt,...) pg_attribute_printf(1
static int fb(int x)
uint32 bin_version
Definition pg_upgrade.h:309
int char_signedness
Definition pg_upgrade.h:349

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

1169{
1170 int dbnum;
1172 PGresult *dbres;
1173 int ntups;
1174 int i_datname;
1175 int i_datallowconn;
1176 int i_datconnlimit;
1177 FILE *script = NULL;
1178 char output_path[MAXPGPATH];
1179
1180 prep_status("Checking database connection settings");
1181
1182 snprintf(output_path, sizeof(output_path), "%s/%s",
1184 "databases_cannot_connect_to.txt");
1185
1186 conn_template1 = connectToServer(cluster, "template1");
1187
1188 /* get database names */
1190 "SELECT datname, datallowconn, datconnlimit "
1191 "FROM pg_catalog.pg_database");
1192
1193 i_datname = PQfnumber(dbres, "datname");
1194 i_datallowconn = PQfnumber(dbres, "datallowconn");
1195 i_datconnlimit = PQfnumber(dbres, "datconnlimit");
1196
1197 ntups = PQntuples(dbres);
1198 for (dbnum = 0; dbnum < ntups; dbnum++)
1199 {
1200 char *datname = PQgetvalue(dbres, dbnum, i_datname);
1203
1204 if (strcmp(datname, "template0") == 0)
1205 {
1206 /* avoid restore failure when pg_dumpall tries to create template0 */
1207 if (strcmp(datallowconn, "t") == 0)
1208 pg_fatal("template0 must not allow connections, "
1209 "i.e. its pg_database.datallowconn must be false");
1210 }
1211 else
1212 {
1213 /*
1214 * Avoid datallowconn == false databases from being skipped on
1215 * restore, and ensure that no databases are marked invalid with
1216 * datconnlimit == -2.
1217 */
1218 if ((strcmp(datallowconn, "f") == 0) || strcmp(datconnlimit, "-2") == 0)
1219 {
1220 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1221 pg_fatal("could not open file \"%s\": %m", output_path);
1222
1223 fprintf(script, "%s\n", datname);
1224 }
1225 }
1226 }
1227
1228 PQclear(dbres);
1229
1231
1232 if (script)
1233 {
1234 fclose(script);
1235 pg_log(PG_REPORT, "fatal");
1236 pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
1237 "pg_database.datallowconn must be true and pg_database.datconnlimit\n"
1238 "must not be -2. Your installation contains non-template0 databases\n"
1239 "which cannot be connected to. Consider allowing connection for all\n"
1240 "non-template0 databases or drop the databases which do not allow\n"
1241 "connections. A list of databases with the problem is in the file:\n"
1242 " %s", output_path);
1243 }
1244 else
1245 check_ok();
1246}
#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:3606
#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:439
@ PG_REPORT
Definition pg_upgrade.h:283
#define snprintf
Definition port.h:260
char * basedir
Definition pg_upgrade.h:329

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

469{
470 PQExpBuffer report = NULL;
474 char **queries = NULL;
475 struct data_type_check_state *states;
476
477 prep_status("Checking data type usage");
478
479 /* Gather number of checks to perform */
480 while (tmp->status != NULL)
481 {
483 tmp++;
484 }
485
486 /* Allocate memory for queries and for task states */
489
490 for (int i = 0; i < n_data_types_usage_checks; i++)
491 {
493
495 {
497
498 /*
499 * Make sure that the check applies to the current cluster version
500 * and skip it if not.
501 */
503 continue;
504 }
506 {
507 if (GET_MAJOR_VERSION(cluster->major_version) > check->threshold_version)
508 continue;
509 }
510 else
512
513 queries[i] = data_type_check_query(i);
514
515 states[i].check = check;
516 states[i].report = &report;
517
519 true, &states[i]);
520 }
521
522 /*
523 * Connect to each database in the cluster and run all defined checks
524 * against that database before trying the next one.
525 */
528
529 if (report)
530 {
531 pg_fatal("Data type checks failed: %s", report->data);
533 }
534
535 for (int i = 0; i < n_data_types_usage_checks; i++)
536 {
537 if (queries[i])
538 pg_free(queries[i]);
539 }
540 pg_free(queries);
541 pg_free(states);
542
543 check_ok();
544}
static char * data_type_check_query(int checknum)
Definition check.c:339
static DataTypesUsageChecks data_types_usage_checks[]
Definition check.c:103
#define ALL_VERSIONS
Definition check.c:68
#define MANUAL_CHECK
Definition check.c:67
static void process_data_type_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:396
void pg_free(void *ptr)
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:57
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:59
const char * status
Definition check.c:49
PQExpBuffer * report
Definition check.c:331
DataTypesUsageChecks * check
Definition check.c:329

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

1834{
1835 UpgradeTaskReport report;
1837 const char *query = "SELECT nc.nspname, cc.relname "
1838 "FROM pg_catalog.pg_opclass oc, pg_catalog.pg_index i, "
1839 " pg_catalog.pg_class cc, pg_catalog.pg_namespace nc "
1840 "WHERE oc.opcmethod = " CppAsString2(GIST_AM_OID)
1841 " AND oc.opcname IN ('gist_inet_ops', 'gist_cidr_ops')"
1842 " AND oc.opcdefault"
1843 " AND oc.oid = any(i.indclass)"
1844 " AND i.indexrelid = cc.oid AND cc.relnamespace = nc.oid";
1845
1846 prep_status("Checking for uses of gist_inet_ops/gist_cidr_ops");
1847
1848 report.file = NULL;
1849 snprintf(report.path, sizeof(report.path), "%s/%s",
1851 "gist_inet_ops.txt");
1852
1854 true, &report);
1857
1858 if (report.file)
1859 {
1860 fclose(report.file);
1861 pg_log(PG_REPORT, "fatal");
1862 pg_fatal("Your installation contains indexes that use btree_gist's\n"
1863 "gist_inet_ops or gist_cidr_ops opclasses,\n"
1864 "which cannot be binary-upgraded. Replace them with indexes\n"
1865 "that use the built-in GiST inet_ops opclass.\n"
1866 "A list of indexes with the problem is in the file:\n"
1867 " %s", report.path);
1868 }
1869 else
1870 check_ok();
1871}
#define CppAsString2(x)
Definition c.h:506
static void process_gist_inet_ops_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1805
char path[MAXPGPATH]
Definition pg_upgrade.h:539

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

1551{
1554 UpgradeTaskReport report;
1555 char *query;
1556
1557 prep_status("Checking for incompatible polymorphic functions");
1558
1559 report.file = NULL;
1560 snprintf(report.path, sizeof(report.path), "%s/%s",
1562 "incompatible_polymorphics.txt");
1563
1564 /* The set of problematic functions varies a bit in different versions */
1566
1568 "'array_append(anyarray,anyelement)'"
1569 ", 'array_cat(anyarray,anyarray)'"
1570 ", 'array_prepend(anyelement,anyarray)'");
1571
1572 if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
1574 ", 'array_remove(anyarray,anyelement)'"
1575 ", 'array_replace(anyarray,anyelement,anyelement)'");
1576
1577 if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
1579 ", 'array_position(anyarray,anyelement)'"
1580 ", 'array_position(anyarray,anyelement,integer)'"
1581 ", 'array_positions(anyarray,anyelement)'"
1582 ", 'width_bucket(anyelement,anyarray)'");
1583
1584 /*
1585 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1586 * interpolating that C #define into the query because, if that #define is
1587 * ever changed, the cutoff we want to use is the value used by
1588 * pre-version 14 servers, not that of some future version.
1589 */
1590
1591 /* Aggregate transition functions */
1592 query = psprintf("SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1593 "FROM pg_proc AS p "
1594 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1595 "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1596 "WHERE p.oid >= 16384 "
1597 "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1598 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1599
1600 /* Aggregate final functions */
1601 "UNION ALL "
1602 "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1603 "FROM pg_proc AS p "
1604 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1605 "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1606 "WHERE p.oid >= 16384 "
1607 "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1608 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1609
1610 /* Operators */
1611 "UNION ALL "
1612 "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1613 "FROM pg_operator AS op "
1614 "WHERE op.oid >= 16384 "
1615 "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
1616 "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[])",
1617 old_polymorphics.data,
1618 old_polymorphics.data,
1619 old_polymorphics.data);
1620
1622 true, &report);
1625
1626 if (report.file)
1627 {
1628 fclose(report.file);
1629 pg_log(PG_REPORT, "fatal");
1630 pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1631 "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1632 "These user-defined objects must be dropped before upgrading and restored\n"
1633 "afterwards, changing them to refer to the new corresponding functions with\n"
1634 "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1635 "A list of the problematic objects is in the file:\n"
1636 " %s", report.path);
1637 }
1638 else
1639 check_ok();
1640
1642 pg_free(query);
1643}
static void process_incompat_polymorphics(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1521
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, 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 1377 of file check.c.

1378{
1380 UpgradeTaskReport report;
1381 const char *query = "SELECT n.nspname, p.proname "
1382 "FROM pg_catalog.pg_proc p, "
1383 " pg_catalog.pg_namespace n "
1384 "WHERE p.pronamespace = n.oid AND "
1385 " p.probin = '$libdir/isn'";
1386
1387 prep_status("Checking for contrib/isn with bigint-passing mismatch");
1388
1391 {
1392 /* no mismatch */
1393 check_ok();
1394 return;
1395 }
1396
1397 report.file = NULL;
1398 snprintf(report.path, sizeof(report.path), "%s/%s",
1400 "contrib_isn_and_int8_pass_by_value.txt");
1401
1404 true, &report);
1407
1408 if (report.file)
1409 {
1410 fclose(report.file);
1411 pg_log(PG_REPORT, "fatal");
1412 pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
1413 "bigint data type. Your old and new clusters pass bigint values\n"
1414 "differently so this cluster cannot currently be upgraded. You can\n"
1415 "manually dump databases in the old cluster that use \"contrib/isn\"\n"
1416 "facilities, drop them, perform the upgrade, and then restore them. A\n"
1417 "list of the problem functions is in the file:\n"
1418 " %s", report.path);
1419 }
1420 else
1421 check_ok();
1422}
static void process_isn_and_int8_passing_mismatch(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1347
bool float8_pass_by_value
Definition pg_upgrade.h:258

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

984{
985 int tblnum;
987
988 prep_status("Checking for new cluster tablespace directories");
989
991 {
992 struct stat statbuf;
993
997
998 if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
999 pg_fatal("new cluster tablespace directory already exists: \"%s\"",
1001 }
1002
1003 check_ok();
1004}
int num_tablespaces
Definition pg_upgrade.h:311
char ** tablespaces
Definition pg_upgrade.h:310
const char * tablespace_suffix
Definition pg_upgrade.h:312
#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 1754 of file check.c.

1755{
1756 UpgradeTaskReport report;
1758 const char *query;
1759
1760 prep_status("Checking for not-null constraint inconsistencies");
1761
1762 report.file = NULL;
1763 snprintf(report.path, sizeof(report.path), "%s/%s",
1765 "not_null_inconsistent_columns.txt");
1766
1767 query = "SELECT nspname, cc.relname, ac.attname "
1768 "FROM pg_catalog.pg_inherits i, pg_catalog.pg_attribute ac, "
1769 " pg_catalog.pg_attribute ap, pg_catalog.pg_class cc, "
1770 " pg_catalog.pg_namespace nc "
1771 "WHERE cc.oid = ac.attrelid AND i.inhrelid = ac.attrelid "
1772 " AND i.inhparent = ap.attrelid AND ac.attname = ap.attname "
1773 " AND cc.relnamespace = nc.oid "
1774 " AND ap.attnum > 0 and ap.attnotnull AND NOT ac.attnotnull";
1775
1779 true, &report);
1782
1783 if (report.file)
1784 {
1785 fclose(report.file);
1786 pg_log(PG_REPORT, "fatal");
1787 pg_fatal("Your installation contains inconsistent NOT NULL constraints.\n"
1788 "If the parent column(s) are NOT NULL, then the child column must\n"
1789 "also be marked NOT NULL, or the upgrade will fail.\n"
1790 "You can fix this by running\n"
1791 " ALTER TABLE tablename ALTER column SET NOT NULL;\n"
1792 "on each column listed in the file:\n"
1793 " %s", report.path);
1794 }
1795 else
1796 check_ok();
1797}
static void process_inconsistent_notnull(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1719

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

static void check_for_pg_role_prefix ( ClusterInfo cluster)
static

Definition at line 1879 of file check.c.

1880{
1881 PGresult *res;
1882 PGconn *conn = connectToServer(cluster, "template1");
1883 int ntups;
1884 int i_roloid;
1885 int i_rolname;
1886 FILE *script = NULL;
1887 char output_path[MAXPGPATH];
1888
1889 prep_status("Checking for roles starting with \"pg_\"");
1890
1891 snprintf(output_path, sizeof(output_path), "%s/%s",
1893 "pg_role_prefix.txt");
1894
1895 res = executeQueryOrDie(conn,
1896 "SELECT oid AS roloid, rolname "
1897 "FROM pg_catalog.pg_roles "
1898 "WHERE rolname ~ '^pg_'");
1899
1900 ntups = PQntuples(res);
1901 i_roloid = PQfnumber(res, "roloid");
1902 i_rolname = PQfnumber(res, "rolname");
1903 for (int rowno = 0; rowno < ntups; rowno++)
1904 {
1905 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1906 pg_fatal("could not open file \"%s\": %m", output_path);
1907 fprintf(script, "%s (oid=%s)\n",
1908 PQgetvalue(res, rowno, i_rolname),
1909 PQgetvalue(res, rowno, i_roloid));
1910 }
1911
1912 PQclear(res);
1913
1914 PQfinish(conn);
1915
1916 if (script)
1917 {
1918 fclose(script);
1919 pg_log(PG_REPORT, "fatal");
1920 pg_fatal("Your installation contains roles starting with \"pg_\".\n"
1921 "\"pg_\" is a reserved prefix for system roles. The cluster\n"
1922 "cannot be upgraded until these roles are renamed.\n"
1923 "A list of roles starting with \"pg_\" is in the file:\n"
1924 " %s", output_path);
1925 }
1926 else
1927 check_ok();
1928}
PGconn * conn
Definition streamutil.c:52

References LogOpts::basedir, check_ok(), conn, connectToServer(), 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_prepared_transactions()

static void check_for_prepared_transactions ( ClusterInfo cluster)
static

Definition at line 1314 of file check.c.

1315{
1316 PGresult *res;
1317 PGconn *conn = connectToServer(cluster, "template1");
1318
1319 prep_status("Checking for prepared transactions");
1320
1321 res = executeQueryOrDie(conn,
1322 "SELECT * "
1323 "FROM pg_catalog.pg_prepared_xacts");
1324
1325 if (PQntuples(res) != 0)
1326 {
1327 if (cluster == &old_cluster)
1328 pg_fatal("The source cluster contains prepared transactions");
1329 else
1330 pg_fatal("The target cluster contains prepared transactions");
1331 }
1332
1333 PQclear(res);
1334
1335 PQfinish(conn);
1336
1337 check_ok();
1338}

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

1678{
1679 UpgradeTaskReport report;
1681 const char *query = "SELECT n.nspname, c.relname "
1682 "FROM pg_catalog.pg_class c, "
1683 " pg_catalog.pg_namespace n "
1684 "WHERE c.relnamespace = n.oid AND "
1685 " c.relhasoids AND"
1686 " n.nspname NOT IN ('pg_catalog')";
1687
1688 prep_status("Checking for tables WITH OIDS");
1689
1690 report.file = NULL;
1691 snprintf(report.path, sizeof(report.path), "%s/%s",
1693 "tables_with_oids.txt");
1694
1696 true, &report);
1699
1700 if (report.file)
1701 {
1702 fclose(report.file);
1703 pg_log(PG_REPORT, "fatal");
1704 pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1705 "supported anymore. Consider removing the oid column using\n"
1706 " ALTER TABLE ... SET WITHOUT OIDS;\n"
1707 "A list of tables with the problem is in the file:\n"
1708 " %s", report.path);
1709 }
1710 else
1711 check_ok();
1712}
static void process_with_oids_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1651

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

2072{
2073 UpgradeTaskReport report;
2075 const char *query;
2076
2077 /*
2078 * The builtin provider did not exist prior to version 17. While there are
2079 * still problems that could potentially be caught from earlier versions,
2080 * such as an index on NORMALIZE(), we don't check for that here.
2081 */
2082 if (GET_MAJOR_VERSION(cluster->major_version) < 1700)
2083 return;
2084
2085 prep_status("Checking for objects affected by Unicode update");
2086
2088 {
2089 check_ok();
2090 return;
2091 }
2092
2093 report.file = NULL;
2094 snprintf(report.path, sizeof(report.path), "%s/%s",
2096 "unicode_dependent_rels.txt");
2097
2098 query =
2099 /* collations that use built-in Unicode for character semantics */
2100 "WITH collations(collid) AS ( "
2101 " SELECT oid FROM pg_collation "
2102 " WHERE collprovider='b' AND colllocale IN ('C.UTF-8','PG_UNICODE_FAST') "
2103 /* include default collation, if appropriate */
2104 " UNION "
2105 " SELECT 'pg_catalog.default'::regcollation FROM pg_database "
2106 " WHERE datname = current_database() AND "
2107 " datlocprovider='b' AND datlocale IN ('C.UTF-8','PG_UNICODE_FAST') "
2108 "), "
2109 /* functions that use built-in Unicode */
2110 "functions(procid) AS ( "
2111 " SELECT proc.oid FROM pg_proc proc "
2112 " WHERE proname IN ('normalize','unicode_assigned','unicode_version','is_normalized') AND "
2113 " pronamespace='pg_catalog'::regnamespace "
2114 "), "
2115 /* operators that use the input collation for character semantics */
2116 "coll_operators(operid, procid, collid) AS ( "
2117 " SELECT oper.oid, oper.oprcode, collid FROM pg_operator oper, collations "
2118 " WHERE oprname IN ('~', '~*', '!~', '!~*', '~~*', '!~~*') AND "
2119 " oprnamespace='pg_catalog'::regnamespace AND "
2120 " oprright='pg_catalog.text'::pg_catalog.regtype "
2121 "), "
2122 /* functions that use the input collation for character semantics */
2123 "coll_functions(procid, collid) AS ( "
2124 " SELECT proc.oid, collid FROM pg_proc proc, collations "
2125 " WHERE pronamespace='pg_catalog'::regnamespace AND "
2126 " ((proname IN ('lower','initcap','upper','casefold') AND "
2127 " pronargs = 1 AND "
2128 " proargtypes[0] = 'pg_catalog.text'::pg_catalog.regtype) OR "
2129 " (proname = 'substring' AND pronargs = 2 AND "
2130 " proargtypes[0] = 'pg_catalog.text'::pg_catalog.regtype AND "
2131 " proargtypes[1] = 'pg_catalog.text'::pg_catalog.regtype) OR "
2132 " proname LIKE 'regexp_%') "
2133 /* include functions behind the operators listed above */
2134 " UNION "
2135 " SELECT procid, collid FROM coll_operators "
2136 "), "
2137
2138 /*
2139 * Generate patterns to search a pg_node_tree for the above functions and
2140 * operators.
2141 */
2142 "patterns(p) AS ( "
2143 " SELECT '{FUNCEXPR :funcid ' || procid::text || '[ }]' FROM functions "
2144 " UNION "
2145 " SELECT '{OPEXPR :opno ' || operid::text || ' (:\\w+ \\w+ )*' || "
2146 " ':inputcollid ' || collid::text || '[ }]' FROM coll_operators "
2147 " UNION "
2148 " SELECT '{FUNCEXPR :funcid ' || procid::text || ' (:\\w+ \\w+ )*' || "
2149 " ':inputcollid ' || collid::text || '[ }]' FROM coll_functions "
2150 ") "
2151
2152 /*
2153 * Match the patterns against expressions used for relation contents.
2154 */
2155 "SELECT reloid, relkind, nspname, relname "
2156 " FROM ( "
2157 " SELECT conrelid "
2158 " FROM pg_constraint, patterns WHERE conbin::text ~ p "
2159 " UNION "
2160 " SELECT indexrelid "
2161 " FROM pg_index, patterns WHERE indexprs::text ~ p OR indpred::text ~ p "
2162 " UNION "
2163 " SELECT partrelid "
2164 " FROM pg_partitioned_table, patterns WHERE partexprs::text ~ p "
2165 " UNION "
2166 " SELECT ev_class "
2167 " FROM pg_rewrite, pg_class, patterns "
2168 " WHERE ev_class = pg_class.oid AND relkind = 'm' AND ev_action::text ~ p"
2169 " ) s(reloid), pg_class c, pg_namespace n, pg_database d "
2170 " WHERE s.reloid = c.oid AND c.relnamespace = n.oid AND "
2171 " d.datname = current_database() AND "
2172 " d.encoding = pg_char_to_encoding('UTF8');";
2173
2177 true, &report);
2180
2181 if (report.file)
2182 {
2183 fclose(report.file);
2184 report_status(PG_WARNING, "warning");
2185 pg_log(PG_WARNING, "Your installation contains relations that might be affected by a new version of Unicode.\n"
2186 "A list of potentially-affected relations is in the file:\n"
2187 " %s", report.path);
2188 }
2189 else
2190 check_ok();
2191}
static bool unicode_version_changed(ClusterInfo *cluster)
Definition check.c:2046
static void process_unicode_update(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:2017
@ PG_WARNING
Definition pg_upgrade.h:284
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 1253 of file check.c.

1254{
1255 int i_datname;
1256 int i_encoding;
1257 int ntups;
1258 PGresult *res;
1259 PGconn *conn;
1260 FILE *script = NULL;
1261 char output_path[MAXPGPATH];
1262
1263 prep_status("Checking for unsupported encodings");
1264
1265 snprintf(output_path, sizeof(output_path), "%s/%s",
1267 "databases_unsupported_encoding.txt");
1268
1269 conn = connectToServer(cluster, "template1");
1270
1271 res = executeQueryOrDie(conn,
1272 "SELECT datname, encoding "
1273 "FROM pg_catalog.pg_database");
1274 ntups = PQntuples(res);
1275 i_datname = PQfnumber(res, "datname");
1276 i_encoding = PQfnumber(res, "encoding");
1277 for (int rowno = 0; rowno < ntups; rowno++)
1278 {
1279 char *datname = PQgetvalue(res, rowno, i_datname);
1280 int encoding = atoi(PQgetvalue(res, rowno, i_encoding));
1281
1283 {
1284 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1285 pg_fatal("could not open file \"%s\": %m", output_path);
1286
1287 fprintf(script, "%s\n", datname);
1288 }
1289 }
1290 PQclear(res);
1291 PQfinish(conn);
1292
1293 if (script)
1294 {
1295 fclose(script);
1296 pg_log(PG_REPORT, "fatal");
1297 pg_fatal("Your installation contains databases using encodings that are\n"
1298 "no longer supported. Consider dumping and restoring with UTF8.\n"
1299 "A list of databases with unsupported encodings is in the file:\n"
1300 " %s", output_path);
1301 }
1302 else
1303 check_ok();
1304}
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 1965 of file check.c.

1966{
1967 UpgradeTaskReport report;
1969 const char *query;
1970
1971 prep_status("Checking for user-defined encoding conversions");
1972
1973 report.file = NULL;
1974 snprintf(report.path, sizeof(report.path), "%s/%s",
1976 "encoding_conversions.txt");
1977
1978 /*
1979 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1980 * interpolating that C #define into the query because, if that #define is
1981 * ever changed, the cutoff we want to use is the value used by
1982 * pre-version 14 servers, not that of some future version.
1983 */
1984 query = "SELECT c.oid as conoid, c.conname, n.nspname "
1985 "FROM pg_catalog.pg_conversion c, "
1986 " pg_catalog.pg_namespace n "
1987 "WHERE c.connamespace = n.oid AND "
1988 " c.oid >= 16384";
1989
1992 true, &report);
1995
1996 if (report.file)
1997 {
1998 fclose(report.file);
1999 pg_log(PG_REPORT, "fatal");
2000 pg_fatal("Your installation contains user-defined encoding conversions.\n"
2001 "The conversion function parameters changed in PostgreSQL version 14\n"
2002 "so this cluster cannot currently be upgraded. You can remove the\n"
2003 "encoding conversions in the old cluster and restart the upgrade.\n"
2004 "A list of user-defined encoding conversions is in the file:\n"
2005 " %s", report.path);
2006 }
2007 else
2008 check_ok();
2009}
static void process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1937

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

1463{
1464 UpgradeTaskReport report;
1466 const char *query;
1467
1468 /*
1469 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1470 * interpolating that C #define into the query because, if that #define is
1471 * ever changed, the cutoff we want to use is the value used by
1472 * pre-version 14 servers, not that of some future version.
1473 */
1474 query = "SELECT o.oid AS oproid, "
1475 " n.nspname AS oprnsp, "
1476 " o.oprname, "
1477 " tn.nspname AS typnsp, "
1478 " t.typname "
1479 "FROM pg_catalog.pg_operator o, "
1480 " pg_catalog.pg_namespace n, "
1481 " pg_catalog.pg_type t, "
1482 " pg_catalog.pg_namespace tn "
1483 "WHERE o.oprnamespace = n.oid AND "
1484 " o.oprleft = t.oid AND "
1485 " t.typnamespace = tn.oid AND "
1486 " o.oprright = 0 AND "
1487 " o.oid >= 16384";
1488
1489 prep_status("Checking for user-defined postfix operators");
1490
1491 report.file = NULL;
1492 snprintf(report.path, sizeof(report.path), "%s/%s",
1494 "postfix_ops.txt");
1495
1497 true, &report);
1500
1501 if (report.file)
1502 {
1503 fclose(report.file);
1504 pg_log(PG_REPORT, "fatal");
1505 pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
1506 "supported anymore. Consider dropping the postfix operators and replacing\n"
1507 "them with prefix operators or function calls.\n"
1508 "A list of user-defined postfix operators is in the file:\n"
1509 " %s", report.path);
1510 }
1511 else
1512 check_ok();
1513}
static void process_user_defined_postfix_ops(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:1430

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

1111{
1112 PGresult *res;
1113 PGconn *conn = connectToServer(cluster, "template1");
1114
1115 prep_status("Checking database user is the install user");
1116
1117 /* Can't use pg_authid because only superusers can view it. */
1118 res = executeQueryOrDie(conn,
1119 "SELECT rolsuper, oid "
1120 "FROM pg_catalog.pg_roles "
1121 "WHERE rolname = current_user "
1122 "AND rolname !~ '^pg_'");
1123
1124 /*
1125 * We only allow the install user in the new cluster (see comment below)
1126 * and we preserve pg_authid.oid, so this must be the install user in the
1127 * old cluster too.
1128 */
1129 if (PQntuples(res) != 1 ||
1131 pg_fatal("database user \"%s\" is not the install user",
1132 os_info.user);
1133
1134 PQclear(res);
1135
1136 res = executeQueryOrDie(conn,
1137 "SELECT COUNT(*) "
1138 "FROM pg_catalog.pg_roles "
1139 "WHERE rolname !~ '^pg_'");
1140
1141 if (PQntuples(res) != 1)
1142 pg_fatal("could not determine the number of users");
1143
1144 /*
1145 * We only allow the install user in the new cluster because other defined
1146 * users might match users defined in the old cluster and generate an
1147 * error during pg_dump restore.
1148 */
1149 if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
1150 pg_fatal("Only the install user can be defined in the new cluster.");
1151
1152 PQclear(res);
1153
1154 PQfinish(conn);
1155
1156 check_ok();
1157}
OSInfo os_info
Definition pg_upgrade.c:75
#define atooid(x)
char * user
Definition pg_upgrade.h:366

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

743{
745
747
749
750 switch (user_opts.transfer_mode)
751 {
754 break;
756 break;
759 break;
762 break;
764
765 /*
766 * We do the hard link check for --swap, too, since it's an easy
767 * way to verify the clusters are in the same file system. This
768 * allows us to take some shortcuts in the file synchronization
769 * step. With some more effort, we could probably support the
770 * separate-file-system use case, but this mode is unlikely to
771 * offer much benefit if we have to copy the files across file
772 * system boundaries.
773 */
775
776 /*
777 * There are a few known issues with using --swap to upgrade from
778 * versions older than 10. For example, the sequence tuple format
779 * changed in v10, and the visibility map format changed in 9.6.
780 * While such problems are not insurmountable (and we may have to
781 * deal with similar problems in the future, anyway), it doesn't
782 * seem worth the effort to support swap mode for upgrades from
783 * long-unsupported versions.
784 */
786 pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.",
787 "10");
788
789 break;
790 }
791
793
795
797
799
801}
static void check_new_cluster_replication_slots(void)
Definition check.c:2205
static void check_new_cluster_subscription_configuration(void)
Definition check.c:2313
static void check_new_cluster_is_empty(void)
Definition check.c:951
static void check_for_new_tablespace_dir(void)
Definition check.c:983
void check_file_clone(void)
Definition file.c:360
void check_hard_link(transferMode transfer_mode)
Definition file.c:437
void check_copy_file_range(void)
Definition file.c:400
void check_loadable_libraries(void)
Definition function.c:171
@ TRANSFER_MODE_COPY
Definition pg_upgrade.h:269
@ TRANSFER_MODE_LINK
Definition pg_upgrade.h:271
@ TRANSFER_MODE_SWAP
Definition pg_upgrade.h:272
@ TRANSFER_MODE_CLONE
Definition pg_upgrade.h:268
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition pg_upgrade.h:270
transferMode transfer_mode
Definition pg_upgrade.h:344

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(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal, 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 951 of file check.c.

952{
953 int dbnum;
954
955 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
956 {
957 int relnum;
958 RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
959
960 for (relnum = 0; relnum < rel_arr->nrels;
961 relnum++)
962 {
963 /* pg_largeobject and its index should be skipped */
964 if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
965 pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
967 rel_arr->rels[relnum].nspname,
968 rel_arr->rels[relnum].relname);
969 }
970 }
971}
DbInfoArr dbarr
Definition pg_upgrade.h:298
DbInfo * dbs
Definition pg_upgrade.h:227
char * db_name
Definition pg_upgrade.h:206
RelInfoArr rel_arr
Definition pg_upgrade.h:209
RelInfo * rels
Definition pg_upgrade.h:160
char * nspname
Definition pg_upgrade.h:147
char * relname
Definition pg_upgrade.h:148

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

2206{
2207 PGresult *res;
2208 PGconn *conn;
2209 int nslots_on_old;
2210 int nslots_on_new;
2211 int rdt_slot_on_new;
2213 char *wal_level;
2214 int i_nslots_on_new;
2216
2217 /*
2218 * Logical slots can be migrated since PG17 and a physical slot
2219 * CONFLICT_DETECTION_SLOT can be migrated since PG19.
2220 */
2222 return;
2223
2225
2226 /*
2227 * Quick return if there are no slots to be migrated and no subscriptions
2228 * have the retain_dead_tuples option enabled.
2229 */
2231 return;
2232
2233 conn = connectToServer(&new_cluster, "template1");
2234
2235 prep_status("Checking for new cluster replication slots");
2236
2237 res = executeQueryOrDie(conn, "SELECT %s AS nslots_on_new, %s AS rdt_slot_on_new "
2238 "FROM pg_catalog.pg_replication_slots",
2239 nslots_on_old > 0
2240 ? "COUNT(*) FILTER (WHERE slot_type = 'logical' AND temporary IS FALSE)"
2241 : "0",
2242 old_cluster.sub_retain_dead_tuples
2243 ? "COUNT(*) FILTER (WHERE slot_name = 'pg_conflict_detection')"
2244 : "0");
2245
2246 if (PQntuples(res) != 1)
2247 pg_fatal("could not count the number of replication slots");
2248
2249 i_nslots_on_new = PQfnumber(res, "nslots_on_new");
2250 i_rdt_slot_on_new = PQfnumber(res, "rdt_slot_on_new");
2251
2253
2254 if (nslots_on_new)
2255 {
2257 pg_fatal("expected 0 logical replication slots but found %d",
2259 }
2260
2262
2263 if (rdt_slot_on_new)
2264 {
2266 pg_fatal("The replication slot \"pg_conflict_detection\" already exists on the new cluster");
2267 }
2268
2269 PQclear(res);
2270
2271 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
2272 "WHERE name IN ('wal_level', 'max_replication_slots') "
2273 "ORDER BY name DESC;");
2274
2275 if (PQntuples(res) != 2)
2276 pg_fatal("could not determine parameter settings on new cluster");
2277
2278 wal_level = PQgetvalue(res, 0, 0);
2279
2281 strcmp(wal_level, "minimal") == 0)
2282 pg_fatal("\"wal_level\" must be \"replica\" or \"logical\" but is set to \"%s\"",
2283 wal_level);
2284
2286
2289 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
2290 "logical replication slots on the old cluster plus one additional slot required "
2291 "for retaining conflict detection information (%d)",
2293
2295 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
2296 "logical replication slots (%d) on the old cluster",
2298
2299 PQclear(res);
2300 PQfinish(conn);
2301
2302 check_ok();
2303}
int count_old_cluster_logical_slots(void)
Definition info.c:824
int max_replication_slots
Definition slot.c:161
bool sub_retain_dead_tuples
Definition pg_upgrade.h:314
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 2313 of file check.c.

2314{
2315 PGresult *res;
2316 PGconn *conn;
2318
2319 /* Subscriptions and their dependencies can be migrated since PG17. */
2321 return;
2322
2323 /* Quick return if there are no subscriptions to be migrated. */
2324 if (old_cluster.nsubs == 0)
2325 return;
2326
2327 prep_status("Checking for new cluster configuration for subscriptions");
2328
2329 conn = connectToServer(&new_cluster, "template1");
2330
2331 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
2332 "WHERE name = 'max_active_replication_origins';");
2333
2334 if (PQntuples(res) != 1)
2335 pg_fatal("could not determine parameter settings on new cluster");
2336
2339 pg_fatal("\"max_active_replication_origins\" (%d) must be greater than or equal to the number of "
2340 "subscriptions (%d) on the old cluster",
2342
2343 PQclear(res);
2344 PQfinish(conn);
2345
2346 check_ok();
2347}
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 2356 of file check.c.

2357{
2358 char output_path[MAXPGPATH];
2359 FILE *script = NULL;
2360
2361 prep_status("Checking for valid logical replication slots");
2362
2363 snprintf(output_path, sizeof(output_path), "%s/%s",
2365 "invalid_logical_slots.txt");
2366
2367 for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
2368 {
2369 LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
2370
2371 for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
2372 {
2373 LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
2374
2375 /* Is the slot usable? */
2376 if (slot->invalid)
2377 {
2378 if (script == NULL &&
2379 (script = fopen_priv(output_path, "w")) == NULL)
2380 pg_fatal("could not open file \"%s\": %m", output_path);
2381
2382 fprintf(script, "The slot \"%s\" is invalid\n",
2383 slot->slotname);
2384
2385 continue;
2386 }
2387
2388 /*
2389 * Do additional check to ensure that all logical replication
2390 * slots have consumed all the WAL before shutdown.
2391 *
2392 * Note: This can be satisfied only when the old cluster has been
2393 * shut down, so we skip this for live checks.
2394 */
2395 if (!user_opts.live_check && !slot->caught_up)
2396 {
2397 if (script == NULL &&
2398 (script = fopen_priv(output_path, "w")) == NULL)
2399 pg_fatal("could not open file \"%s\": %m", output_path);
2400
2401 fprintf(script,
2402 "The slot \"%s\" has not consumed the WAL yet\n",
2403 slot->slotname);
2404 }
2405
2406 /*
2407 * The name "pg_conflict_detection" (defined as
2408 * CONFLICT_DETECTION_SLOT) has been reserved for logical
2409 * replication conflict detection slot since PG19.
2410 */
2411 if (strcmp(slot->slotname, "pg_conflict_detection") == 0)
2412 {
2413 if (script == NULL &&
2414 (script = fopen_priv(output_path, "w")) == NULL)
2415 pg_fatal("could not open file \"%s\": %m", output_path);
2416
2417 fprintf(script,
2418 "The slot name \"%s\" is reserved\n",
2419 slot->slotname);
2420 }
2421 }
2422 }
2423
2424 if (script)
2425 {
2426 fclose(script);
2427
2428 pg_log(PG_REPORT, "fatal");
2429 pg_fatal("Your installation contains logical replication slots that cannot be upgraded.\n"
2430 "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
2431 "and then restart the upgrade.\n"
2432 "A list of the problematic slots is in the file:\n"
2433 " %s", output_path);
2434 }
2435
2436 check_ok();
2437}
LogicalSlotInfoArr slot_arr
Definition pg_upgrade.h:210
LogicalSlotInfo * slots
Definition pg_upgrade.h:181

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

2586{
2587 int i;
2589 PGresult *res;
2590 int ntups;
2591 FILE *script = NULL;
2592 char output_path[MAXPGPATH];
2593 int count = 0;
2594
2595 prep_status("Checking names of databases, roles and tablespaces");
2596
2597 snprintf(output_path, sizeof(output_path), "%s/%s",
2599 "db_role_tablespace_invalid_names.txt");
2600
2601 conn_template1 = connectToServer(cluster, "template1");
2602
2603 /*
2604 * Get database, user/role and tablespacenames from cluster. Can't use
2605 * pg_authid because only superusers can view it.
2606 */
2608 "SELECT datname AS objname, 'database' AS objtype "
2609 "FROM pg_catalog.pg_database UNION ALL "
2610 "SELECT rolname AS objname, 'role' AS objtype "
2611 "FROM pg_catalog.pg_roles UNION ALL "
2612 "SELECT spcname AS objname, 'tablespace' AS objtype "
2613 "FROM pg_catalog.pg_tablespace ORDER BY 2 ");
2614
2615 ntups = PQntuples(res);
2616 for (i = 0; i < ntups; i++)
2617 {
2618 char *objname = PQgetvalue(res, i, 0);
2619 char *objtype = PQgetvalue(res, i, 1);
2620
2621 /* If name has \n or \r, then report it. */
2622 if (strpbrk(objname, "\n\r"))
2623 {
2624 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
2625 pg_fatal("could not open file \"%s\": %m", output_path);
2626
2627 fprintf(script, "%d : %s name = \"%s\"\n", ++count, objtype, objname);
2628 }
2629 }
2630
2631 PQclear(res);
2633
2634 if (script)
2635 {
2636 fclose(script);
2637 pg_log(PG_REPORT, "fatal");
2638 pg_fatal("All the database, role and tablespace names should have only valid characters. A newline or \n"
2639 "carriage return character is not allowed in these object names. To fix this, please \n"
2640 "rename these names with valid names. \n"
2641 "To see all %d invalid object names, refer db_role_tablespace_invalid_names.txt file. \n"
2642 " %s", count, output_path);
2643 }
2644 else
2645 check_ok();
2646}

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

2479{
2481 UpgradeTaskReport report;
2482 const char *query;
2483 PGresult *res;
2484 PGconn *conn;
2485 int ntup;
2486
2487 prep_status("Checking for subscription state");
2488
2489 report.file = NULL;
2490 snprintf(report.path, sizeof(report.path), "%s/%s",
2492 "subs_invalid.txt");
2493
2494 /*
2495 * Check that all the subscriptions have their respective replication
2496 * origin. This check only needs to run once.
2497 */
2499 res = executeQueryOrDie(conn,
2500 "SELECT d.datname, s.subname "
2501 "FROM pg_catalog.pg_subscription s "
2502 "LEFT OUTER JOIN pg_catalog.pg_replication_origin o "
2503 " ON o.roname = 'pg_' || s.oid "
2504 "INNER JOIN pg_catalog.pg_database d "
2505 " ON d.oid = s.subdbid "
2506 "WHERE o.roname IS NULL;");
2507 ntup = PQntuples(res);
2508 for (int i = 0; i < ntup; i++)
2509 {
2510 if (report.file == NULL &&
2511 (report.file = fopen_priv(report.path, "w")) == NULL)
2512 pg_fatal("could not open file \"%s\": %m", report.path);
2513 fprintf(report.file, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n",
2514 PQgetvalue(res, i, 0),
2515 PQgetvalue(res, i, 1));
2516 }
2517 PQclear(res);
2518 PQfinish(conn);
2519
2520 /*
2521 * We don't allow upgrade if there is a risk of dangling slot or origin
2522 * corresponding to initial sync after upgrade.
2523 *
2524 * A slot/origin not created yet refers to the 'i' (initialize) state,
2525 * while 'r' (ready) state refers to a slot/origin created previously but
2526 * already dropped. These states are supported for pg_upgrade. The other
2527 * states listed below are not supported:
2528 *
2529 * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state would
2530 * retain a replication slot and origin. The sync worker spawned after the
2531 * upgrade cannot drop them because the subscription ID used for the slot
2532 * and origin name no longer matches.
2533 *
2534 * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state would
2535 * retain the replication origin when there is a failure in tablesync
2536 * worker immediately after dropping the replication slot in the
2537 * publisher.
2538 *
2539 * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on a
2540 * relation upgraded while in this state would expect an origin ID with
2541 * the OID of the subscription used before the upgrade, causing it to
2542 * fail.
2543 *
2544 * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and
2545 * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, so we
2546 * need not allow these states.
2547 */
2548 query = "SELECT r.srsubstate, s.subname, n.nspname, c.relname "
2549 "FROM pg_catalog.pg_subscription_rel r "
2550 "LEFT JOIN pg_catalog.pg_subscription s"
2551 " ON r.srsubid = s.oid "
2552 "LEFT JOIN pg_catalog.pg_class c"
2553 " ON r.srrelid = c.oid "
2554 "LEFT JOIN pg_catalog.pg_namespace n"
2555 " ON c.relnamespace = n.oid "
2556 "WHERE r.srsubstate NOT IN ('i', 'r') "
2557 "ORDER BY s.subname";
2558
2560 true, &report);
2561
2564
2565 if (report.file)
2566 {
2567 fclose(report.file);
2568 pg_log(PG_REPORT, "fatal");
2569 pg_fatal("Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n"
2570 "You can allow the initial sync to finish for all relations and then restart the upgrade.\n"
2571 "A list of the problematic subscriptions is in the file:\n"
2572 " %s", report.path);
2573 }
2574 else
2575 check_ok();
2576}
static void process_old_sub_state_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition check.c:2445

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

1013{
1014 FILE *script = NULL;
1015 int tblnum;
1018 char *old_tblspc_suffix;
1019
1020 *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
1022
1025
1028
1029 /* Some people put the new data directory inside the old one. */
1031 {
1033 "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
1034
1035 /* Unlink file in case it is left over from a previous run. */
1039 return;
1040 }
1041
1042 /*
1043 * Some users (oddly) create tablespaces inside the cluster data
1044 * directory. We can't create a proper old cluster delete script in that
1045 * case.
1046 */
1048 {
1050
1054 {
1055 /* reproduce warning from CREATE TABLESPACE that is in the log */
1057 "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", new_tablespace_dir);
1058
1059 /* Unlink file in case it is left over from a previous run. */
1063 return;
1064 }
1065 }
1066
1067 prep_status("Creating script to delete old cluster");
1068
1069 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
1070 pg_fatal("could not open file \"%s\": %m",
1072
1073#ifndef WIN32
1074 /* add shebang header */
1075 fprintf(script, "#!/bin/sh\n\n");
1076#endif
1077
1078 /* delete old cluster's default tablespace */
1079 fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
1081
1082 /* delete old cluster's alternate tablespaces */
1086 fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1090
1091 fclose(script);
1092
1093#ifndef WIN32
1095 pg_fatal("could not add execute permission to file \"%s\": %m",
1097#endif
1098
1099 check_ok();
1100}
static char * fix_path_separator(char *path)
Definition check.c:554
char * pg_strdup(const char *in)
Definition fe_memutils.c:85
void pfree(void *pointer)
Definition mcxt.c:1616
#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:637
void canonicalize_path(char *path)
Definition path.c:337
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
char * pgdata
Definition pg_upgrade.h:299
#define S_IRWXU
Definition win32_port.h:288

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

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

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

555{
556#ifdef WIN32
557
558 char *result;
559 char *c;
560
561 result = pg_strdup(path);
562
563 for (c = result; *c != '\0'; c++)
564 if (*c == '/')
565 *c = '\\';
566
567 return result;
568#else
569
570 return path;
571#endif
572}
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 824 of file check.c.

825{
826 /*
827 * We unconditionally start/stop the new server because pg_resetwal -o set
828 * wal_level to 'minimum'. If the user is upgrading standby servers using
829 * the rsync instructions, they will need pg_upgrade to write its final
830 * WAL record showing wal_level as 'replica'.
831 */
833
834 /* Reindex hash indexes for old < 10.0 */
837
839
840 stop_postmaster(false);
841}
void report_extension_updates(ClusterInfo *cluster)
Definition version.c:195

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

576{
578 {
580 "Performing Consistency Checks on Old Live Server\n"
581 "------------------------------------------------");
582 }
583 else
584 {
586 "Performing Consistency Checks\n"
587 "-----------------------------");
588 }
589}

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

846{
848
851 {
855 }
856
858 "Some statistics are not transferred by pg_upgrade.\n"
859 "Once you start the new server, consider running these two commands:\n"
860 " %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n"
861 " %s/vacuumdb %s--all --analyze-only",
864
867 "Running this script will delete the old cluster's data files:\n"
868 " %s",
870 else
872 "Could not create a script to delete the old cluster's data files\n"
873 "because user-defined tablespaces or the new cluster's data directory\n"
874 "exist in the old cluster directory. The old cluster's contents must\n"
875 "be deleted manually.");
876
878}
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendShellString(PQExpBuffer buf, const char *str)
char * bindir
Definition pg_upgrade.h:302
bool user_specified
Definition pg_upgrade.h:367

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

397{
399 int ntups = PQntuples(res);
401 int i_nspname = PQfnumber(res, "nspname");
402 int i_relname = PQfnumber(res, "relname");
403 int i_attname = PQfnumber(res, "attname");
404 FILE *script = NULL;
405
406 if (ntups == 0)
407 return;
408
409 snprintf(output_path, sizeof(output_path), "%s/%s",
411 state->check->report_filename);
412
413 /*
414 * Make sure we have a buffer to save reports to now that we found a first
415 * failing check.
416 */
417 if (*state->report == NULL)
418 *state->report = createPQExpBuffer();
419
420 /*
421 * If this is the first time we see an error for the check in question
422 * then print a status message of the failure.
423 */
424 if (!state->result)
425 {
426 pg_log(PG_REPORT, "failed check: %s", _(state->check->status));
427 appendPQExpBuffer(*state->report, "\n%s\n%s\n %s\n",
428 _(state->check->report_text),
429 _("A list of the problem columns is in the file:"),
431 }
432 state->result = true;
433
434 if ((script = fopen_priv(output_path, "a")) == NULL)
435 pg_fatal("could not open file \"%s\": %m", output_path);
436
437 fprintf(script, "In database: %s\n", dbinfo->db_name);
438
439 for (int rowno = 0; rowno < ntups; rowno++)
440 fprintf(script, " %s.%s.%s\n",
443 PQgetvalue(res, rowno, i_attname));
444
445 fclose(script);
446}
Datum arg
Definition elog.c:1322
#define _(x)
Definition elog.c:95
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 1805 of file check.c.

1806{
1808 int ntups = PQntuples(res);
1809 int i_nspname = PQfnumber(res, "nspname");
1810 int i_relname = PQfnumber(res, "relname");
1811
1812 if (ntups == 0)
1813 return;
1814
1815 if (report->file == NULL &&
1816 (report->file = fopen_priv(report->path, "w")) == NULL)
1817 pg_fatal("could not open file \"%s\": %m", report->path);
1818
1819 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1820
1821 for (int rowno = 0; rowno < ntups; rowno++)
1822 fprintf(report->file, " %s.%s\n",
1823 PQgetvalue(res, rowno, i_nspname),
1824 PQgetvalue(res, rowno, i_relname));
1825}

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

1522{
1524 int ntups = PQntuples(res);
1525 int i_objkind = PQfnumber(res, "objkind");
1526 int i_objname = PQfnumber(res, "objname");
1527
1528 if (ntups == 0)
1529 return;
1530
1531 if (report->file == NULL &&
1532 (report->file = fopen_priv(report->path, "w")) == NULL)
1533 pg_fatal("could not open file \"%s\": %m", report->path);
1534
1535 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1536
1537 for (int rowno = 0; rowno < ntups; rowno++)
1538 fprintf(report->file, " %s: %s\n",
1539 PQgetvalue(res, rowno, i_objkind),
1540 PQgetvalue(res, rowno, i_objname));
1541}

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

1720{
1722 int ntups = PQntuples(res);
1723 int i_nspname = PQfnumber(res, "nspname");
1724 int i_relname = PQfnumber(res, "relname");
1725 int i_attname = PQfnumber(res, "attname");
1726
1727 if (ntups == 0)
1728 return;
1729
1730 if (report->file == NULL &&
1731 (report->file = fopen_priv(report->path, "w")) == NULL)
1732 pg_fatal("could not open file \"%s\": %m", report->path);
1733
1734 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1735
1736 for (int rowno = 0; rowno < ntups; rowno++)
1737 {
1738 fprintf(report->file, " %s.%s.%s\n",
1739 PQgetvalue(res, rowno, i_nspname),
1740 PQgetvalue(res, rowno, i_relname),
1741 PQgetvalue(res, rowno, i_attname));
1742 }
1743}

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

1348{
1349 int ntups = PQntuples(res);
1350 int i_nspname = PQfnumber(res, "nspname");
1351 int i_proname = PQfnumber(res, "proname");
1353
1354 if (ntups == 0)
1355 return;
1356
1357 if (report->file == NULL &&
1358 (report->file = fopen_priv(report->path, "w")) == NULL)
1359 pg_fatal("could not open file \"%s\": %m", report->path);
1360
1361 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1362
1363 for (int rowno = 0; rowno < ntups; rowno++)
1364 fprintf(report->file, " %s.%s\n",
1365 PQgetvalue(res, rowno, i_nspname),
1366 PQgetvalue(res, rowno, i_proname));
1367}

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

2446{
2448 int ntups = PQntuples(res);
2449 int i_srsubstate = PQfnumber(res, "srsubstate");
2450 int i_subname = PQfnumber(res, "subname");
2451 int i_nspname = PQfnumber(res, "nspname");
2452 int i_relname = PQfnumber(res, "relname");
2453
2454 if (ntups == 0)
2455 return;
2456
2457 if (report->file == NULL &&
2458 (report->file = fopen_priv(report->path, "w")) == NULL)
2459 pg_fatal("could not open file \"%s\": %m", report->path);
2460
2461 for (int i = 0; i < ntups; i++)
2462 fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n",
2463 PQgetvalue(res, i, i_srsubstate),
2464 dbinfo->db_name,
2465 PQgetvalue(res, i, i_subname),
2466 PQgetvalue(res, i, i_nspname),
2467 PQgetvalue(res, i, i_relname));
2468}

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

2018{
2020 int ntups = PQntuples(res);
2021 int i_reloid = PQfnumber(res, "reloid");
2022 int i_nspname = PQfnumber(res, "nspname");
2023 int i_relname = PQfnumber(res, "relname");
2024
2025 if (ntups == 0)
2026 return;
2027
2028 if (report->file == NULL &&
2029 (report->file = fopen_priv(report->path, "w")) == NULL)
2030 pg_fatal("could not open file \"%s\": %m", report->path);
2031
2032 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
2033
2034 for (int rowno = 0; rowno < ntups; rowno++)
2035 fprintf(report->file, " (oid=%s) %s.%s\n",
2036 PQgetvalue(res, rowno, i_reloid),
2037 PQgetvalue(res, rowno, i_nspname),
2038 PQgetvalue(res, rowno, i_relname));
2039}

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

1938{
1940 int ntups = PQntuples(res);
1941 int i_conoid = PQfnumber(res, "conoid");
1942 int i_conname = PQfnumber(res, "conname");
1943 int i_nspname = PQfnumber(res, "nspname");
1944
1945 if (ntups == 0)
1946 return;
1947
1948 if (report->file == NULL &&
1949 (report->file = fopen_priv(report->path, "w")) == NULL)
1950 pg_fatal("could not open file \"%s\": %m", report->path);
1951
1952 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1953
1954 for (int rowno = 0; rowno < ntups; rowno++)
1955 fprintf(report->file, " (oid=%s) %s.%s\n",
1956 PQgetvalue(res, rowno, i_conoid),
1957 PQgetvalue(res, rowno, i_nspname),
1958 PQgetvalue(res, rowno, i_conname));
1959}

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

1431{
1433 int ntups = PQntuples(res);
1434 int i_oproid = PQfnumber(res, "oproid");
1435 int i_oprnsp = PQfnumber(res, "oprnsp");
1436 int i_oprname = PQfnumber(res, "oprname");
1437 int i_typnsp = PQfnumber(res, "typnsp");
1438 int i_typname = PQfnumber(res, "typname");
1439
1440 if (ntups == 0)
1441 return;
1442
1443 if (report->file == NULL &&
1444 (report->file = fopen_priv(report->path, "w")) == NULL)
1445 pg_fatal("could not open file \"%s\": %m", report->path);
1446
1447 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1448
1449 for (int rowno = 0; rowno < ntups; rowno++)
1450 fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n",
1451 PQgetvalue(res, rowno, i_oproid),
1452 PQgetvalue(res, rowno, i_oprnsp),
1453 PQgetvalue(res, rowno, i_oprname),
1454 PQgetvalue(res, rowno, i_typnsp),
1455 PQgetvalue(res, rowno, i_typname));
1456}

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

1652{
1654 int ntups = PQntuples(res);
1655 int i_nspname = PQfnumber(res, "nspname");
1656 int i_relname = PQfnumber(res, "relname");
1657
1658 if (ntups == 0)
1659 return;
1660
1661 if (report->file == NULL &&
1662 (report->file = fopen_priv(report->path, "w")) == NULL)
1663 pg_fatal("could not open file \"%s\": %m", report->path);
1664
1665 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1666
1667 for (int rowno = 0; rowno < ntups; rowno++)
1668 fprintf(report->file, " %s.%s\n",
1669 PQgetvalue(res, rowno, i_nspname),
1670 PQgetvalue(res, rowno, i_relname));
1671}

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

806{
807 if (user_opts.check)
808 {
809 pg_log(PG_REPORT, "\n*Clusters are compatible*");
810 /* stops new cluster */
811 stop_postmaster(false);
812
814 exit(0);
815 }
816
817 pg_log(PG_REPORT, "\n"
818 "If pg_upgrade fails after this point, you must re-initdb the\n"
819 "new cluster before continuing.");
820}
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 2046 of file check.c.

2047{
2049 PGresult *res;
2050 char *old_unicode_version;
2051 bool unicode_updated;
2052
2053 res = executeQueryOrDie(conn_template1, "SELECT unicode_version()");
2054 old_unicode_version = PQgetvalue(res, 0, 0);
2056
2057 PQclear(res);
2059
2060 return unicode_updated;
2061}
#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 103 of file check.c.

104{
105 /*
106 * Look for composite types that were made during initdb *or* belong to
107 * information_schema; that's important in case information_schema was
108 * dropped and reloaded.
109 *
110 * The cutoff OID here should match the source cluster's value of
111 * FirstNormalObjectId. We hardcode it rather than using that C #define
112 * because, if that #define is ever changed, our own version's value is
113 * NOT what to use. Eventually we may need a test on the source cluster's
114 * version to select the correct value.
115 */
116 {
117 .status = gettext_noop("Checking for system-defined composite types in user tables"),
118 .report_filename = "tables_using_composite.txt",
119 .base_query =
120 "SELECT t.oid FROM pg_catalog.pg_type t "
121 "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
122 " WHERE typtype = 'c' AND (t.oid < 16384 OR nspname = 'information_schema')",
123 .report_text =
124 gettext_noop("Your installation contains system-defined composite types in user tables.\n"
125 "These type OIDs are not stable across PostgreSQL versions,\n"
126 "so this cluster cannot currently be upgraded. You can drop the\n"
127 "problem columns and restart the upgrade.\n"),
128 .threshold_version = ALL_VERSIONS
129 },
130
131 /*
132 * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which
133 * previously returned "not enabled" by default and was only functionally
134 * enabled with a compile-time switch; as of 9.4 "line" has a different
135 * on-disk representation format.
136 */
137 {
138 .status = gettext_noop("Checking for incompatible \"line\" data type"),
139 .report_filename = "tables_using_line.txt",
140 .base_query =
141 "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid",
142 .report_text =
143 gettext_noop("Your installation contains the \"line\" data type in user tables.\n"
144 "This data type changed its internal and input/output format\n"
145 "between your old and new versions so this\n"
146 "cluster cannot currently be upgraded. You can\n"
147 "drop the problem columns and restart the upgrade.\n"),
148 .threshold_version = 903
149 },
150
151 /*
152 * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid
153 * pg_enum.oid
154 *
155 * Many of the reg* data types reference system catalog info that is not
156 * preserved, and hence these data types cannot be used in user tables
157 * upgraded by pg_upgrade.
158 */
159 {
160 .status = gettext_noop("Checking for reg* data types in user tables"),
161 .report_filename = "tables_using_reg.txt",
162
163 /*
164 * Note: older servers will not have all of these reg* types, so we
165 * have to write the query like this rather than depending on casts to
166 * regtype.
167 */
168 .base_query =
169 "SELECT oid FROM pg_catalog.pg_type t "
170 "WHERE t.typnamespace = "
171 " (SELECT oid FROM pg_catalog.pg_namespace "
172 " WHERE nspname = 'pg_catalog') "
173 " AND t.typname IN ( "
174 /* pg_class.oid is preserved, so 'regclass' is OK */
175 " 'regcollation', "
176 " 'regconfig', "
177 /* pg_database.oid is preserved, so 'regdatabase' is OK */
178 " 'regdictionary', "
179 " 'regnamespace', "
180 " 'regoper', "
181 " 'regoperator', "
182 " 'regproc', "
183 " 'regprocedure' "
184 /* pg_authid.oid is preserved, so 'regrole' is OK */
185 /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
186 " )",
187 .report_text =
188 gettext_noop("Your installation contains one of the reg* data types in user tables.\n"
189 "These data types reference system OIDs that are not preserved by\n"
190 "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
191 "drop the problem columns and restart the upgrade.\n"),
192 .threshold_version = ALL_VERSIONS
193 },
194
195 /*
196 * PG 16 increased the size of the 'aclitem' type, which breaks the
197 * on-disk format for existing data.
198 */
199 {
200 .status = gettext_noop("Checking for incompatible \"aclitem\" data type"),
201 .report_filename = "tables_using_aclitem.txt",
202 .base_query =
203 "SELECT 'pg_catalog.aclitem'::pg_catalog.regtype AS oid",
204 .report_text =
205 gettext_noop("Your installation contains the \"aclitem\" data type in user tables.\n"
206 "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
207 "so this cluster cannot currently be upgraded. You can drop the\n"
208 "problem columns and restart the upgrade.\n"),
209 .threshold_version = 1500
210 },
211
212 /*
213 * It's no longer allowed to create tables or views with "unknown"-type
214 * columns. We do not complain about views with such columns, because
215 * they should get silently converted to "text" columns during the DDL
216 * dump and reload; it seems unlikely to be worth making users do that by
217 * hand. However, if there's a table with such a column, the DDL reload
218 * will fail, so we should pre-detect that rather than failing
219 * mid-upgrade. Worse, if there's a matview with such a column, the DDL
220 * reload will silently change it to "text" which won't match the on-disk
221 * storage (which is like "cstring"). So we *must* reject that.
222 */
223 {
224 .status = gettext_noop("Checking for invalid \"unknown\" user columns"),
225 .report_filename = "tables_using_unknown.txt",
226 .base_query =
227 "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid",
228 .report_text =
229 gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n"
230 "This data type is no longer allowed in tables, so this cluster\n"
231 "cannot currently be upgraded. You can drop the problem columns\n"
232 "and restart the upgrade.\n"),
233 .threshold_version = 906
234 },
235
236 /*
237 * PG 12 changed the 'sql_identifier' type storage to be based on name,
238 * not varchar, which breaks on-disk format for existing data. So we need
239 * to prevent upgrade when used in user objects (tables, indexes, ...). In
240 * 12, the sql_identifier data type was switched from name to varchar,
241 * which does affect the storage (name is by-ref, but not varlena). This
242 * means user tables using sql_identifier for columns are broken because
243 * the on-disk format is different.
244 */
245 {
246 .status = gettext_noop("Checking for invalid \"sql_identifier\" user columns"),
247 .report_filename = "tables_using_sql_identifier.txt",
248 .base_query =
249 "SELECT 'information_schema.sql_identifier'::pg_catalog.regtype AS oid",
250 .report_text =
251 gettext_noop("Your installation contains the \"sql_identifier\" data type in user tables.\n"
252 "The on-disk format for this data type has changed, so this\n"
253 "cluster cannot currently be upgraded. You can drop the problem\n"
254 "columns and restart the upgrade.\n"),
255 .threshold_version = 1100
256 },
257
258 /*
259 * JSONB changed its storage format during 9.4 beta, so check for it.
260 */
261 {
262 .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"),
263 .report_filename = "tables_using_jsonb.txt",
264 .base_query =
265 "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid",
266 .report_text =
267 gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n"
268 "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
269 "cluster cannot currently be upgraded. You can drop the problem \n"
270 "columns and restart the upgrade.\n"),
271 .threshold_version = MANUAL_CHECK,
272 .version_hook = jsonb_9_4_check_applicable
273 },
274
275 /*
276 * PG 12 removed types abstime, reltime, tinterval.
277 */
278 {
279 .status = gettext_noop("Checking for removed \"abstime\" data type in user tables"),
280 .report_filename = "tables_using_abstime.txt",
281 .base_query =
282 "SELECT 'pg_catalog.abstime'::pg_catalog.regtype AS oid",
283 .report_text =
284 gettext_noop("Your installation contains the \"abstime\" data type in user tables.\n"
285 "The \"abstime\" type has been removed in PostgreSQL version 12,\n"
286 "so this cluster cannot currently be upgraded. You can drop the\n"
287 "problem columns, or change them to another data type, and restart\n"
288 "the upgrade.\n"),
289 .threshold_version = 1100
290 },
291 {
292 .status = gettext_noop("Checking for removed \"reltime\" data type in user tables"),
293 .report_filename = "tables_using_reltime.txt",
294 .base_query =
295 "SELECT 'pg_catalog.reltime'::pg_catalog.regtype AS oid",
296 .report_text =
297 gettext_noop("Your installation contains the \"reltime\" data type in user tables.\n"
298 "The \"reltime\" type has been removed in PostgreSQL version 12,\n"
299 "so this cluster cannot currently be upgraded. You can drop the\n"
300 "problem columns, or change them to another data type, and restart\n"
301 "the upgrade.\n"),
302 .threshold_version = 1100
303 },
304 {
305 .status = gettext_noop("Checking for removed \"tinterval\" data type in user tables"),
306 .report_filename = "tables_using_tinterval.txt",
307 .base_query =
308 "SELECT 'pg_catalog.tinterval'::pg_catalog.regtype AS oid",
309 .report_text =
310 gettext_noop("Your installation contains the \"tinterval\" data type in user tables.\n"
311 "The \"tinterval\" type has been removed in PostgreSQL version 12,\n"
312 "so this cluster cannot currently be upgraded. You can drop the\n"
313 "problem columns, or change them to another data type, and restart\n"
314 "the upgrade.\n"),
315 .threshold_version = 1100
316 },
317
318 /* End of checks marker, must remain last */
319 {
320 NULL, NULL, NULL, NULL, 0, NULL
321 }
322};
#define gettext_noop(x)
Definition c.h:1285
bool jsonb_9_4_check_applicable(ClusterInfo *cluster)
Definition version.c:21

Referenced by check_for_data_types_usage(), and data_type_check_query().