PostgreSQL Source Code  git master
check.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_authid.h"
#include "fe_utils/string_utils.h"
#include "mb/pg_wchar.h"
#include "pg_upgrade.h"
Include dependency graph for check.c:

Go to the source code of this file.

Functions

static void check_new_cluster_is_empty (void)
 
static void check_databases_are_compatible (void)
 
static void check_locale_and_encoding (DbInfo *olddb, DbInfo *newdb)
 
static bool equivalent_locale (int category, const char *loca, const char *locb)
 
static void check_is_install_user (ClusterInfo *cluster)
 
static void check_proper_datallowconn (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_reg_data_type_usage (ClusterInfo *cluster)
 
static void check_for_jsonb_9_4_usage (ClusterInfo *cluster)
 
static void check_for_pg_role_prefix (ClusterInfo *cluster)
 
static char * get_canonical_locale_name (int category, const char *locale)
 
static char * fix_path_separator (char *path)
 
void output_check_banner (bool live_check)
 
void check_and_dump_old_cluster (bool live_check)
 
void check_new_cluster (void)
 
void report_clusters_compatible (void)
 
void issue_warnings_and_set_wal_level (void)
 
void output_completion_banner (char *analyze_script_file_name, char *deletion_script_file_name)
 
void check_cluster_versions (void)
 
void check_cluster_compatibility (bool live_check)
 
void create_script_for_cluster_analyze (char **analyze_script_file_name)
 
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
 

Function Documentation

◆ check_and_dump_old_cluster()

void check_and_dump_old_cluster ( bool  live_check)

Definition at line 79 of file check.c.

References ControlData::cat_ver, UserOpts::check, check_for_isn_and_int8_passing_mismatch(), check_for_jsonb_9_4_usage(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_is_install_user(), check_proper_datallowconn(), ClusterInfo::controldata, generate_old_dump(), get_db_and_rel_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, init_tablespaces(), JSONB_FORMAT_CHANGE_CAT_VER, ClusterInfo::major_version, new_9_0_populate_pg_largeobject_metadata(), old_9_3_check_for_line_data_type_usage(), old_9_6_check_for_unknown_data_type_usage(), old_9_6_invalidate_hash_indexes(), old_cluster, start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

80 {
81  /* -- OLD -- */
82 
83  if (!live_check)
85 
86  /* Extract a list of databases and tables from the old cluster */
88 
90 
92 
93 
94  /*
95  * Check for various failure cases
96  */
102 
103  /*
104  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
105  * hash indexes
106  */
108  {
110  if (user_opts.check)
112  }
113 
114  /* 9.5 and below should not have roles starting with pg_ */
117 
121 
122  /* Pre-PG 9.4 had a different 'line' data type internal format */
125 
126  /* Pre-PG 9.0 had no large object permissions */
129 
130  /*
131  * While not a check option, we do this now because this is the only time
132  * the old server is running.
133  */
134  if (!user_opts.check)
136 
137  if (!live_check)
138  stop_postmaster(false);
139 }
uint32 major_version
Definition: pg_upgrade.h:274
ControlData controldata
Definition: pg_upgrade.h:264
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:297
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:886
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:757
void stop_postmaster(bool fast)
Definition: server.c:325
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:696
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1072
void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster, bool check_mode)
Definition: version.c:25
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
void generate_old_dump(void)
Definition: dump.c:18
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:645
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:792
UserOpts user_opts
Definition: option.c:29
uint32 cat_ver
Definition: pg_upgrade.h:210
void get_loadable_libraries(void)
Definition: function.c:49
void get_db_and_rel_infos(ClusterInfo *cluster)
Definition: info.c:311
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:132
bool check
Definition: pg_upgrade.h:297
static pgpid_t start_postmaster(void)
Definition: pg_ctl.c:442
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:983
void init_tablespaces(void)
Definition: tablespace.c:19
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
Definition: version.c:111
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
Definition: version.c:208

◆ check_cluster_compatibility()

void check_cluster_compatibility ( bool  live_check)

Definition at line 275 of file check.c.

References check_control_data(), ClusterInfo::controldata, DEF_PGUPORT, get_control_data(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, pg_fatal(), and ClusterInfo::port.

Referenced by main().

276 {
277  /* get/check pg_control data of servers */
278  get_control_data(&old_cluster, live_check);
279  get_control_data(&new_cluster, false);
281 
282  /* We read the real port number for PG >= 9.1 */
283  if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
285  pg_fatal("When checking a pre-PG 9.1 live old server, "
286  "you must specify the old server's port number.\n");
287 
288  if (live_check && old_cluster.port == new_cluster.port)
289  pg_fatal("When checking a live server, "
290  "the old and new port numbers must be different.\n");
291 }
uint32 major_version
Definition: pg_upgrade.h:274
ControlData controldata
Definition: pg_upgrade.h:264
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
unsigned short port
Definition: pg_upgrade.h:273
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:552
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
#define DEF_PGUPORT
Definition: pg_upgrade.h:16
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:34

◆ check_cluster_versions()

void check_cluster_versions ( void  )

Definition at line 233 of file check.c.

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

Referenced by main().

234 {
235  prep_status("Checking cluster versions");
236 
237  /* cluster versions should already have been obtained */
240 
241  /*
242  * We allow upgrades from/to the same major version for alpha/beta
243  * upgrades
244  */
245 
247  pg_fatal("This utility can only upgrade from PostgreSQL version 8.4 and later.\n");
248 
249  /* Only current PG version is supported as a target */
251  pg_fatal("This utility can only upgrade to PostgreSQL version %s.\n",
252  PG_MAJORVERSION);
253 
254  /*
255  * We can't allow downgrading because we use the target pg_dump, and
256  * pg_dump cannot operate on newer database versions, only current and
257  * older versions.
258  */
260  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
261 
262  /* Ensure binaries match the designated data directories */
265  pg_fatal("Old cluster data and binary directories are from different major versions.\n");
268  pg_fatal("New cluster data and binary directories are from different major versions.\n");
269 
270  check_ok();
271 }
uint32 major_version
Definition: pg_upgrade.h:274
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static void check_ok(void)
Definition: initdb.c:2051
uint32 bin_version
Definition: pg_upgrade.h:276
#define Assert(condition)
Definition: c.h:670

◆ check_databases_are_compatible()

static void check_databases_are_compatible ( void  )
static

Definition at line 396 of file check.c.

References check_locale_and_encoding(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, DbInfoArr::ndbs, new_cluster, and old_cluster.

Referenced by check_new_cluster().

397 {
398  int newdbnum;
399  int olddbnum;
400  DbInfo *newdbinfo;
401  DbInfo *olddbinfo;
402 
403  for (newdbnum = 0; newdbnum < new_cluster.dbarr.ndbs; newdbnum++)
404  {
405  newdbinfo = &new_cluster.dbarr.dbs[newdbnum];
406 
407  /* Find the corresponding database in the old cluster */
408  for (olddbnum = 0; olddbnum < old_cluster.dbarr.ndbs; olddbnum++)
409  {
410  olddbinfo = &old_cluster.dbarr.dbs[olddbnum];
411  if (strcmp(newdbinfo->db_name, olddbinfo->db_name) == 0)
412  {
413  check_locale_and_encoding(olddbinfo, newdbinfo);
414  break;
415  }
416  }
417  }
418 }
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
DbInfoArr dbarr
Definition: pg_upgrade.h:265
char * db_name
Definition: pg_upgrade.h:187
DbInfo * dbs
Definition: pg_upgrade.h:198
static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb)
Definition: check.c:301

◆ check_for_isn_and_int8_passing_mismatch()

static void check_for_isn_and_int8_passing_mismatch ( ClusterInfo cluster)
static

Definition at line 792 of file check.c.

References check_ok(), conn, connectToServer(), ClusterInfo::controldata, DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), ControlData::float8_pass_by_value, fopen_priv(), MAXPGPATH, DbInfoArr::ndbs, new_cluster, old_cluster, pg_fatal(), pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), snprintf(), and strerror().

