LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - check.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16devel Lines: 201 508 39.6 %
Date: 2022-12-05 10:11:06 Functions: 21 29 72.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  check.c
       3             :  *
       4             :  *  server checks and output routines
       5             :  *
       6             :  *  Copyright (c) 2010-2022, PostgreSQL Global Development Group
       7             :  *  src/bin/pg_upgrade/check.c
       8             :  */
       9             : 
      10             : #include "postgres_fe.h"
      11             : 
      12             : #include "catalog/pg_authid_d.h"
      13             : #include "catalog/pg_collation.h"
      14             : #include "fe_utils/string_utils.h"
      15             : #include "mb/pg_wchar.h"
      16             : #include "pg_upgrade.h"
      17             : 
      18             : static void check_new_cluster_is_empty(void);
      19             : static void check_databases_are_compatible(void);
      20             : static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb);
      21             : static bool equivalent_locale(int category, const char *loca, const char *locb);
      22             : static void check_is_install_user(ClusterInfo *cluster);
      23             : static void check_proper_datallowconn(ClusterInfo *cluster);
      24             : static void check_for_prepared_transactions(ClusterInfo *cluster);
      25             : static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
      26             : static void check_for_user_defined_postfix_ops(ClusterInfo *cluster);
      27             : static void check_for_incompatible_polymorphics(ClusterInfo *cluster);
      28             : static void check_for_tables_with_oids(ClusterInfo *cluster);
      29             : static void check_for_composite_data_type_usage(ClusterInfo *cluster);
      30             : static void check_for_reg_data_type_usage(ClusterInfo *cluster);
      31             : static void check_for_aclitem_data_type_usage(ClusterInfo *cluster);
      32             : static void check_for_jsonb_9_4_usage(ClusterInfo *cluster);
      33             : static void check_for_pg_role_prefix(ClusterInfo *cluster);
      34             : static void check_for_new_tablespace_dir(ClusterInfo *new_cluster);
      35             : static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster);
      36             : static char *get_canonical_locale_name(int category, const char *locale);
      37             : 
      38             : 
      39             : /*
      40             :  * fix_path_separator
      41             :  * For non-Windows, just return the argument.
      42             :  * For Windows convert any forward slash to a backslash
      43             :  * such as is suitable for arguments to builtin commands
      44             :  * like RMDIR and DEL.
      45             :  */
      46             : static char *
      47           2 : fix_path_separator(char *path)
      48             : {
      49             : #ifdef WIN32
      50             : 
      51             :     char       *result;
      52             :     char       *c;
      53             : 
      54             :     result = pg_strdup(path);
      55             : 
      56             :     for (c = result; *c != '\0'; c++)
      57             :         if (*c == '/')
      58             :             *c = '\\';
      59             : 
      60             :     return result;
      61             : #else
      62             : 
      63           2 :     return path;
      64             : #endif
      65             : }
      66             : 
      67             : void
      68           4 : output_check_banner(bool live_check)
      69             : {
      70           4 :     if (user_opts.check && live_check)
      71             :     {
      72           0 :         pg_log(PG_REPORT,
      73             :                "Performing Consistency Checks on Old Live Server\n"
      74             :                "------------------------------------------------");
      75             :     }
      76             :     else
      77             :     {
      78           4 :         pg_log(PG_REPORT,
      79             :                "Performing Consistency Checks\n"
      80             :                "-----------------------------");
      81             :     }
      82           4 : }
      83             : 
      84             : 
      85             : void
      86           4 : check_and_dump_old_cluster(bool live_check)
      87             : {
      88             :     /* -- OLD -- */
      89             : 
      90           4 :     if (!live_check)
      91           4 :         start_postmaster(&old_cluster, true);
      92             : 
      93             :     /* Extract a list of databases and tables from the old cluster */
      94           4 :     get_db_and_rel_infos(&old_cluster);
      95             : 
      96           4 :     init_tablespaces();
      97             : 
      98           4 :     get_loadable_libraries();
      99             : 
     100             : 
     101             :     /*
     102             :      * Check for various failure cases
     103             :      */
     104           4 :     check_is_install_user(&old_cluster);
     105           4 :     check_proper_datallowconn(&old_cluster);
     106           4 :     check_for_prepared_transactions(&old_cluster);
     107           4 :     check_for_composite_data_type_usage(&old_cluster);
     108           4 :     check_for_reg_data_type_usage(&old_cluster);
     109           4 :     check_for_isn_and_int8_passing_mismatch(&old_cluster);
     110             : 
     111             :     /*
     112             :      * PG 16 increased the size of the 'aclitem' type, which breaks the on-disk
     113             :      * format for existing data.
     114             :      */
     115           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1500)
     116           0 :         check_for_aclitem_data_type_usage(&old_cluster);
     117             : 
     118             :     /*
     119             :      * PG 14 changed the function signature of encoding conversion functions.
     120             :      * Conversions from older versions cannot be upgraded automatically
     121             :      * because the user-defined functions used by the encoding conversions
     122             :      * need to be changed to match the new signature.
     123             :      */
     124           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
     125           0 :         check_for_user_defined_encoding_conversions(&old_cluster);
     126             : 
     127             :     /*
     128             :      * Pre-PG 14 allowed user defined postfix operators, which are not
     129             :      * supported anymore.  Verify there are none, iff applicable.
     130             :      */
     131           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
     132           0 :         check_for_user_defined_postfix_ops(&old_cluster);
     133             : 
     134             :     /*
     135             :      * PG 14 changed polymorphic functions from anyarray to
     136             :      * anycompatiblearray.
     137             :      */
     138           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
     139           0 :         check_for_incompatible_polymorphics(&old_cluster);
     140             : 
     141             :     /*
     142             :      * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
     143             :      * supported anymore. Verify there are none, iff applicable.
     144             :      */
     145           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
     146           0 :         check_for_tables_with_oids(&old_cluster);
     147             : 
     148             :     /*
     149             :      * PG 12 changed the 'sql_identifier' type storage to be based on name,
     150             :      * not varchar, which breaks on-disk format for existing data. So we need
     151             :      * to prevent upgrade when used in user objects (tables, indexes, ...).
     152             :      */
     153           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
     154           0 :         old_11_check_for_sql_identifier_data_type_usage(&old_cluster);
     155             : 
     156             :     /*
     157             :      * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
     158             :      * hash indexes
     159             :      */
     160           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
     161             :     {
     162           0 :         old_9_6_check_for_unknown_data_type_usage(&old_cluster);
     163           0 :         if (user_opts.check)
     164           0 :             old_9_6_invalidate_hash_indexes(&old_cluster, true);
     165             :     }
     166             : 
     167             :     /* 9.5 and below should not have roles starting with pg_ */
     168           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905)
     169           0 :         check_for_pg_role_prefix(&old_cluster);
     170             : 
     171           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 &&
     172           0 :         old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
     173           0 :         check_for_jsonb_9_4_usage(&old_cluster);
     174             : 
     175             :     /* Pre-PG 9.4 had a different 'line' data type internal format */
     176           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
     177           0 :         old_9_3_check_for_line_data_type_usage(&old_cluster);
     178             : 
     179             :     /*
     180             :      * While not a check option, we do this now because this is the only time
     181             :      * the old server is running.
     182             :      */
     183           4 :     if (!user_opts.check)
     184           2 :         generate_old_dump();
     185             : 
     186           4 :     if (!live_check)
     187           4 :         stop_postmaster(false);
     188           4 : }
     189             : 
     190             : 
     191             : void
     192           4 : check_new_cluster(void)
     193             : {
     194           4 :     get_db_and_rel_infos(&new_cluster);
     195             : 
     196           4 :     check_new_cluster_is_empty();
     197           4 :     check_databases_are_compatible();
     198             : 
     199           4 :     check_loadable_libraries();
     200             : 
     201           4 :     switch (user_opts.transfer_mode)
     202             :     {
     203           0 :         case TRANSFER_MODE_CLONE:
     204           0 :             check_file_clone();
     205           0 :             break;
     206           4 :         case TRANSFER_MODE_COPY:
     207           4 :             break;
     208           0 :         case TRANSFER_MODE_LINK:
     209           0 :             check_hard_link();
     210           0 :             break;
     211             :     }
     212             : 
     213           4 :     check_is_install_user(&new_cluster);
     214             : 
     215           4 :     check_for_prepared_transactions(&new_cluster);
     216             : 
     217           4 :     check_for_new_tablespace_dir(&new_cluster);
     218           4 : }
     219             : 
     220             : 
     221             : void
     222           4 : report_clusters_compatible(void)
     223             : {
     224           4 :     if (user_opts.check)
     225             :     {
     226           2 :         pg_log(PG_REPORT, "\n*Clusters are compatible*");
     227             :         /* stops new cluster */
     228           2 :         stop_postmaster(false);
     229             : 
     230           2 :         cleanup_output_dirs();
     231           2 :         exit(0);
     232             :     }
     233             : 
     234           2 :     pg_log(PG_REPORT, "\n"
     235             :            "If pg_upgrade fails after this point, you must re-initdb the\n"
     236             :            "new cluster before continuing.");
     237           2 : }
     238             : 
     239             : 
     240             : void
     241           2 : issue_warnings_and_set_wal_level(void)
     242             : {
     243             :     /*
     244             :      * We unconditionally start/stop the new server because pg_resetwal -o set
     245             :      * wal_level to 'minimum'.  If the user is upgrading standby servers using
     246             :      * the rsync instructions, they will need pg_upgrade to write its final
     247             :      * WAL record showing wal_level as 'replica'.
     248             :      */
     249           2 :     start_postmaster(&new_cluster, true);
     250             : 
     251             :     /* Reindex hash indexes for old < 10.0 */
     252           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
     253           0 :         old_9_6_invalidate_hash_indexes(&new_cluster, false);
     254             : 
     255           2 :     report_extension_updates(&new_cluster);
     256             : 
     257           2 :     stop_postmaster(false);
     258           2 : }
     259             : 
     260             : 
     261             : void
     262           2 : output_completion_banner(char *deletion_script_file_name)
     263             : {
     264             :     PQExpBufferData user_specification;
     265             : 
     266           2 :     initPQExpBuffer(&user_specification);
     267           2 :     if (os_info.user_specified)
     268             :     {
     269           0 :         appendPQExpBufferStr(&user_specification, "-U ");
     270           0 :         appendShellString(&user_specification, os_info.user);
     271           0 :         appendPQExpBufferChar(&user_specification, ' ');
     272             :     }
     273             : 
     274           2 :     pg_log(PG_REPORT,
     275             :            "Optimizer statistics are not transferred by pg_upgrade.\n"
     276             :            "Once you start the new server, consider running:\n"
     277             :            "    %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
     278             : 
     279           2 :     if (deletion_script_file_name)
     280           2 :         pg_log(PG_REPORT,
     281             :                "Running this script will delete the old cluster's data files:\n"
     282             :                "    %s",
     283             :                deletion_script_file_name);
     284             :     else
     285           0 :         pg_log(PG_REPORT,
     286             :                "Could not create a script to delete the old cluster's data files\n"
     287             :                "because user-defined tablespaces or the new cluster's data directory\n"
     288             :                "exist in the old cluster directory.  The old cluster's contents must\n"
     289             :                "be deleted manually.");
     290             : 
     291           2 :     termPQExpBuffer(&user_specification);
     292           2 : }
     293             : 
     294             : 
     295             : void
     296           4 : check_cluster_versions(void)
     297             : {
     298           4 :     prep_status("Checking cluster versions");
     299             : 
     300             :     /* cluster versions should already have been obtained */
     301             :     Assert(old_cluster.major_version != 0);
     302             :     Assert(new_cluster.major_version != 0);
     303             : 
     304             :     /*
     305             :      * We allow upgrades from/to the same major version for alpha/beta
     306             :      * upgrades
     307             :      */
     308             : 
     309           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) < 902)
     310           0 :         pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
     311             :                  "9.2");
     312             : 
     313             :     /* Only current PG version is supported as a target */
     314           4 :     if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
     315           0 :         pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
     316             :                  PG_MAJORVERSION);
     317             : 
     318             :     /*
     319             :      * We can't allow downgrading because we use the target pg_dump, and
     320             :      * pg_dump cannot operate on newer database versions, only current and
     321             :      * older versions.
     322             :      */
     323           4 :     if (old_cluster.major_version > new_cluster.major_version)
     324           0 :         pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
     325             : 
     326             :     /* Ensure binaries match the designated data directories */
     327           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) !=
     328           4 :         GET_MAJOR_VERSION(old_cluster.bin_version))
     329           0 :         pg_fatal("Old cluster data and binary directories are from different major versions.");
     330           4 :     if (GET_MAJOR_VERSION(new_cluster.major_version) !=
     331           4 :         GET_MAJOR_VERSION(new_cluster.bin_version))
     332           0 :         pg_fatal("New cluster data and binary directories are from different major versions.");
     333             : 
     334           4 :     check_ok();
     335           4 : }
     336             : 
     337             : 
     338             : void
     339           4 : check_cluster_compatibility(bool live_check)
     340             : {
     341             :     /* get/check pg_control data of servers */
     342           4 :     get_control_data(&old_cluster, live_check);
     343           4 :     get_control_data(&new_cluster, false);
     344           4 :     check_control_data(&old_cluster.controldata, &new_cluster.controldata);
     345             : 
     346           4 :     if (live_check && old_cluster.port == new_cluster.port)
     347           0 :         pg_fatal("When checking a live server, "
     348             :                  "the old and new port numbers must be different.");
     349           4 : }
     350             : 
     351             : 
     352             : /*
     353             :  * check_locale_and_encoding()
     354             :  *
     355             :  * Check that locale and encoding of a database in the old and new clusters
     356             :  * are compatible.
     357             :  */
     358             : static void
     359           8 : check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb)
     360             : {
     361           8 :     if (olddb->db_encoding != newdb->db_encoding)
     362           0 :         pg_fatal("encodings for database \"%s\" do not match:  old \"%s\", new \"%s\"",
     363             :                  olddb->db_name,
     364             :                  pg_encoding_to_char(olddb->db_encoding),
     365             :                  pg_encoding_to_char(newdb->db_encoding));
     366           8 :     if (!equivalent_locale(LC_COLLATE, olddb->db_collate, newdb->db_collate))
     367           0 :         pg_fatal("lc_collate values for database \"%s\" do not match:  old \"%s\", new \"%s\"",
     368             :                  olddb->db_name, olddb->db_collate, newdb->db_collate);
     369           8 :     if (!equivalent_locale(LC_CTYPE, olddb->db_ctype, newdb->db_ctype))
     370           0 :         pg_fatal("lc_ctype values for database \"%s\" do not match:  old \"%s\", new \"%s\"",
     371             :                  olddb->db_name, olddb->db_ctype, newdb->db_ctype);
     372           8 :     if (olddb->db_collprovider != newdb->db_collprovider)
     373           0 :         pg_fatal("locale providers for database \"%s\" do not match:  old \"%s\", new \"%s\"",
     374             :                  olddb->db_name,
     375           0 :                  collprovider_name(olddb->db_collprovider),
     376           0 :                  collprovider_name(newdb->db_collprovider));
     377           8 :     if ((olddb->db_iculocale == NULL && newdb->db_iculocale != NULL) ||
     378           8 :         (olddb->db_iculocale != NULL && newdb->db_iculocale == NULL) ||
     379           8 :         (olddb->db_iculocale != NULL && newdb->db_iculocale != NULL && strcmp(olddb->db_iculocale, newdb->db_iculocale) != 0))
     380           0 :         pg_fatal("ICU locale values for database \"%s\" do not match:  old \"%s\", new \"%s\"",
     381             :                  olddb->db_name,
     382           0 :                  olddb->db_iculocale ? olddb->db_iculocale : "(null)",
     383           0 :                  newdb->db_iculocale ? newdb->db_iculocale : "(null)");
     384           8 : }
     385             : 
     386             : /*
     387             :  * equivalent_locale()
     388             :  *
     389             :  * Best effort locale-name comparison.  Return false if we are not 100% sure
     390             :  * the locales are equivalent.
     391             :  *
     392             :  * Note: The encoding parts of the names are ignored. This function is
     393             :  * currently used to compare locale names stored in pg_database, and
     394             :  * pg_database contains a separate encoding field. That's compared directly
     395             :  * in check_locale_and_encoding().
     396             :  */
     397             : static bool
     398          16 : equivalent_locale(int category, const char *loca, const char *locb)
     399             : {
     400             :     const char *chara;
     401             :     const char *charb;
     402             :     char       *canona;
     403             :     char       *canonb;
     404             :     int         lena;
     405             :     int         lenb;
     406             : 
     407             :     /*
     408             :      * If the names are equal, the locales are equivalent. Checking this first
     409             :      * avoids calling setlocale() in the common case that the names are equal.
     410             :      * That's a good thing, if setlocale() is buggy, for example.
     411             :      */
     412          16 :     if (pg_strcasecmp(loca, locb) == 0)
     413          16 :         return true;
     414             : 
     415             :     /*
     416             :      * Not identical. Canonicalize both names, remove the encoding parts, and
     417             :      * try again.
     418             :      */
     419           0 :     canona = get_canonical_locale_name(category, loca);
     420           0 :     chara = strrchr(canona, '.');
     421           0 :     lena = chara ? (chara - canona) : strlen(canona);
     422             : 
     423           0 :     canonb = get_canonical_locale_name(category, locb);
     424           0 :     charb = strrchr(canonb, '.');
     425           0 :     lenb = charb ? (charb - canonb) : strlen(canonb);
     426             : 
     427           0 :     if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0)
     428             :     {
     429           0 :         pg_free(canona);
     430           0 :         pg_free(canonb);
     431           0 :         return true;
     432             :     }
     433             : 
     434           0 :     pg_free(canona);
     435           0 :     pg_free(canonb);
     436           0 :     return false;
     437             : }
     438             : 
     439             : 
     440             : static void
     441           4 : check_new_cluster_is_empty(void)
     442             : {
     443             :     int         dbnum;
     444             : 
     445          12 :     for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
     446             :     {
     447             :         int         relnum;
     448           8 :         RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
     449             : 
     450          24 :         for (relnum = 0; relnum < rel_arr->nrels;
     451          16 :              relnum++)
     452             :         {
     453             :             /* pg_largeobject and its index should be skipped */
     454          16 :             if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
     455           0 :                 pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
     456           0 :                          new_cluster.dbarr.dbs[dbnum].db_name,
     457           0 :                          rel_arr->rels[relnum].nspname,
     458           0 :                          rel_arr->rels[relnum].relname);
     459             :         }
     460             :     }
     461           4 : }
     462             : 
     463             : /*
     464             :  * Check that every database that already exists in the new cluster is
     465             :  * compatible with the corresponding database in the old one.
     466             :  */
     467             : static void
     468           4 : check_databases_are_compatible(void)
     469             : {
     470             :     int         newdbnum;
     471             :     int         olddbnum;
     472             :     DbInfo     *newdbinfo;
     473             :     DbInfo     *olddbinfo;
     474             : 
     475          12 :     for (newdbnum = 0; newdbnum < new_cluster.dbarr.ndbs; newdbnum++)
     476             :     {
     477           8 :         newdbinfo = &new_cluster.dbarr.dbs[newdbnum];
     478             : 
     479             :         /* Find the corresponding database in the old cluster */
     480          12 :         for (olddbnum = 0; olddbnum < old_cluster.dbarr.ndbs; olddbnum++)
     481             :         {
     482          12 :             olddbinfo = &old_cluster.dbarr.dbs[olddbnum];
     483          12 :             if (strcmp(newdbinfo->db_name, olddbinfo->db_name) == 0)
     484             :             {
     485           8 :                 check_locale_and_encoding(olddbinfo, newdbinfo);
     486           8 :                 break;
     487             :             }
     488             :         }
     489             :     }
     490           4 : }
     491             : 
     492             : /*
     493             :  * A previous run of pg_upgrade might have failed and the new cluster
     494             :  * directory recreated, but they might have forgotten to remove
     495             :  * the new cluster's tablespace directories.  Therefore, check that
     496             :  * new cluster tablespace directories do not already exist.  If
     497             :  * they do, it would cause an error while restoring global objects.
     498             :  * This allows the failure to be detected at check time, rather than
     499             :  * during schema restore.
     500             :  */
     501             : static void
     502           4 : check_for_new_tablespace_dir(ClusterInfo *new_cluster)
     503             : {
     504             :     int         tblnum;
     505             :     char        new_tablespace_dir[MAXPGPATH];
     506             : 
     507           4 :     prep_status("Checking for new cluster tablespace directories");
     508             : 
     509           4 :     for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
     510             :     {
     511             :         struct stat statbuf;
     512             : 
     513           0 :         snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
     514           0 :                  os_info.old_tablespaces[tblnum],
     515             :                  new_cluster->tablespace_suffix);
     516             : 
     517           0 :         if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
     518           0 :             pg_fatal("new cluster tablespace directory already exists: \"%s\"",
     519             :                      new_tablespace_dir);
     520             :     }
     521             : 
     522           4 :     check_ok();
     523           4 : }
     524             : 
     525             : /*
     526             :  * create_script_for_old_cluster_deletion()
     527             :  *
     528             :  *  This is particularly useful for tablespace deletion.
     529             :  */
     530             : void
     531           2 : create_script_for_old_cluster_deletion(char **deletion_script_file_name)
     532             : {
     533           2 :     FILE       *script = NULL;
     534             :     int         tblnum;
     535             :     char        old_cluster_pgdata[MAXPGPATH],
     536             :                 new_cluster_pgdata[MAXPGPATH];
     537             : 
     538           2 :     *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
     539             :                                           SCRIPT_PREFIX, SCRIPT_EXT);
     540             : 
     541           2 :     strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
     542           2 :     canonicalize_path(old_cluster_pgdata);
     543             : 
     544           2 :     strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
     545           2 :     canonicalize_path(new_cluster_pgdata);
     546             : 
     547             :     /* Some people put the new data directory inside the old one. */
     548           2 :     if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
     549             :     {
     550           0 :         pg_log(PG_WARNING,
     551             :                "\nWARNING:  new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
     552             : 
     553             :         /* Unlink file in case it is left over from a previous run. */
     554           0 :         unlink(*deletion_script_file_name);
     555           0 :         pg_free(*deletion_script_file_name);
     556           0 :         *deletion_script_file_name = NULL;
     557           0 :         return;
     558             :     }
     559             : 
     560             :     /*
     561             :      * Some users (oddly) create tablespaces inside the cluster data
     562             :      * directory.  We can't create a proper old cluster delete script in that
     563             :      * case.
     564             :      */
     565           2 :     for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
     566             :     {
     567             :         char        old_tablespace_dir[MAXPGPATH];
     568             : 
     569           0 :         strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
     570           0 :         canonicalize_path(old_tablespace_dir);
     571           0 :         if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
     572             :         {
     573             :             /* reproduce warning from CREATE TABLESPACE that is in the log */
     574           0 :             pg_log(PG_WARNING,
     575             :                    "\nWARNING:  user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
     576             : 
     577             :             /* Unlink file in case it is left over from a previous run. */
     578           0 :             unlink(*deletion_script_file_name);
     579           0 :             pg_free(*deletion_script_file_name);
     580           0 :             *deletion_script_file_name = NULL;
     581           0 :             return;
     582             :         }
     583             :     }
     584             : 
     585           2 :     prep_status("Creating script to delete old cluster");
     586             : 
     587           2 :     if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
     588           0 :         pg_fatal("could not open file \"%s\": %s",
     589           0 :                  *deletion_script_file_name, strerror(errno));
     590             : 
     591             : #ifndef WIN32
     592             :     /* add shebang header */
     593           2 :     fprintf(script, "#!/bin/sh\n\n");
     594             : #endif
     595             : 
     596             :     /* delete old cluster's default tablespace */
     597           2 :     fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
     598             :             fix_path_separator(old_cluster.pgdata), PATH_QUOTE);
     599             : 
     600             :     /* delete old cluster's alternate tablespaces */
     601           2 :     for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
     602             :     {
     603             :         /*
     604             :          * Do the old cluster's per-database directories share a directory
     605             :          * with a new version-specific tablespace?
     606             :          */
     607           0 :         if (strlen(old_cluster.tablespace_suffix) == 0)
     608             :         {
     609             :             /* delete per-database directories */
     610             :             int         dbnum;
     611             : 
     612           0 :             fprintf(script, "\n");
     613             : 
     614           0 :             for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
     615           0 :                 fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
     616           0 :                         fix_path_separator(os_info.old_tablespaces[tblnum]),
     617           0 :                         PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid,
     618             :                         PATH_QUOTE);
     619             :         }
     620             :         else
     621             :         {
     622           0 :             char       *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
     623             : 
     624             :             /*
     625             :              * Simply delete the tablespace directory, which might be ".old"
     626             :              * or a version-specific subdirectory.
     627             :              */
     628           0 :             fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
     629           0 :                     fix_path_separator(os_info.old_tablespaces[tblnum]),
     630             :                     fix_path_separator(suffix_path), PATH_QUOTE);
     631           0 :             pfree(suffix_path);
     632             :         }
     633             :     }
     634             : 
     635           2 :     fclose(script);
     636             : 
     637             : #ifndef WIN32
     638           2 :     if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
     639           0 :         pg_fatal("could not add execute permission to file \"%s\": %s",
     640           0 :                  *deletion_script_file_name, strerror(errno));
     641             : #endif
     642             : 
     643           2 :     check_ok();
     644             : }
     645             : 
     646             : 
     647             : /*
     648             :  *  check_is_install_user()
     649             :  *
     650             :  *  Check we are the install user, and that the new cluster
     651             :  *  has no other users.
     652             :  */
     653             : static void
     654           8 : check_is_install_user(ClusterInfo *cluster)
     655             : {
     656             :     PGresult   *res;
     657           8 :     PGconn     *conn = connectToServer(cluster, "template1");
     658             : 
     659           8 :     prep_status("Checking database user is the install user");
     660             : 
     661             :     /* Can't use pg_authid because only superusers can view it. */
     662           8 :     res = executeQueryOrDie(conn,
     663             :                             "SELECT rolsuper, oid "
     664             :                             "FROM pg_catalog.pg_roles "
     665             :                             "WHERE rolname = current_user "
     666             :                             "AND rolname !~ '^pg_'");
     667             : 
     668             :     /*
     669             :      * We only allow the install user in the new cluster (see comment below)
     670             :      * and we preserve pg_authid.oid, so this must be the install user in the
     671             :      * old cluster too.
     672             :      */
     673           8 :     if (PQntuples(res) != 1 ||
     674           8 :         atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
     675           0 :         pg_fatal("database user \"%s\" is not the install user",
     676             :                  os_info.user);
     677             : 
     678           8 :     PQclear(res);
     679             : 
     680           8 :     res = executeQueryOrDie(conn,
     681             :                             "SELECT COUNT(*) "
     682             :                             "FROM pg_catalog.pg_roles "
     683             :                             "WHERE rolname !~ '^pg_'");
     684             : 
     685           8 :     if (PQntuples(res) != 1)
     686           0 :         pg_fatal("could not determine the number of users");
     687             : 
     688             :     /*
     689             :      * We only allow the install user in the new cluster because other defined
     690             :      * users might match users defined in the old cluster and generate an
     691             :      * error during pg_dump restore.
     692             :      */
     693           8 :     if (cluster == &new_cluster && atooid(PQgetvalue(res, 0, 0)) != 1)
     694           0 :         pg_fatal("Only the install user can be defined in the new cluster.");
     695             : 
     696           8 :     PQclear(res);
     697             : 
     698           8 :     PQfinish(conn);
     699             : 
     700           8 :     check_ok();
     701           8 : }
     702             : 
     703             : 
     704             : /*
     705             :  *  check_proper_datallowconn
     706             :  *
     707             :  *  Ensure that all non-template0 databases allow connections since they
     708             :  *  otherwise won't be restored; and that template0 explicitly doesn't allow
     709             :  *  connections since it would make pg_dumpall --globals restore fail.
     710             :  */
     711             : static void
     712           4 : check_proper_datallowconn(ClusterInfo *cluster)
     713             : {
     714             :     int         dbnum;
     715             :     PGconn     *conn_template1;
     716             :     PGresult   *dbres;
     717             :     int         ntups;
     718             :     int         i_datname;
     719             :     int         i_datallowconn;
     720           4 :     FILE       *script = NULL;
     721             :     char        output_path[MAXPGPATH];
     722             : 
     723           4 :     prep_status("Checking database connection settings");
     724             : 
     725           4 :     snprintf(output_path, sizeof(output_path), "%s/%s",
     726             :              log_opts.basedir,
     727             :              "databases_with_datallowconn_false.txt");
     728             : 
     729           4 :     conn_template1 = connectToServer(cluster, "template1");
     730             : 
     731             :     /* get database names */
     732           4 :     dbres = executeQueryOrDie(conn_template1,
     733             :                               "SELECT  datname, datallowconn "
     734             :                               "FROM    pg_catalog.pg_database");
     735             : 
     736           4 :     i_datname = PQfnumber(dbres, "datname");
     737           4 :     i_datallowconn = PQfnumber(dbres, "datallowconn");
     738             : 
     739           4 :     ntups = PQntuples(dbres);
     740          32 :     for (dbnum = 0; dbnum < ntups; dbnum++)
     741             :     {
     742          28 :         char       *datname = PQgetvalue(dbres, dbnum, i_datname);
     743          28 :         char       *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
     744             : 
     745          28 :         if (strcmp(datname, "template0") == 0)
     746             :         {
     747             :             /* avoid restore failure when pg_dumpall tries to create template0 */
     748           4 :             if (strcmp(datallowconn, "t") == 0)
     749           0 :                 pg_fatal("template0 must not allow connections, "
     750             :                          "i.e. its pg_database.datallowconn must be false");
     751             :         }
     752             :         else
     753             :         {
     754             :             /*
     755             :              * avoid datallowconn == false databases from being skipped on
     756             :              * restore
     757             :              */
     758          24 :             if (strcmp(datallowconn, "f") == 0)
     759             :             {
     760           0 :                 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
     761           0 :                     pg_fatal("could not open file \"%s\": %s",
     762           0 :                              output_path, strerror(errno));
     763             : 
     764           0 :                 fprintf(script, "%s\n", datname);
     765             :             }
     766             :         }
     767             :     }
     768             : 
     769           4 :     PQclear(dbres);
     770             : 
     771           4 :     PQfinish(conn_template1);
     772             : 
     773           4 :     if (script)
     774             :     {
     775           0 :         fclose(script);
     776           0 :         pg_log(PG_REPORT, "fatal");
     777           0 :         pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
     778             :                  "pg_database.datallowconn must be true.  Your installation contains\n"
     779             :                  "non-template0 databases with their pg_database.datallowconn set to\n"
     780             :                  "false.  Consider allowing connection for all non-template0 databases\n"
     781             :                  "or drop the databases which do not allow connections.  A list of\n"
     782             :                  "databases with the problem is in the file:\n"
     783             :                  "    %s", output_path);
     784             :     }
     785             :     else
     786           4 :         check_ok();
     787           4 : }
     788             : 
     789             : 
     790             : /*
     791             :  *  check_for_prepared_transactions()
     792             :  *
     793             :  *  Make sure there are no prepared transactions because the storage format
     794             :  *  might have changed.
     795             :  */
     796             : static void
     797           8 : check_for_prepared_transactions(ClusterInfo *cluster)
     798             : {
     799             :     PGresult   *res;
     800           8 :     PGconn     *conn = connectToServer(cluster, "template1");
     801             : 
     802           8 :     prep_status("Checking for prepared transactions");
     803             : 
     804           8 :     res = executeQueryOrDie(conn,
     805             :                             "SELECT * "
     806             :                             "FROM pg_catalog.pg_prepared_xacts");
     807             : 
     808           8 :     if (PQntuples(res) != 0)
     809             :     {
     810           0 :         if (cluster == &old_cluster)
     811           0 :             pg_fatal("The source cluster contains prepared transactions");
     812             :         else
     813           0 :             pg_fatal("The target cluster contains prepared transactions");
     814             :     }
     815             : 
     816           8 :     PQclear(res);
     817             : 
     818           8 :     PQfinish(conn);
     819             : 
     820           8 :     check_ok();
     821           8 : }
     822             : 
     823             : 
     824             : /*
     825             :  *  check_for_isn_and_int8_passing_mismatch()
     826             :  *
     827             :  *  contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
     828             :  *  by value.  The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
     829             :  *  it must match for the old and new servers.
     830             :  */
     831             : static void
     832           4 : check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
     833             : {
     834             :     int         dbnum;
     835           4 :     FILE       *script = NULL;
     836             :     char        output_path[MAXPGPATH];
     837             : 
     838           4 :     prep_status("Checking for contrib/isn with bigint-passing mismatch");
     839             : 
     840           4 :     if (old_cluster.controldata.float8_pass_by_value ==
     841           4 :         new_cluster.controldata.float8_pass_by_value)
     842             :     {
     843             :         /* no mismatch */
     844           4 :         check_ok();
     845           4 :         return;
     846             :     }
     847             : 
     848           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
     849             :              log_opts.basedir,
     850             :              "contrib_isn_and_int8_pass_by_value.txt");
     851             : 
     852           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
     853             :     {
     854             :         PGresult   *res;
     855           0 :         bool        db_used = false;
     856             :         int         ntups;
     857             :         int         rowno;
     858             :         int         i_nspname,
     859             :                     i_proname;
     860           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
     861           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
     862             : 
     863             :         /* Find any functions coming from contrib/isn */
     864           0 :         res = executeQueryOrDie(conn,
     865             :                                 "SELECT n.nspname, p.proname "
     866             :                                 "FROM  pg_catalog.pg_proc p, "
     867             :                                 "      pg_catalog.pg_namespace n "
     868             :                                 "WHERE p.pronamespace = n.oid AND "
     869             :                                 "      p.probin = '$libdir/isn'");
     870             : 
     871           0 :         ntups = PQntuples(res);
     872           0 :         i_nspname = PQfnumber(res, "nspname");
     873           0 :         i_proname = PQfnumber(res, "proname");
     874           0 :         for (rowno = 0; rowno < ntups; rowno++)
     875             :         {
     876           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
     877           0 :                 pg_fatal("could not open file \"%s\": %s",
     878           0 :                          output_path, strerror(errno));
     879           0 :             if (!db_used)
     880             :             {
     881           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
     882           0 :                 db_used = true;
     883             :             }
     884           0 :             fprintf(script, "  %s.%s\n",
     885             :                     PQgetvalue(res, rowno, i_nspname),
     886             :                     PQgetvalue(res, rowno, i_proname));
     887             :         }
     888             : 
     889           0 :         PQclear(res);
     890             : 
     891           0 :         PQfinish(conn);
     892             :     }
     893             : 
     894           0 :     if (script)
     895             :     {
     896           0 :         fclose(script);
     897           0 :         pg_log(PG_REPORT, "fatal");
     898           0 :         pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
     899             :                  "bigint data type.  Your old and new clusters pass bigint values\n"
     900             :                  "differently so this cluster cannot currently be upgraded.  You can\n"
     901             :                  "manually dump databases in the old cluster that use \"contrib/isn\"\n"
     902             :                  "facilities, drop them, perform the upgrade, and then restore them.  A\n"
     903             :                  "list of the problem functions is in the file:\n"
     904             :                  "    %s", output_path);
     905             :     }
     906             :     else
     907           0 :         check_ok();
     908             : }
     909             : 
     910             : /*
     911             :  * Verify that no user defined postfix operators exist.
     912             :  */
     913             : static void
     914           0 : check_for_user_defined_postfix_ops(ClusterInfo *cluster)
     915             : {
     916             :     int         dbnum;
     917           0 :     FILE       *script = NULL;
     918             :     char        output_path[MAXPGPATH];
     919             : 
     920           0 :     prep_status("Checking for user-defined postfix operators");
     921             : 
     922           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
     923             :              log_opts.basedir,
     924             :              "postfix_ops.txt");
     925             : 
     926             :     /* Find any user defined postfix operators */
     927           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
     928             :     {
     929             :         PGresult   *res;
     930           0 :         bool        db_used = false;
     931             :         int         ntups;
     932             :         int         rowno;
     933             :         int         i_oproid,
     934             :                     i_oprnsp,
     935             :                     i_oprname,
     936             :                     i_typnsp,
     937             :                     i_typname;
     938           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
     939           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
     940             : 
     941             :         /*
     942             :          * The query below hardcodes FirstNormalObjectId as 16384 rather than
     943             :          * interpolating that C #define into the query because, if that
     944             :          * #define is ever changed, the cutoff we want to use is the value
     945             :          * used by pre-version 14 servers, not that of some future version.
     946             :          */
     947           0 :         res = executeQueryOrDie(conn,
     948             :                                 "SELECT o.oid AS oproid, "
     949             :                                 "       n.nspname AS oprnsp, "
     950             :                                 "       o.oprname, "
     951             :                                 "       tn.nspname AS typnsp, "
     952             :                                 "       t.typname "
     953             :                                 "FROM pg_catalog.pg_operator o, "
     954             :                                 "     pg_catalog.pg_namespace n, "
     955             :                                 "     pg_catalog.pg_type t, "
     956             :                                 "     pg_catalog.pg_namespace tn "
     957             :                                 "WHERE o.oprnamespace = n.oid AND "
     958             :                                 "      o.oprleft = t.oid AND "
     959             :                                 "      t.typnamespace = tn.oid AND "
     960             :                                 "      o.oprright = 0 AND "
     961             :                                 "      o.oid >= 16384");
     962           0 :         ntups = PQntuples(res);
     963           0 :         i_oproid = PQfnumber(res, "oproid");
     964           0 :         i_oprnsp = PQfnumber(res, "oprnsp");
     965           0 :         i_oprname = PQfnumber(res, "oprname");
     966           0 :         i_typnsp = PQfnumber(res, "typnsp");
     967           0 :         i_typname = PQfnumber(res, "typname");
     968           0 :         for (rowno = 0; rowno < ntups; rowno++)
     969             :         {
     970           0 :             if (script == NULL &&
     971           0 :                 (script = fopen_priv(output_path, "w")) == NULL)
     972           0 :                 pg_fatal("could not open file \"%s\": %s",
     973           0 :                          output_path, strerror(errno));
     974           0 :             if (!db_used)
     975             :             {
     976           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
     977           0 :                 db_used = true;
     978             :             }
     979           0 :             fprintf(script, "  (oid=%s) %s.%s (%s.%s, NONE)\n",
     980             :                     PQgetvalue(res, rowno, i_oproid),
     981             :                     PQgetvalue(res, rowno, i_oprnsp),
     982             :                     PQgetvalue(res, rowno, i_oprname),
     983             :                     PQgetvalue(res, rowno, i_typnsp),
     984             :                     PQgetvalue(res, rowno, i_typname));
     985             :         }
     986             : 
     987           0 :         PQclear(res);
     988             : 
     989           0 :         PQfinish(conn);
     990             :     }
     991             : 
     992           0 :     if (script)
     993             :     {
     994           0 :         fclose(script);
     995           0 :         pg_log(PG_REPORT, "fatal");
     996           0 :         pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
     997             :                  "supported anymore.  Consider dropping the postfix operators and replacing\n"
     998             :                  "them with prefix operators or function calls.\n"
     999             :                  "A list of user-defined postfix operators is in the file:\n"
    1000             :                  "    %s", output_path);
    1001             :     }
    1002             :     else
    1003           0 :         check_ok();
    1004           0 : }
    1005             : 
    1006             : /*
    1007             :  *  check_for_incompatible_polymorphics()
    1008             :  *
    1009             :  *  Make sure nothing is using old polymorphic functions with
    1010             :  *  anyarray/anyelement rather than the new anycompatible variants.
    1011             :  */
    1012             : static void
    1013           0 : check_for_incompatible_polymorphics(ClusterInfo *cluster)
    1014             : {
    1015             :     PGresult   *res;
    1016           0 :     FILE       *script = NULL;
    1017             :     char        output_path[MAXPGPATH];
    1018             :     PQExpBufferData old_polymorphics;
    1019             : 
    1020           0 :     prep_status("Checking for incompatible polymorphic functions");
    1021             : 
    1022           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1023             :              log_opts.basedir,
    1024             :              "incompatible_polymorphics.txt");
    1025             : 
    1026             :     /* The set of problematic functions varies a bit in different versions */
    1027           0 :     initPQExpBuffer(&old_polymorphics);
    1028             : 
    1029           0 :     appendPQExpBufferStr(&old_polymorphics,
    1030             :                          "'array_append(anyarray,anyelement)'"
    1031             :                          ", 'array_cat(anyarray,anyarray)'"
    1032             :                          ", 'array_prepend(anyelement,anyarray)'");
    1033             : 
    1034           0 :     if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
    1035           0 :         appendPQExpBufferStr(&old_polymorphics,
    1036             :                              ", 'array_remove(anyarray,anyelement)'"
    1037             :                              ", 'array_replace(anyarray,anyelement,anyelement)'");
    1038             : 
    1039           0 :     if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
    1040           0 :         appendPQExpBufferStr(&old_polymorphics,
    1041             :                              ", 'array_position(anyarray,anyelement)'"
    1042             :                              ", 'array_position(anyarray,anyelement,integer)'"
    1043             :                              ", 'array_positions(anyarray,anyelement)'"
    1044             :                              ", 'width_bucket(anyelement,anyarray)'");
    1045             : 
    1046           0 :     for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    1047             :     {
    1048           0 :         bool        db_used = false;
    1049           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
    1050           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
    1051             :         int         ntups;
    1052             :         int         i_objkind,
    1053             :                     i_objname;
    1054             : 
    1055             :         /*
    1056             :          * The query below hardcodes FirstNormalObjectId as 16384 rather than
    1057             :          * interpolating that C #define into the query because, if that
    1058             :          * #define is ever changed, the cutoff we want to use is the value
    1059             :          * used by pre-version 14 servers, not that of some future version.
    1060             :          */
    1061           0 :         res = executeQueryOrDie(conn,
    1062             :         /* Aggregate transition functions */
    1063             :                                 "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
    1064             :                                 "FROM pg_proc AS p "
    1065             :                                 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
    1066             :                                 "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
    1067             :                                 "WHERE p.oid >= 16384 "
    1068             :                                 "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
    1069             :                                 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
    1070             : 
    1071             :         /* Aggregate final functions */
    1072             :                                 "UNION ALL "
    1073             :                                 "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
    1074             :                                 "FROM pg_proc AS p "
    1075             :                                 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
    1076             :                                 "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
    1077             :                                 "WHERE p.oid >= 16384 "
    1078             :                                 "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
    1079             :                                 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
    1080             : 
    1081             :         /* Operators */
    1082             :                                 "UNION ALL "
    1083             :                                 "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
    1084             :                                 "FROM pg_operator AS op "
    1085             :                                 "WHERE op.oid >= 16384 "
    1086             :                                 "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
    1087             :                                 "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);",
    1088             :                                 old_polymorphics.data,
    1089             :                                 old_polymorphics.data,
    1090             :                                 old_polymorphics.data);
    1091             : 
    1092           0 :         ntups = PQntuples(res);
    1093             : 
    1094           0 :         i_objkind = PQfnumber(res, "objkind");
    1095           0 :         i_objname = PQfnumber(res, "objname");
    1096             : 
    1097           0 :         for (int rowno = 0; rowno < ntups; rowno++)
    1098             :         {
    1099           0 :             if (script == NULL &&
    1100           0 :                 (script = fopen_priv(output_path, "w")) == NULL)
    1101           0 :                 pg_fatal("could not open file \"%s\": %s",
    1102           0 :                          output_path, strerror(errno));
    1103           0 :             if (!db_used)
    1104             :             {
    1105           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
    1106           0 :                 db_used = true;
    1107             :             }
    1108             : 
    1109           0 :             fprintf(script, "  %s: %s\n",
    1110             :                     PQgetvalue(res, rowno, i_objkind),
    1111             :                     PQgetvalue(res, rowno, i_objname));
    1112             :         }
    1113             : 
    1114           0 :         PQclear(res);
    1115           0 :         PQfinish(conn);
    1116             :     }
    1117             : 
    1118           0 :     if (script)
    1119             :     {
    1120           0 :         fclose(script);
    1121           0 :         pg_log(PG_REPORT, "fatal");
    1122           0 :         pg_fatal("Your installation contains user-defined objects that refer to internal\n"
    1123             :                  "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
    1124             :                  "These user-defined objects must be dropped before upgrading and restored\n"
    1125             :                  "afterwards, changing them to refer to the new corresponding functions with\n"
    1126             :                  "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
    1127             :                  "A list of the problematic objects is in the file:\n"
    1128             :                  "    %s", output_path);
    1129             :     }
    1130             :     else
    1131           0 :         check_ok();
    1132             : 
    1133           0 :     termPQExpBuffer(&old_polymorphics);
    1134           0 : }
    1135             : 
    1136             : /*
    1137             :  * Verify that no tables are declared WITH OIDS.
    1138             :  */
    1139             : static void
    1140           0 : check_for_tables_with_oids(ClusterInfo *cluster)
    1141             : {
    1142             :     int         dbnum;
    1143           0 :     FILE       *script = NULL;
    1144             :     char        output_path[MAXPGPATH];
    1145             : 
    1146           0 :     prep_status("Checking for tables WITH OIDS");
    1147             : 
    1148           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1149             :              log_opts.basedir,
    1150             :              "tables_with_oids.txt");
    1151             : 
    1152             :     /* Find any tables declared WITH OIDS */
    1153           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    1154             :     {
    1155             :         PGresult   *res;
    1156           0 :         bool        db_used = false;
    1157             :         int         ntups;
    1158             :         int         rowno;
    1159             :         int         i_nspname,
    1160             :                     i_relname;
    1161           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
    1162           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
    1163             : 
    1164           0 :         res = executeQueryOrDie(conn,
    1165             :                                 "SELECT n.nspname, c.relname "
    1166             :                                 "FROM  pg_catalog.pg_class c, "
    1167             :                                 "      pg_catalog.pg_namespace n "
    1168             :                                 "WHERE c.relnamespace = n.oid AND "
    1169             :                                 "      c.relhasoids AND"
    1170             :                                 "       n.nspname NOT IN ('pg_catalog')");
    1171             : 
    1172           0 :         ntups = PQntuples(res);
    1173           0 :         i_nspname = PQfnumber(res, "nspname");
    1174           0 :         i_relname = PQfnumber(res, "relname");
    1175           0 :         for (rowno = 0; rowno < ntups; rowno++)
    1176             :         {
    1177           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
    1178           0 :                 pg_fatal("could not open file \"%s\": %s",
    1179           0 :                          output_path, strerror(errno));
    1180           0 :             if (!db_used)
    1181             :             {
    1182           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
    1183           0 :                 db_used = true;
    1184             :             }
    1185           0 :             fprintf(script, "  %s.%s\n",
    1186             :                     PQgetvalue(res, rowno, i_nspname),
    1187             :                     PQgetvalue(res, rowno, i_relname));
    1188             :         }
    1189             : 
    1190           0 :         PQclear(res);
    1191             : 
    1192           0 :         PQfinish(conn);
    1193             :     }
    1194             : 
    1195           0 :     if (script)
    1196             :     {
    1197           0 :         fclose(script);
    1198           0 :         pg_log(PG_REPORT, "fatal");
    1199           0 :         pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
    1200             :                  "supported anymore.  Consider removing the oid column using\n"
    1201             :                  "    ALTER TABLE ... SET WITHOUT OIDS;\n"
    1202             :                  "A list of tables with the problem is in the file:\n"
    1203             :                  "    %s", output_path);
    1204             :     }
    1205             :     else
    1206           0 :         check_ok();
    1207           0 : }
    1208             : 
    1209             : 
    1210             : /*
    1211             :  * check_for_composite_data_type_usage()
    1212             :  *  Check for system-defined composite types used in user tables.
    1213             :  *
    1214             :  *  The OIDs of rowtypes of system catalogs and information_schema views
    1215             :  *  can change across major versions; unlike user-defined types, we have
    1216             :  *  no mechanism for forcing them to be the same in the new cluster.
    1217             :  *  Hence, if any user table uses one, that's problematic for pg_upgrade.
    1218             :  */
    1219             : static void
    1220           4 : check_for_composite_data_type_usage(ClusterInfo *cluster)
    1221             : {
    1222             :     bool        found;
    1223             :     Oid         firstUserOid;
    1224             :     char        output_path[MAXPGPATH];
    1225             :     char       *base_query;
    1226             : 
    1227           4 :     prep_status("Checking for system-defined composite types in user tables");
    1228             : 
    1229           4 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1230             :              log_opts.basedir,
    1231             :              "tables_using_composite.txt");
    1232             : 
    1233             :     /*
    1234             :      * Look for composite types that were made during initdb *or* belong to
    1235             :      * information_schema; that's important in case information_schema was
    1236             :      * dropped and reloaded.
    1237             :      *
    1238             :      * The cutoff OID here should match the source cluster's value of
    1239             :      * FirstNormalObjectId.  We hardcode it rather than using that C #define
    1240             :      * because, if that #define is ever changed, our own version's value is
    1241             :      * NOT what to use.  Eventually we may need a test on the source cluster's
    1242             :      * version to select the correct value.
    1243             :      */
    1244           4 :     firstUserOid = 16384;
    1245             : 
    1246           4 :     base_query = psprintf("SELECT t.oid FROM pg_catalog.pg_type t "
    1247             :                           "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
    1248             :                           " WHERE typtype = 'c' AND (t.oid < %u OR nspname = 'information_schema')",
    1249             :                           firstUserOid);
    1250             : 
    1251           4 :     found = check_for_data_types_usage(cluster, base_query, output_path);
    1252             : 
    1253           4 :     free(base_query);
    1254             : 
    1255           4 :     if (found)
    1256             :     {
    1257           0 :         pg_log(PG_REPORT, "fatal");
    1258           0 :         pg_fatal("Your installation contains system-defined composite type(s) in user tables.\n"
    1259             :                  "These type OIDs are not stable across PostgreSQL versions,\n"
    1260             :                  "so this cluster cannot currently be upgraded.  You can\n"
    1261             :                  "drop the problem columns and restart the upgrade.\n"
    1262             :                  "A list of the problem columns is in the file:\n"
    1263             :                  "    %s", output_path);
    1264             :     }
    1265             :     else
    1266           4 :         check_ok();
    1267           4 : }
    1268             : 
    1269             : /*
    1270             :  * check_for_reg_data_type_usage()
    1271             :  *  pg_upgrade only preserves these system values:
    1272             :  *      pg_class.oid
    1273             :  *      pg_type.oid
    1274             :  *      pg_enum.oid
    1275             :  *
    1276             :  *  Many of the reg* data types reference system catalog info that is
    1277             :  *  not preserved, and hence these data types cannot be used in user
    1278             :  *  tables upgraded by pg_upgrade.
    1279             :  */
    1280             : static void
    1281           4 : check_for_reg_data_type_usage(ClusterInfo *cluster)
    1282             : {
    1283             :     bool        found;
    1284             :     char        output_path[MAXPGPATH];
    1285             : 
    1286           4 :     prep_status("Checking for reg* data types in user tables");
    1287             : 
    1288           4 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1289             :              log_opts.basedir,
    1290             :              "tables_using_reg.txt");
    1291             : 
    1292             :     /*
    1293             :      * Note: older servers will not have all of these reg* types, so we have
    1294             :      * to write the query like this rather than depending on casts to regtype.
    1295             :      */
    1296           4 :     found = check_for_data_types_usage(cluster,
    1297             :                                        "SELECT oid FROM pg_catalog.pg_type t "
    1298             :                                        "WHERE t.typnamespace = "
    1299             :                                        "        (SELECT oid FROM pg_catalog.pg_namespace "
    1300             :                                        "         WHERE nspname = 'pg_catalog') "
    1301             :                                        "  AND t.typname IN ( "
    1302             :     /* pg_class.oid is preserved, so 'regclass' is OK */
    1303             :                                        "           'regcollation', "
    1304             :                                        "           'regconfig', "
    1305             :                                        "           'regdictionary', "
    1306             :                                        "           'regnamespace', "
    1307             :                                        "           'regoper', "
    1308             :                                        "           'regoperator', "
    1309             :                                        "           'regproc', "
    1310             :                                        "           'regprocedure' "
    1311             :     /* pg_authid.oid is preserved, so 'regrole' is OK */
    1312             :     /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
    1313             :                                        "         )",
    1314             :                                        output_path);
    1315             : 
    1316           4 :     if (found)
    1317             :     {
    1318           0 :         pg_log(PG_REPORT, "fatal");
    1319           0 :         pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
    1320             :                  "These data types reference system OIDs that are not preserved by\n"
    1321             :                  "pg_upgrade, so this cluster cannot currently be upgraded.  You can\n"
    1322             :                  "drop the problem columns and restart the upgrade.\n"
    1323             :                  "A list of the problem columns is in the file:\n"
    1324             :                  "    %s", output_path);
    1325             :     }
    1326             :     else
    1327           4 :         check_ok();
    1328           4 : }
    1329             : 
    1330             : /*
    1331             :  * check_for_aclitem_data_type_usage
    1332             :  *
    1333             :  *  aclitem changed its storage format in 16, so check for it.
    1334             :  */
    1335             : static void
    1336           0 : check_for_aclitem_data_type_usage(ClusterInfo *cluster)
    1337             : {
    1338             :     char        output_path[MAXPGPATH];
    1339             : 
    1340           0 :     prep_status("Checking for incompatible aclitem data type in user tables");
    1341             : 
    1342           0 :     snprintf(output_path, sizeof(output_path), "tables_using_aclitem.txt");
    1343             : 
    1344           0 :     if (check_for_data_type_usage(cluster, "pg_catalog.aclitem", output_path))
    1345             :     {
    1346           0 :         pg_log(PG_REPORT, "fatal");
    1347           0 :         pg_fatal("Your installation contains the \"aclitem\" data type in user tables.\n"
    1348             :                  "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
    1349             :                  "so this cluster cannot currently be upgraded.  You can drop the\n"
    1350             :                  "problem columns and restart the upgrade.  A list of the problem\n"
    1351             :                  "columns is in the file:\n"
    1352             :                  "    %s", output_path);
    1353             :     }
    1354             :     else
    1355           0 :         check_ok();
    1356           0 : }
    1357             : 
    1358             : /*
    1359             :  * check_for_jsonb_9_4_usage()
    1360             :  *
    1361             :  *  JSONB changed its storage format during 9.4 beta, so check for it.
    1362             :  */
    1363             : static void
    1364           0 : check_for_jsonb_9_4_usage(ClusterInfo *cluster)
    1365             : {
    1366             :     char        output_path[MAXPGPATH];
    1367             : 
    1368           0 :     prep_status("Checking for incompatible \"jsonb\" data type");
    1369             : 
    1370           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1371             :              log_opts.basedir,
    1372             :              "tables_using_jsonb.txt");
    1373             : 
    1374           0 :     if (check_for_data_type_usage(cluster, "pg_catalog.jsonb", output_path))
    1375             :     {
    1376           0 :         pg_log(PG_REPORT, "fatal");
    1377           0 :         pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
    1378             :                  "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
    1379             :                  "cluster cannot currently be upgraded.  You can\n"
    1380             :                  "drop the problem columns and restart the upgrade.\n"
    1381             :                  "A list of the problem columns is in the file:\n"
    1382             :                  "    %s", output_path);
    1383             :     }
    1384             :     else
    1385           0 :         check_ok();
    1386           0 : }
    1387             : 
    1388             : /*
    1389             :  * check_for_pg_role_prefix()
    1390             :  *
    1391             :  *  Versions older than 9.6 should not have any pg_* roles
    1392             :  */
    1393             : static void
    1394           0 : check_for_pg_role_prefix(ClusterInfo *cluster)
    1395             : {
    1396             :     PGresult   *res;
    1397           0 :     PGconn     *conn = connectToServer(cluster, "template1");
    1398             :     int         ntups;
    1399             :     int         i_roloid;
    1400             :     int         i_rolname;
    1401           0 :     FILE       *script = NULL;
    1402             :     char        output_path[MAXPGPATH];
    1403             : 
    1404           0 :     prep_status("Checking for roles starting with \"pg_\"");
    1405             : 
    1406           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1407             :              log_opts.basedir,
    1408             :              "pg_role_prefix.txt");
    1409             : 
    1410           0 :     res = executeQueryOrDie(conn,
    1411             :                             "SELECT oid AS roloid, rolname "
    1412             :                             "FROM pg_catalog.pg_roles "
    1413             :                             "WHERE rolname ~ '^pg_'");
    1414             : 
    1415           0 :     ntups = PQntuples(res);
    1416           0 :     i_roloid = PQfnumber(res, "roloid");
    1417           0 :     i_rolname = PQfnumber(res, "rolname");
    1418           0 :     for (int rowno = 0; rowno < ntups; rowno++)
    1419             :     {
    1420           0 :         if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
    1421           0 :             pg_fatal("could not open file \"%s\": %s",
    1422           0 :                      output_path, strerror(errno));
    1423           0 :         fprintf(script, "%s (oid=%s)\n",
    1424             :                 PQgetvalue(res, rowno, i_rolname),
    1425             :                 PQgetvalue(res, rowno, i_roloid));
    1426             :     }
    1427             : 
    1428           0 :     PQclear(res);
    1429             : 
    1430           0 :     PQfinish(conn);
    1431             : 
    1432           0 :     if (script)
    1433             :     {
    1434           0 :         fclose(script);
    1435           0 :         pg_log(PG_REPORT, "fatal");
    1436           0 :         pg_fatal("Your installation contains roles starting with \"pg_\".\n"
    1437             :                  "\"pg_\" is a reserved prefix for system roles, the cluster\n"
    1438             :                  "cannot be upgraded until these roles are renamed.\n"
    1439             :                  "A list of roles starting with \"pg_\" is in the file:\n"
    1440             :                  "    %s", output_path);
    1441             :     }
    1442             :     else
    1443           0 :         check_ok();
    1444           0 : }
    1445             : 
    1446             : /*
    1447             :  * Verify that no user-defined encoding conversions exist.
    1448             :  */
    1449             : static void
    1450           0 : check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
    1451             : {
    1452             :     int         dbnum;
    1453           0 :     FILE       *script = NULL;
    1454             :     char        output_path[MAXPGPATH];
    1455             : 
    1456           0 :     prep_status("Checking for user-defined encoding conversions");
    1457             : 
    1458           0 :     snprintf(output_path, sizeof(output_path), "%s/%s",
    1459             :              log_opts.basedir,
    1460             :              "encoding_conversions.txt");
    1461             : 
    1462             :     /* Find any user defined encoding conversions */
    1463           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    1464             :     {
    1465             :         PGresult   *res;
    1466           0 :         bool        db_used = false;
    1467             :         int         ntups;
    1468             :         int         rowno;
    1469             :         int         i_conoid,
    1470             :                     i_conname,
    1471             :                     i_nspname;
    1472           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
    1473           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
    1474             : 
    1475             :         /*
    1476             :          * The query below hardcodes FirstNormalObjectId as 16384 rather than
    1477             :          * interpolating that C #define into the query because, if that
    1478             :          * #define is ever changed, the cutoff we want to use is the value
    1479             :          * used by pre-version 14 servers, not that of some future version.
    1480             :          */
    1481           0 :         res = executeQueryOrDie(conn,
    1482             :                                 "SELECT c.oid as conoid, c.conname, n.nspname "
    1483             :                                 "FROM pg_catalog.pg_conversion c, "
    1484             :                                 "     pg_catalog.pg_namespace n "
    1485             :                                 "WHERE c.connamespace = n.oid AND "
    1486             :                                 "      c.oid >= 16384");
    1487           0 :         ntups = PQntuples(res);
    1488           0 :         i_conoid = PQfnumber(res, "conoid");
    1489           0 :         i_conname = PQfnumber(res, "conname");
    1490           0 :         i_nspname = PQfnumber(res, "nspname");
    1491           0 :         for (rowno = 0; rowno < ntups; rowno++)
    1492             :         {
    1493           0 :             if (script == NULL &&
    1494           0 :                 (script = fopen_priv(output_path, "w")) == NULL)
    1495           0 :                 pg_fatal("could not open file \"%s\": %s",
    1496           0 :                          output_path, strerror(errno));
    1497           0 :             if (!db_used)
    1498             :             {
    1499           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
    1500           0 :                 db_used = true;
    1501             :             }
    1502           0 :             fprintf(script, "  (oid=%s) %s.%s\n",
    1503             :                     PQgetvalue(res, rowno, i_conoid),
    1504             :                     PQgetvalue(res, rowno, i_nspname),
    1505             :                     PQgetvalue(res, rowno, i_conname));
    1506             :         }
    1507             : 
    1508           0 :         PQclear(res);
    1509             : 
    1510           0 :         PQfinish(conn);
    1511             :     }
    1512             : 
    1513           0 :     if (script)
    1514             :     {
    1515           0 :         fclose(script);
    1516           0 :         pg_log(PG_REPORT, "fatal");
    1517           0 :         pg_fatal("Your installation contains user-defined encoding conversions.\n"
    1518             :                  "The conversion function parameters changed in PostgreSQL version 14\n"
    1519             :                  "so this cluster cannot currently be upgraded.  You can remove the\n"
    1520             :                  "encoding conversions in the old cluster and restart the upgrade.\n"
    1521             :                  "A list of user-defined encoding conversions is in the file:\n"
    1522             :                  "    %s", output_path);
    1523             :     }
    1524             :     else
    1525           0 :         check_ok();
    1526           0 : }
    1527             : 
    1528             : 
    1529             : /*
    1530             :  * get_canonical_locale_name
    1531             :  *
    1532             :  * Send the locale name to the system, and hope we get back a canonical
    1533             :  * version.  This should match the backend's check_locale() function.
    1534             :  */
    1535             : static char *
    1536           0 : get_canonical_locale_name(int category, const char *locale)
    1537             : {
    1538             :     char       *save;
    1539             :     char       *res;
    1540             : 
    1541             :     /* get the current setting, so we can restore it. */
    1542           0 :     save = setlocale(category, NULL);
    1543           0 :     if (!save)
    1544           0 :         pg_fatal("failed to get the current locale");
    1545             : 
    1546             :     /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
    1547           0 :     save = pg_strdup(save);
    1548             : 
    1549             :     /* set the locale with setlocale, to see if it accepts it. */
    1550           0 :     res = setlocale(category, locale);
    1551             : 
    1552           0 :     if (!res)
    1553           0 :         pg_fatal("failed to get system locale name for \"%s\"", locale);
    1554             : 
    1555           0 :     res = pg_strdup(res);
    1556             : 
    1557             :     /* restore old value. */
    1558           0 :     if (!setlocale(category, save))
    1559           0 :         pg_fatal("failed to restore old locale \"%s\"", save);
    1560             : 
    1561           0 :     pg_free(save);
    1562             : 
    1563           0 :     return res;
    1564             : }

Generated by: LCOV version 1.14