Referenced by check_and_dump_old_cluster().

793 {
794  int dbnum;
795  FILE *script = NULL;
796  bool found = false;
797  char output_path[MAXPGPATH];
798 
799  prep_status("Checking for contrib/isn with bigint-passing mismatch");
800 
803  {
804  /* no mismatch */
805  check_ok();
806  return;
807  }
808 
809  snprintf(output_path, sizeof(output_path),
810  "contrib_isn_and_int8_pass_by_value.txt");
811 
812  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
813  {
814  PGresult *res;
815  bool db_used = false;
816  int ntups;
817  int rowno;
818  int i_nspname,
819  i_proname;
820  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
821  PGconn *conn = connectToServer(cluster, active_db->db_name);
822 
823  /* Find any functions coming from contrib/isn */
824  res = executeQueryOrDie(conn,
825  "SELECT n.nspname, p.proname "
826  "FROM pg_catalog.pg_proc p, "
827  " pg_catalog.pg_namespace n "
828  "WHERE p.pronamespace = n.oid AND "
829  " p.probin = '$libdir/isn'");
830 
831  ntups = PQntuples(res);
832  i_nspname = PQfnumber(res, "nspname");
833  i_proname = PQfnumber(res, "proname");
834  for (rowno = 0; rowno < ntups; rowno++)
835  {
836  found = true;
837  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
838  pg_fatal("could not open file \"%s\": %s\n",
839  output_path, strerror(errno));
840  if (!db_used)
841  {
842  fprintf(script, "Database: %s\n", active_db->db_name);
843  db_used = true;
844  }
845  fprintf(script, " %s.%s\n",
846  PQgetvalue(res, rowno, i_nspname),
847  PQgetvalue(res, rowno, i_proname));
848  }
849 
850  PQclear(res);
851 
852  PQfinish(conn);
853  }
854 
855  if (script)
856  fclose(script);
857 
858  if (found)
859  {
860  pg_log(PG_REPORT, "fatal\n");
861  pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
862  "bigint data type. Your old and new clusters pass bigint values\n"
863  "differently so this cluster cannot currently be upgraded. You can\n"
864  "manually upgrade databases that use \"contrib/isn\" facilities and remove\n"
865  "\"contrib/isn\" from the old cluster and restart the upgrade. A list of\n"
866  "the problem functions is in the file:\n"
867  " %s\n\n", output_path);
868  }
869  else
870  check_ok();
871 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
ControlData controldata
Definition: pg_upgrade.h:264
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
FILE * fopen_priv(const char *path, const char *mode)
Definition: file.c:321
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
PGconn * conn
Definition: streamutil.c:46
#define MAXPGPATH
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:2832
void PQclear(PGresult *res)
Definition: fe-exec.c:671
DbInfoArr dbarr
Definition: pg_upgrade.h:265
const char * strerror(int errnum)
Definition: strerror.c:19
char * db_name
Definition: pg_upgrade.h:187
DbInfo * dbs
Definition: pg_upgrade.h:198
bool float8_pass_by_value
Definition: pg_upgrade.h:228

◆ check_for_jsonb_9_4_usage()

static void check_for_jsonb_9_4_usage ( ClusterInfo cluster)
static

Definition at line 983 of file check.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), MAXPGPATH, DbInfoArr::ndbs, pg_fatal(), pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), snprintf(), and strerror().

Referenced by check_and_dump_old_cluster().

984 {
985  int dbnum;
986  FILE *script = NULL;
987  bool found = false;
988  char output_path[MAXPGPATH];
989 
990  prep_status("Checking for incompatible \"jsonb\" data type");
991 
992  snprintf(output_path, sizeof(output_path), "tables_using_jsonb.txt");
993 
994  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
995  {
996  PGresult *res;
997  bool db_used = false;
998  int ntups;
999  int rowno;
1000  int i_nspname,
1001  i_relname,
1002  i_attname;
1003  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1004  PGconn *conn = connectToServer(cluster, active_db->db_name);
1005 
1006  /*
1007  * While several relkinds don't store any data, e.g. views, they can
1008  * be used to define data types of other columns, so we check all
1009  * relkinds.
1010  */
1011  res = executeQueryOrDie(conn,
1012  "SELECT n.nspname, c.relname, a.attname "
1013  "FROM pg_catalog.pg_class c, "
1014  " pg_catalog.pg_namespace n, "
1015  " pg_catalog.pg_attribute a "
1016  "WHERE c.oid = a.attrelid AND "
1017  " NOT a.attisdropped AND "
1018  " a.atttypid = 'pg_catalog.jsonb'::pg_catalog.regtype AND "
1019  " c.relnamespace = n.oid AND "
1020  /* exclude possible orphaned temp tables */
1021  " n.nspname !~ '^pg_temp_' AND "
1022  " n.nspname NOT IN ('pg_catalog', 'information_schema')");
1023 
1024  ntups = PQntuples(res);
1025  i_nspname = PQfnumber(res, "nspname");
1026  i_relname = PQfnumber(res, "relname");
1027  i_attname = PQfnumber(res, "attname");
1028  for (rowno = 0; rowno < ntups; rowno++)
1029  {
1030  found = true;
1031  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1032  pg_fatal("could not open file \"%s\": %s\n",
1033  output_path, strerror(errno));
1034  if (!db_used)
1035  {
1036  fprintf(script, "Database: %s\n", active_db->db_name);
1037  db_used = true;
1038  }
1039  fprintf(script, " %s.%s.%s\n",
1040  PQgetvalue(res, rowno, i_nspname),
1041  PQgetvalue(res, rowno, i_relname),
1042  PQgetvalue(res, rowno, i_attname));
1043  }
1044 
1045  PQclear(res);
1046 
1047  PQfinish(conn);
1048  }
1049 
1050  if (script)
1051  fclose(script);
1052 
1053  if (found)
1054  {
1055  pg_log(PG_REPORT, "fatal\n");
1056  pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
1057  "The internal format of \"jsonb\" changed during 9.4 beta so this cluster cannot currently\n"
1058  "be upgraded. You can remove the problem tables and restart the upgrade. A list\n"
1059  "of the problem columns is in the file:\n"
1060  " %s\n\n", output_path);
1061  }
1062  else
1063  check_ok();
1064 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
FILE * fopen_priv(const char *path, const char *mode)
Definition: file.c:321
PGconn * conn
Definition: streamutil.c:46
#define MAXPGPATH
void prep_status(const char *fmt,...) pg_attribute_printf(1
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:2832
void PQclear(PGresult *res)
Definition: fe-exec.c:671
DbInfoArr dbarr
Definition: pg_upgrade.h:265
const char * strerror(int errnum)
Definition: strerror.c:19
char * db_name
Definition: pg_upgrade.h:187
DbInfo * dbs
Definition: pg_upgrade.h:198

◆ check_for_pg_role_prefix()

static void check_for_pg_role_prefix ( ClusterInfo cluster)
static

Definition at line 1072 of file check.c.

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

Referenced by check_and_dump_old_cluster().

1073 {
1074  PGresult *res;
1075  PGconn *conn = connectToServer(cluster, "template1");
1076 
1077  prep_status("Checking for roles starting with \"pg_\"");
1078 
1079  res = executeQueryOrDie(conn,
1080  "SELECT * "
1081  "FROM pg_catalog.pg_roles "
1082  "WHERE rolname ~ '^pg_'");
1083 
1084  if (PQntuples(res) != 0)
1085  {
1086  if (cluster == &old_cluster)
1087  pg_fatal("The source cluster contains roles starting with \"pg_\"\n");
1088  else
1089  pg_fatal("The target cluster contains roles starting with \"pg_\"\n");
1090  }
1091 
1092  PQclear(res);
1093 
1094  PQfinish(conn);
1095 
1096  check_ok();
1097 }
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
PGconn * conn
Definition: streamutil.c:46
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
void PQclear(PGresult *res)
Definition: fe-exec.c:671

◆ check_for_prepared_transactions()

static void check_for_prepared_transactions ( ClusterInfo cluster)
static

Definition at line 757 of file check.c.

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

Referenced by check_and_dump_old_cluster(), and check_new_cluster().

758 {
759  PGresult *res;
760  PGconn *conn = connectToServer(cluster, "template1");
761 
762  prep_status("Checking for prepared transactions");
763 
764  res = executeQueryOrDie(conn,
765  "SELECT * "
766  "FROM pg_catalog.pg_prepared_xacts");
767 
768  if (PQntuples(res) != 0)
769  {
770  if (cluster == &old_cluster)
771  pg_fatal("The source cluster contains prepared transactions\n");
772  else
773  pg_fatal("The target cluster contains prepared transactions\n");
774  }
775 
776  PQclear(res);
777 
778  PQfinish(conn);
779 
780  check_ok();
781 }
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
PGconn * conn
Definition: streamutil.c:46
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
void PQclear(PGresult *res)
Definition: fe-exec.c:671

◆ check_for_reg_data_type_usage()

static void check_for_reg_data_type_usage ( ClusterInfo cluster)
static

Definition at line 886 of file check.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), MAXPGPATH, DbInfoArr::ndbs, pg_fatal(), pg_log(), PG_REPORT, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), snprintf(), and strerror().

Referenced by check_and_dump_old_cluster().

887 {
888  int dbnum;
889  FILE *script = NULL;
890  bool found = false;
891  char output_path[MAXPGPATH];
892 
893  prep_status("Checking for reg* data types in user tables");
894 
895  snprintf(output_path, sizeof(output_path), "tables_using_reg.txt");
896 
897  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
898  {
899  PGresult *res;
900  bool db_used = false;
901  int ntups;
902  int rowno;
903  int i_nspname,
904  i_relname,
905  i_attname;
906  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
907  PGconn *conn = connectToServer(cluster, active_db->db_name);
908 
909  /*
910  * While several relkinds don't store any data, e.g. views, they can
911  * be used to define data types of other columns, so we check all
912  * relkinds.
913  */
914  res = executeQueryOrDie(conn,
915  "SELECT n.nspname, c.relname, a.attname "
916  "FROM pg_catalog.pg_class c, "
917  " pg_catalog.pg_namespace n, "
918  " pg_catalog.pg_attribute a "
919  "WHERE c.oid = a.attrelid AND "
920  " NOT a.attisdropped AND "
921  " a.atttypid IN ( "
922  " 'pg_catalog.regproc'::pg_catalog.regtype, "
923  " 'pg_catalog.regprocedure'::pg_catalog.regtype, "
924  " 'pg_catalog.regoper'::pg_catalog.regtype, "
925  " 'pg_catalog.regoperator'::pg_catalog.regtype, "
926  /* regclass.oid is preserved, so 'regclass' is OK */
927  /* regtype.oid is preserved, so 'regtype' is OK */
928  " 'pg_catalog.regconfig'::pg_catalog.regtype, "
929  " 'pg_catalog.regdictionary'::pg_catalog.regtype) AND "
930  " c.relnamespace = n.oid AND "
931  " n.nspname NOT IN ('pg_catalog', 'information_schema')");
932 
933  ntups = PQntuples(res);
934  i_nspname = PQfnumber(res, "nspname");
935  i_relname = PQfnumber(res, "relname");
936  i_attname = PQfnumber(res, "attname");
937  for (rowno = 0; rowno < ntups; rowno++)
938  {
939  found = true;
940  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
941  pg_fatal("could not open file \"%s\": %s\n",
942  output_path, strerror(errno));
943  if (!db_used)
944  {
945  fprintf(script, "Database: %s\n", active_db->db_name);
946  db_used = true;
947  }
948  fprintf(script, " %s.%s.%s\n",
949  PQgetvalue(res, rowno, i_nspname),
950  PQgetvalue(res, rowno, i_relname),
951  PQgetvalue(res, rowno, i_attname));
952  }
953 
954  PQclear(res);
955 
956  PQfinish(conn);
957  }
958 
959  if (script)
960  fclose(script);
961 
962  if (found)
963  {
964  pg_log(PG_REPORT, "fatal\n");
965  pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
966  "These data types reference system OIDs that are not preserved by\n"
967  "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
968  "remove the problem tables and restart the upgrade. A list of the problem\n"
969  "columns is in the file:\n"
970  " %s\n\n", output_path);
971  }
972  else
973  check_ok();
974 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
FILE * fopen_priv(const char *path, const char *mode)
Definition: file.c:321
PGconn * conn
Definition: streamutil.c:46
#define MAXPGPATH
void prep_status(const char *fmt,...) pg_attribute_printf(1
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:2832
void PQclear(PGresult *res)
Definition: fe-exec.c:671
DbInfoArr dbarr
Definition: pg_upgrade.h:265
const char * strerror(int errnum)
Definition: strerror.c:19
char * db_name
Definition: pg_upgrade.h:187
DbInfo * dbs
Definition: pg_upgrade.h:198

◆ check_is_install_user()

static void check_is_install_user ( ClusterInfo cluster)
static

Definition at line 645 of file check.c.

References atooid, BOOTSTRAP_SUPERUSERID, check_ok(), conn, connectToServer(), executeQueryOrDie(), new_cluster, os_info, pg_fatal(), PQclear(), PQfinish(), PQgetvalue(), PQntuples(), prep_status(), and OSInfo::user.

Referenced by check_and_dump_old_cluster(), and check_new_cluster().

646 {
647  PGresult *res;
648  PGconn *conn = connectToServer(cluster, "template1");
649 
650  prep_status("Checking database user is the install user");
651 
652  /* Can't use pg_authid because only superusers can view it. */
653  res = executeQueryOrDie(conn,
654  "SELECT rolsuper, oid "
655  "FROM pg_catalog.pg_roles "
656  "WHERE rolname = current_user "
657  "AND rolname !~ '^pg_'");
658 
659  /*
660  * We only allow the install user in the new cluster (see comment below)
661  * and we preserve pg_authid.oid, so this must be the install user in the
662  * old cluster too.
663  */
664  if (PQntuples(res) != 1 ||
665  atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
666  pg_fatal("database user \"%s\" is not the install user\n",
667  os_info.user);
668 
669  PQclear(res);
670 
671  res = executeQueryOrDie(conn,
672  "SELECT COUNT(*) "
673  "FROM pg_catalog.pg_roles "
674  "WHERE rolname !~ '^pg_'");
675 
676  if (PQntuples(res) != 1)
677  pg_fatal("could not determine the number of users\n");
678 
679  /*
680  * We only allow the install user in the new cluster because other defined
681  * users might match users defined in the old cluster and generate an
682  * error during pg_dump restore.
683  */
684  if (cluster == &new_cluster && atooid(PQgetvalue(res, 0, 0)) != 1)
685  pg_fatal("Only the install user can be defined in the new cluster.\n");
686 
687  PQclear(res);
688 
689  PQfinish(conn);
690 
691  check_ok();
692 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
PGconn * conn
Definition: streamutil.c:46
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define atooid(x)
Definition: postgres_ext.h:42
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define BOOTSTRAP_SUPERUSERID
Definition: pg_authid.h:102
OSInfo os_info
Definition: pg_upgrade.c:58
char * user
Definition: pg_upgrade.h:311

◆ check_locale_and_encoding()

static void check_locale_and_encoding ( DbInfo olddb,
DbInfo newdb 
)
static

Definition at line 301 of file check.c.

References DbInfo::db_collate, DbInfo::db_ctype, DbInfo::db_encoding, DbInfo::db_name, equivalent_locale(), pg_encoding_to_char(), and pg_fatal().

Referenced by check_databases_are_compatible().

302 {
303  if (olddb->db_encoding != newdb->db_encoding)
304  pg_fatal("encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
305  olddb->db_name,
308  if (!equivalent_locale(LC_COLLATE, olddb->db_collate, newdb->db_collate))
309  pg_fatal("lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
310  olddb->db_name, olddb->db_collate, newdb->db_collate);
311  if (!equivalent_locale(LC_CTYPE, olddb->db_ctype, newdb->db_ctype))
312  pg_fatal("lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
313  olddb->db_name, olddb->db_ctype, newdb->db_ctype);
314 }
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
static bool equivalent_locale(int category, const char *loca, const char *locb)
Definition: check.c:328
char * db_ctype
Definition: pg_upgrade.h:191
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:607
int db_encoding
Definition: pg_upgrade.h:192
char * db_name
Definition: pg_upgrade.h:187
char * db_collate
Definition: pg_upgrade.h:190

◆ check_new_cluster()

void check_new_cluster ( void  )

Definition at line 143 of file check.c.

References check_databases_are_compatible(), check_for_prepared_transactions(), check_hard_link(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_is_empty(), get_db_and_rel_infos(), new_cluster, UserOpts::transfer_mode, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

144 {
146 
149 
151 
153  check_hard_link();
154 
156 
158 }
void check_hard_link(void)
Definition: file.c:282
static void check_databases_are_compatible(void)
Definition: check.c:396
void check_loadable_libraries(void)
Definition: function.c:203
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:757
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:645
transferMode transfer_mode
Definition: pg_upgrade.h:299
UserOpts user_opts
Definition: option.c:29
static void check_new_cluster_is_empty(void)
Definition: check.c:371
void get_db_and_rel_infos(ClusterInfo *cluster)
Definition: info.c:311

◆ check_new_cluster_is_empty()

static void check_new_cluster_is_empty ( void  )
static

Definition at line 371 of file check.c.

References DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, DbInfoArr::ndbs, new_cluster, RelInfoArr::nrels, RelInfo::nspname, pg_fatal(), DbInfo::rel_arr, and RelInfoArr::rels.

Referenced by check_new_cluster().

372 {
373  int dbnum;
374 
375  for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
376  {
377  int relnum;
378  RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
379 
380  for (relnum = 0; relnum < rel_arr->nrels;
381  relnum++)
382  {
383  /* pg_largeobject and its index should be skipped */
384  if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
385  pg_fatal("New cluster database \"%s\" is not empty\n",
386  new_cluster.dbarr.dbs[dbnum].db_name);
387  }
388  }
389 }
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
char * nspname
Definition: pg_upgrade.h:141
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
RelInfo * rels
Definition: pg_upgrade.h:154
DbInfoArr dbarr
Definition: pg_upgrade.h:265
RelInfoArr rel_arr
Definition: pg_upgrade.h:193
char * db_name
Definition: pg_upgrade.h:187
DbInfo * dbs
Definition: pg_upgrade.h:198

◆ check_proper_datallowconn()

static void check_proper_datallowconn ( ClusterInfo cluster)
static

Definition at line 696 of file check.c.

References check_ok(), connectToServer(), executeQueryOrDie(), pg_fatal(), PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), and prep_status().

Referenced by check_and_dump_old_cluster().

697 {
698  int dbnum;
699  PGconn *conn_template1;
700  PGresult *dbres;
701  int ntups;
702  int i_datname;
703  int i_datallowconn;
704 
705  prep_status("Checking database connection settings");
706 
707  conn_template1 = connectToServer(cluster, "template1");
708 
709  /* get database names */
710  dbres = executeQueryOrDie(conn_template1,
711  "SELECT datname, datallowconn "
712  "FROM pg_catalog.pg_database");
713 
714  i_datname = PQfnumber(dbres, "datname");
715  i_datallowconn = PQfnumber(dbres, "datallowconn");
716 
717  ntups = PQntuples(dbres);
718  for (dbnum = 0; dbnum < ntups; dbnum++)
719  {
720  char *datname = PQgetvalue(dbres, dbnum, i_datname);
721  char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
722 
723  if (strcmp(datname, "template0") == 0)
724  {
725  /* avoid restore failure when pg_dumpall tries to create template0 */
726  if (strcmp(datallowconn, "t") == 0)
727  pg_fatal("template0 must not allow connections, "
728  "i.e. its pg_database.datallowconn must be false\n");
729  }
730  else
731  {
732  /*
733  * avoid datallowconn == false databases from being skipped on
734  * restore
735  */
736  if (strcmp(datallowconn, "f") == 0)
737  pg_fatal("All non-template0 databases must allow connections, "
738  "i.e. their pg_database.datallowconn must be true\n");
739  }
740  }
741 
742  PQclear(dbres);
743 
744  PQfinish(conn_template1);
745 
746  check_ok();
747 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
void prep_status(const char *fmt,...) pg_attribute_printf(1
static void check_ok(void)
Definition: initdb.c:2051
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:2832
void PQclear(PGresult *res)
Definition: fe-exec.c:671

◆ create_script_for_cluster_analyze()

void create_script_for_cluster_analyze ( char **  analyze_script_file_name)

Definition at line 427 of file check.c.

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendShellString(), ClusterInfo::bindir, check_ok(), PQExpBufferData::data, ECHO_BLANK, ECHO_QUOTE, fopen_priv(), GET_MAJOR_VERSION, initPQExpBuffer(), ClusterInfo::major_version, new_cluster, old_cluster, os_info, pg_fatal(), prep_status(), psprintf(), S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, strerror(), termPQExpBuffer(), OSInfo::user, and OSInfo::user_specified.

Referenced by main().

428 {
429  FILE *script = NULL;
430  PQExpBufferData user_specification;
431 
432  prep_status("Creating script to analyze new cluster");
433 
434  initPQExpBuffer(&user_specification);
436  {
437  appendPQExpBufferStr(&user_specification, "-U ");
438  appendShellString(&user_specification, os_info.user);
439  appendPQExpBufferChar(&user_specification, ' ');
440  }
441 
442  *analyze_script_file_name = psprintf("%sanalyze_new_cluster.%s",
444 
445  if ((script = fopen_priv(*analyze_script_file_name, "w")) == NULL)
446  pg_fatal("could not open file \"%s\": %s\n",
447  *analyze_script_file_name, strerror(errno));
448 
449 #ifndef WIN32
450  /* add shebang header */
451  fprintf(script, "#!/bin/sh\n\n");
452 #else
453  /* suppress command echoing */
454  fprintf(script, "@echo off\n");
455 #endif
456 
457  fprintf(script, "echo %sThis script will generate minimal optimizer statistics rapidly%s\n",
459  fprintf(script, "echo %sso your system is usable, and then gather statistics twice more%s\n",
461  fprintf(script, "echo %swith increasing accuracy. When it is done, your system will%s\n",
463  fprintf(script, "echo %shave the default level of optimizer statistics.%s\n",
465  fprintf(script, "echo%s\n\n", ECHO_BLANK);
466 
467  fprintf(script, "echo %sIf you have used ALTER TABLE to modify the statistics target for%s\n",
469  fprintf(script, "echo %sany tables, you might want to remove them and restore them after%s\n",
471  fprintf(script, "echo %srunning this script because they will delay fast statistics generation.%s\n",
473  fprintf(script, "echo%s\n\n", ECHO_BLANK);
474 
475  fprintf(script, "echo %sIf you would like default statistics as quickly as possible, cancel%s\n",
477  fprintf(script, "echo %sthis script and run:%s\n",
479  fprintf(script, "echo %s \"%s/vacuumdb\" %s--all %s%s\n", ECHO_QUOTE,
480  new_cluster.bindir, user_specification.data,
481  /* Did we copy the free space files? */
483  "--analyze-only" : "--analyze", ECHO_QUOTE);
484  fprintf(script, "echo%s\n\n", ECHO_BLANK);
485 
486  fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-in-stages\n",
487  new_cluster.bindir, user_specification.data);
488  /* Did we copy the free space files? */
490  fprintf(script, "\"%s/vacuumdb\" %s--all\n", new_cluster.bindir,
491  user_specification.data);
492 
493  fprintf(script, "echo%s\n\n", ECHO_BLANK);
494  fprintf(script, "echo %sDone%s\n",
496 
497  fclose(script);
498 
499 #ifndef WIN32
500  if (chmod(*analyze_script_file_name, S_IRWXU) != 0)
501  pg_fatal("could not add execute permission to file \"%s\": %s\n",
502  *analyze_script_file_name, strerror(errno));
503 #endif
504 
505  termPQExpBuffer(&user_specification);
506 
507  check_ok();
508 }
uint32 major_version
Definition: pg_upgrade.h:274
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define SCRIPT_EXT
Definition: pg_upgrade.h:80
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
FILE * fopen_priv(const char *path, const char *mode)
Definition: file.c:321
bool user_specified
Definition: pg_upgrade.h:312
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static void check_ok(void)
Definition: initdb.c:2051
char * bindir
Definition: pg_upgrade.h:269
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:434
#define ECHO_BLANK
Definition: pg_upgrade.h:82
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:79
#define S_IRWXU
Definition: win32_port.h:280
const char * strerror(int errnum)
Definition: strerror.c:19
OSInfo os_info
Definition: pg_upgrade.c:58
#define ECHO_QUOTE
Definition: pg_upgrade.h:81
char * user
Definition: pg_upgrade.h:311
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ create_script_for_old_cluster_deletion()

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name)

Definition at line 517 of file check.c.

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv(), GET_MAJOR_VERSION, ClusterInfo::major_version, MAXPGPATH, DbInfoArr::ndbs, new_cluster, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_QUOTE, PATH_SEPARATOR, pfree(), pg_fatal(), pg_free(), pg_log(), pg_strdup(), PG_WARNING, ClusterInfo::pgdata, prep_status(), psprintf(), RM_CMD, RMDIR_CMD, S_IRWXU, SCRIPT_EXT, SCRIPT_PREFIX, strerror(), strlcpy(), and ClusterInfo::tablespace_suffix.

Referenced by main().

518 {
519  FILE *script = NULL;
520  int tblnum;
521  char old_cluster_pgdata[MAXPGPATH],
522  new_cluster_pgdata[MAXPGPATH];
523 
524  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
526 
527  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
528  canonicalize_path(old_cluster_pgdata);
529 
530  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
531  canonicalize_path(new_cluster_pgdata);
532 
533  /* Some people put the new data directory inside the old one. */
534  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
535  {
537  "\nWARNING: new data directory should not be inside the old data directory, e.g. %s\n", old_cluster_pgdata);
538 
539  /* Unlink file in case it is left over from a previous run. */
540  unlink(*deletion_script_file_name);
541  pg_free(*deletion_script_file_name);
542  *deletion_script_file_name = NULL;
543  return;
544  }
545 
546  /*
547  * Some users (oddly) create tablespaces inside the cluster data
548  * directory. We can't create a proper old cluster delete script in that
549  * case.
550  */
551  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
552  {
553  char old_tablespace_dir[MAXPGPATH];
554 
555  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
556  canonicalize_path(old_tablespace_dir);
557  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
558  {
559  /* reproduce warning from CREATE TABLESPACE that is in the log */
561  "\nWARNING: user-defined tablespace locations should not be inside the data directory, e.g. %s\n", old_tablespace_dir);
562 
563  /* Unlink file in case it is left over from a previous run. */
564  unlink(*deletion_script_file_name);
565  pg_free(*deletion_script_file_name);
566  *deletion_script_file_name = NULL;
567  return;
568  }
569  }
570 
571  prep_status("Creating script to delete old cluster");
572 
573  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
574  pg_fatal("could not open file \"%s\": %s\n",
575  *deletion_script_file_name, strerror(errno));
576 
577 #ifndef WIN32
578  /* add shebang header */
579  fprintf(script, "#!/bin/sh\n\n");
580 #endif
581 
582  /* delete old cluster's default tablespace */
583  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
585 
586  /* delete old cluster's alternate tablespaces */
587  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
588  {
589  /*
590  * Do the old cluster's per-database directories share a directory
591  * with a new version-specific tablespace?
592  */
593  if (strlen(old_cluster.tablespace_suffix) == 0)
594  {
595  /* delete per-database directories */
596  int dbnum;
597 
598  fprintf(script, "\n");
599  /* remove PG_VERSION? */
601  fprintf(script, RM_CMD " %s%cPG_VERSION\n",
604 
605  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
606  fprintf(script, RMDIR_CMD " %c%s%c%d%c\n", PATH_QUOTE,
609  PATH_QUOTE);
610  }
611  else
612  {
613  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
614 
615  /*
616  * Simply delete the tablespace directory, which might be ".old"
617  * or a version-specific subdirectory.
618  */
619  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
621  fix_path_separator(suffix_path), PATH_QUOTE);
622  pfree(suffix_path);
623  }
624  }
625 
626  fclose(script);
627 
628 #ifndef WIN32
629  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
630  pg_fatal("could not add execute permission to file \"%s\": %s\n",
631  *deletion_script_file_name, strerror(errno));
632 #endif
633 
634  check_ok();
635 }
uint32 major_version
Definition: pg_upgrade.h:274
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:438
#define PATH_SEPARATOR
Definition: pg_upgrade.h:75
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define SCRIPT_EXT
Definition: pg_upgrade.h:80
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
void canonicalize_path(char *path)
Definition: path.c:254
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
FILE * fopen_priv(const char *path, const char *mode)
Definition: file.c:321
Oid db_oid
Definition: pg_upgrade.h:186
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
void pfree(void *pointer)
Definition: mcxt.c:949
#define MAXPGPATH
#define RMDIR_CMD
Definition: pg_upgrade.h:78
void prep_status(const char *fmt,...) pg_attribute_printf(1
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
static void check_ok(void)
Definition: initdb.c:2051
char ** old_tablespaces
Definition: pg_upgrade.h:313
const char * tablespace_suffix
Definition: pg_upgrade.h:277
DbInfoArr dbarr
Definition: pg_upgrade.h:265
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:79
#define PATH_QUOTE
Definition: pg_upgrade.h:76
char * pgdata
Definition: pg_upgrade.h:266
#define S_IRWXU
Definition: win32_port.h:280
int num_old_tablespaces
Definition: pg_upgrade.h:314
const char * strerror(int errnum)
Definition: strerror.c:19
OSInfo os_info
Definition: pg_upgrade.c:58
DbInfo * dbs
Definition: pg_upgrade.h:198
#define RM_CMD
Definition: pg_upgrade.h:77
static char * fix_path_separator(char *path)
Definition: check.c:40

◆ equivalent_locale()

static bool equivalent_locale ( int  category,
const char *  loca,
const char *  locb 
)
static

Definition at line 328 of file check.c.

References get_canonical_locale_name(), pg_free(), pg_strcasecmp(), and pg_strncasecmp().

Referenced by check_locale_and_encoding().

329 {
330  const char *chara;
331  const char *charb;
332  char *canona;
333  char *canonb;
334  int lena;
335  int lenb;
336 
337  /*
338  * If the names are equal, the locales are equivalent. Checking this first
339  * avoids calling setlocale() in the common case that the names are equal.
340  * That's a good thing, if setlocale() is buggy, for example.
341  */
342  if (pg_strcasecmp(loca, locb) == 0)
343  return true;
344 
345  /*
346  * Not identical. Canonicalize both names, remove the encoding parts, and
347  * try again.
348  */
349  canona = get_canonical_locale_name(category, loca);
350  chara = strrchr(canona, '.');
351  lena = chara ? (chara - canona) : strlen(canona);
352 
353  canonb = get_canonical_locale_name(category, locb);
354  charb = strrchr(canonb, '.');
355  lenb = charb ? (charb - canonb) : strlen(canonb);
356 
357  if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0)
358  {
359  pg_free(canona);
360  pg_free(canonb);
361  return true;
362  }
363 
364  pg_free(canona);
365  pg_free(canonb);
366  return false;
367 }
static char * get_canonical_locale_name(int category, const char *locale)
Definition: check.c:1107
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void pg_free(void *ptr)
Definition: fe_memutils.c:105

◆ fix_path_separator()

static char* fix_path_separator ( char *  path)
static

Definition at line 40 of file check.c.

References pg_strdup().

Referenced by create_script_for_old_cluster_deletion().

41 {
42 #ifdef WIN32
43 
44  char *result;
45  char *c;
46 
47  result = pg_strdup(path);
48 
49  for (c = result; *c != '\0'; c++)
50  if (*c == '/')
51  *c = '\\';
52 
53  return result;
54 #else
55 
56  return path;
57 #endif
58 }
char * c
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85

◆ get_canonical_locale_name()

static char * get_canonical_locale_name ( int  category,
const char *  locale 
)
static

Definition at line 1107 of file check.c.

References pg_fatal(), pg_free(), pg_strdup(), and setlocale.

Referenced by equivalent_locale().

1108 {
1109  char *save;
1110  char *res;
1111 
1112  /* get the current setting, so we can restore it. */
1113  save = setlocale(category, NULL);
1114  if (!save)
1115  pg_fatal("failed to get the current locale\n");
1116 
1117  /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
1118  save = pg_strdup(save);
1119 
1120  /* set the locale with setlocale, to see if it accepts it. */
1121  res = setlocale(category, locale);
1122 
1123  if (!res)
1124  pg_fatal("failed to get system locale name for \"%s\"\n", locale);
1125 
1126  res = pg_strdup(res);
1127 
1128  /* restore old value. */
1129  if (!setlocale(category, save))
1130  pg_fatal("failed to restore old locale \"%s\"\n", save);
1131 
1132  pg_free(save);
1133 
1134  return res;
1135 }
#define setlocale(a, b)
Definition: win32_port.h:419
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static char * locale
Definition: initdb.c:124

◆ issue_warnings_and_set_wal_level()

void issue_warnings_and_set_wal_level ( void  )

Definition at line 179 of file check.c.

References GET_MAJOR_VERSION, ClusterInfo::major_version, new_9_0_populate_pg_largeobject_metadata(), new_cluster, old_9_6_invalidate_hash_indexes(), old_cluster, start_postmaster(), and stop_postmaster().

Referenced by main().

180 {
181  /*
182  * We unconditionally start/stop the new server because pg_resetwal -o set
183  * wal_level to 'minimum'. If the user is upgrading standby servers using
184  * the rsync instructions, they will need pg_upgrade to write its final
185  * WAL record showing wal_level as 'replica'.
186  */
188 
189  /* Create dummy large object permissions for old < PG 9.0? */
192 
193  /* Reindex hash indexes for old < 10.0 */
196 
197  stop_postmaster(false);
198 }
uint32 major_version
Definition: pg_upgrade.h:274
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:297
void stop_postmaster(bool fast)
Definition: server.c:325
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster, bool check_mode)
Definition: version.c:25
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static pgpid_t start_postmaster(void)
Definition: pg_ctl.c:442

◆ output_check_banner()

void output_check_banner ( bool  live_check)

Definition at line 61 of file check.c.

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

Referenced by main().

62 {
63  if (user_opts.check && live_check)
64  {
66  "Performing Consistency Checks on Old Live Server\n"
67  "------------------------------------------------\n");
68  }
69  else
70  {
72  "Performing Consistency Checks\n"
73  "-----------------------------\n");
74  }
75 }
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
UserOpts user_opts
Definition: option.c:29
bool check
Definition: pg_upgrade.h:297

◆ output_completion_banner()

void output_completion_banner ( char *  analyze_script_file_name,
char *  deletion_script_file_name 
)

Definition at line 202 of file check.c.

References GET_MAJOR_VERSION, ClusterInfo::major_version, old_cluster, pg_log(), and PG_REPORT.

Referenced by main().

204 {
205  /* Did we copy the free space files? */
208  "Optimizer statistics are not transferred by pg_upgrade so,\n"
209  "once you start the new server, consider running:\n"
210  " %s\n\n", analyze_script_file_name);
211  else
213  "Optimizer statistics and free space information are not transferred\n"
214  "by pg_upgrade so, once you start the new server, consider running:\n"
215  " %s\n\n", analyze_script_file_name);
216 
217 
218  if (deletion_script_file_name)
220  "Running this script will delete the old cluster's data files:\n"
221  " %s\n",
222  deletion_script_file_name);
223  else
225  "Could not create a script to delete the old cluster's data files\n"
226  "because user-defined tablespaces or the new cluster's data directory\n"
227  "exist in the old cluster directory. The old cluster's contents must\n"
228  "be deleted manually.\n");
229 }
uint32 major_version
Definition: pg_upgrade.h:274
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69

◆ report_clusters_compatible()

void report_clusters_compatible ( void  )

Definition at line 162 of file check.c.

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

Referenced by main().

163 {
164  if (user_opts.check)
165  {
166  pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
167  /* stops new cluster */
168  stop_postmaster(false);
169  exit(0);
170  }
171 
172  pg_log(PG_REPORT, "\n"
173  "If pg_upgrade fails after this point, you must re-initdb the\n"
174  "new cluster before continuing.\n");
175 }
void stop_postmaster(bool fast)
Definition: server.c:325
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
UserOpts user_opts
Definition: option.c:29
bool check
Definition: pg_upgrade.h:297