LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - check.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 214 435 49.2 %
Date: 2019-11-21 13:06:38 Functions: 20 24 83.3 %
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-2019, 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 "fe_utils/string_utils.h"
      14             : #include "mb/pg_wchar.h"
      15             : #include "pg_upgrade.h"
      16             : 
      17             : static void check_new_cluster_is_empty(void);
      18             : static void check_databases_are_compatible(void);
      19             : static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb);
      20             : static bool equivalent_locale(int category, const char *loca, const char *locb);
      21             : static void check_is_install_user(ClusterInfo *cluster);
      22             : static void check_proper_datallowconn(ClusterInfo *cluster);
      23             : static void check_for_prepared_transactions(ClusterInfo *cluster);
      24             : static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
      25             : static void check_for_tables_with_oids(ClusterInfo *cluster);
      26             : static void check_for_reg_data_type_usage(ClusterInfo *cluster);
      27             : static void check_for_jsonb_9_4_usage(ClusterInfo *cluster);
      28             : static void check_for_pg_role_prefix(ClusterInfo *cluster);
      29             : static char *get_canonical_locale_name(int category, const char *locale);
      30             : 
      31             : 
      32             : /*
      33             :  * fix_path_separator
      34             :  * For non-Windows, just return the argument.
      35             :  * For Windows convert any forward slash to a backslash
      36             :  * such as is suitable for arguments to builtin commands
      37             :  * like RMDIR and DEL.
      38             :  */
      39             : static char *
      40           2 : fix_path_separator(char *path)
      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           2 :     return path;
      57             : #endif
      58             : }
      59             : 
      60             : void
      61           2 : output_check_banner(bool live_check)
      62             : {
      63           2 :     if (user_opts.check && live_check)
      64             :     {
      65           0 :         pg_log(PG_REPORT,
      66             :                "Performing Consistency Checks on Old Live Server\n"
      67             :                "------------------------------------------------\n");
      68             :     }
      69             :     else
      70             :     {
      71           2 :         pg_log(PG_REPORT,
      72             :                "Performing Consistency Checks\n"
      73             :                "-----------------------------\n");
      74             :     }
      75           2 : }
      76             : 
      77             : 
      78             : void
      79           2 : check_and_dump_old_cluster(bool live_check)
      80             : {
      81             :     /* -- OLD -- */
      82             : 
      83           2 :     if (!live_check)
      84           2 :         start_postmaster(&old_cluster, true);
      85             : 
      86             :     /* Extract a list of databases and tables from the old cluster */
      87           2 :     get_db_and_rel_infos(&old_cluster);
      88             : 
      89           2 :     init_tablespaces();
      90             : 
      91           2 :     get_loadable_libraries();
      92             : 
      93             : 
      94             :     /*
      95             :      * Check for various failure cases
      96             :      */
      97           2 :     check_is_install_user(&old_cluster);
      98           2 :     check_proper_datallowconn(&old_cluster);
      99           2 :     check_for_prepared_transactions(&old_cluster);
     100           2 :     check_for_reg_data_type_usage(&old_cluster);
     101           2 :     check_for_isn_and_int8_passing_mismatch(&old_cluster);
     102             : 
     103             :     /*
     104             :      * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
     105             :      * supported anymore. Verify there are none, iff applicable.
     106             :      */
     107           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
     108           0 :         check_for_tables_with_oids(&old_cluster);
     109             : 
     110             :     /*
     111             :      * PG 12 changed the 'sql_identifier' type storage to be based on name,
     112             :      * not varchar, which breaks on-disk format for existing data. So we need
     113             :      * to prevent upgrade when used in user objects (tables, indexes, ...).
     114             :      */
     115           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
     116           0 :         old_11_check_for_sql_identifier_data_type_usage(&old_cluster);
     117             : 
     118             :     /*
     119             :      * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
     120             :      * hash indexes
     121             :      */
     122           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
     123             :     {
     124           0 :         old_9_6_check_for_unknown_data_type_usage(&old_cluster);
     125           0 :         if (user_opts.check)
     126           0 :             old_9_6_invalidate_hash_indexes(&old_cluster, true);
     127             :     }
     128             : 
     129             :     /* 9.5 and below should not have roles starting with pg_ */
     130           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905)
     131           0 :         check_for_pg_role_prefix(&old_cluster);
     132             : 
     133           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 &&
     134           0 :         old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
     135           0 :         check_for_jsonb_9_4_usage(&old_cluster);
     136             : 
     137             :     /* Pre-PG 9.4 had a different 'line' data type internal format */
     138           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
     139           0 :         old_9_3_check_for_line_data_type_usage(&old_cluster);
     140             : 
     141             :     /* Pre-PG 9.0 had no large object permissions */
     142           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
     143           0 :         new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);
     144             : 
     145             :     /*
     146             :      * While not a check option, we do this now because this is the only time
     147             :      * the old server is running.
     148             :      */
     149           2 :     if (!user_opts.check)
     150           2 :         generate_old_dump();
     151             : 
     152           2 :     if (!live_check)
     153           2 :         stop_postmaster(false);
     154           2 : }
     155             : 
     156             : 
     157             : void
     158           2 : check_new_cluster(void)
     159             : {
     160           2 :     get_db_and_rel_infos(&new_cluster);
     161             : 
     162           2 :     check_new_cluster_is_empty();
     163           2 :     check_databases_are_compatible();
     164             : 
     165           2 :     check_loadable_libraries();
     166             : 
     167           2 :     switch (user_opts.transfer_mode)
     168             :     {
     169             :         case TRANSFER_MODE_CLONE:
     170           0 :             check_file_clone();
     171           0 :             break;
     172             :         case TRANSFER_MODE_COPY:
     173           2 :             break;
     174             :         case TRANSFER_MODE_LINK:
     175           0 :             check_hard_link();
     176           0 :             break;
     177             :     }
     178             : 
     179           2 :     check_is_install_user(&new_cluster);
     180             : 
     181           2 :     check_for_prepared_transactions(&new_cluster);
     182           2 : }
     183             : 
     184             : 
     185             : void
     186           2 : report_clusters_compatible(void)
     187             : {
     188           2 :     if (user_opts.check)
     189             :     {
     190           0 :         pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
     191             :         /* stops new cluster */
     192           0 :         stop_postmaster(false);
     193           0 :         exit(0);
     194             :     }
     195             : 
     196           2 :     pg_log(PG_REPORT, "\n"
     197             :            "If pg_upgrade fails after this point, you must re-initdb the\n"
     198             :            "new cluster before continuing.\n");
     199           2 : }
     200             : 
     201             : 
     202             : void
     203           2 : issue_warnings_and_set_wal_level(void)
     204             : {
     205             :     /*
     206             :      * We unconditionally start/stop the new server because pg_resetwal -o set
     207             :      * wal_level to 'minimum'.  If the user is upgrading standby servers using
     208             :      * the rsync instructions, they will need pg_upgrade to write its final
     209             :      * WAL record showing wal_level as 'replica'.
     210             :      */
     211           2 :     start_postmaster(&new_cluster, true);
     212             : 
     213             :     /* Create dummy large object permissions for old < PG 9.0? */
     214           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
     215           0 :         new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
     216             : 
     217             :     /* Reindex hash indexes for old < 10.0 */
     218           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
     219           0 :         old_9_6_invalidate_hash_indexes(&new_cluster, false);
     220             : 
     221           2 :     stop_postmaster(false);
     222           2 : }
     223             : 
     224             : 
     225             : void
     226           2 : output_completion_banner(char *analyze_script_file_name,
     227             :                          char *deletion_script_file_name)
     228             : {
     229             :     /* Did we copy the free space files? */
     230           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
     231           2 :         pg_log(PG_REPORT,
     232             :                "Optimizer statistics are not transferred by pg_upgrade so,\n"
     233             :                "once you start the new server, consider running:\n"
     234             :                "    %s\n\n", analyze_script_file_name);
     235             :     else
     236           0 :         pg_log(PG_REPORT,
     237             :                "Optimizer statistics and free space information are not transferred\n"
     238             :                "by pg_upgrade so, once you start the new server, consider running:\n"
     239             :                "    %s\n\n", analyze_script_file_name);
     240             : 
     241             : 
     242           2 :     if (deletion_script_file_name)
     243           2 :         pg_log(PG_REPORT,
     244             :                "Running this script will delete the old cluster's data files:\n"
     245             :                "    %s\n",
     246             :                deletion_script_file_name);
     247             :     else
     248           0 :         pg_log(PG_REPORT,
     249             :                "Could not create a script to delete the old cluster's data files\n"
     250             :                "because user-defined tablespaces or the new cluster's data directory\n"
     251             :                "exist in the old cluster directory.  The old cluster's contents must\n"
     252             :                "be deleted manually.\n");
     253           2 : }
     254             : 
     255             : 
     256             : void
     257           2 : check_cluster_versions(void)
     258             : {
     259           2 :     prep_status("Checking cluster versions");
     260             : 
     261             :     /* cluster versions should already have been obtained */
     262             :     Assert(old_cluster.major_version != 0);
     263             :     Assert(new_cluster.major_version != 0);
     264             : 
     265             :     /*
     266             :      * We allow upgrades from/to the same major version for alpha/beta
     267             :      * upgrades
     268             :      */
     269             : 
     270           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
     271           0 :         pg_fatal("This utility can only upgrade from PostgreSQL version 8.4 and later.\n");
     272             : 
     273             :     /* Only current PG version is supported as a target */
     274           2 :     if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
     275           0 :         pg_fatal("This utility can only upgrade to PostgreSQL version %s.\n",
     276             :                  PG_MAJORVERSION);
     277             : 
     278             :     /*
     279             :      * We can't allow downgrading because we use the target pg_dump, and
     280             :      * pg_dump cannot operate on newer database versions, only current and
     281             :      * older versions.
     282             :      */
     283           2 :     if (old_cluster.major_version > new_cluster.major_version)
     284           0 :         pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
     285             : 
     286             :     /* Ensure binaries match the designated data directories */
     287           4 :     if (GET_MAJOR_VERSION(old_cluster.major_version) !=
     288           2 :         GET_MAJOR_VERSION(old_cluster.bin_version))
     289           0 :         pg_fatal("Old cluster data and binary directories are from different major versions.\n");
     290           4 :     if (GET_MAJOR_VERSION(new_cluster.major_version) !=
     291           2 :         GET_MAJOR_VERSION(new_cluster.bin_version))
     292           0 :         pg_fatal("New cluster data and binary directories are from different major versions.\n");
     293             : 
     294           2 :     check_ok();
     295           2 : }
     296             : 
     297             : 
     298             : void
     299           2 : check_cluster_compatibility(bool live_check)
     300             : {
     301             :     /* get/check pg_control data of servers */
     302           2 :     get_control_data(&old_cluster, live_check);
     303           2 :     get_control_data(&new_cluster, false);
     304           2 :     check_control_data(&old_cluster.controldata, &new_cluster.controldata);
     305             : 
     306             :     /* We read the real port number for PG >= 9.1 */
     307           2 :     if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
     308           0 :         old_cluster.port == DEF_PGUPORT)
     309           0 :         pg_fatal("When checking a pre-PG 9.1 live old server, "
     310             :                  "you must specify the old server's port number.\n");
     311             : 
     312           2 :     if (live_check && old_cluster.port == new_cluster.port)
     313           0 :         pg_fatal("When checking a live server, "
     314             :                  "the old and new port numbers must be different.\n");
     315           2 : }
     316             : 
     317             : 
     318             : /*
     319             :  * check_locale_and_encoding()
     320             :  *
     321             :  * Check that locale and encoding of a database in the old and new clusters
     322             :  * are compatible.
     323             :  */
     324             : static void
     325           4 : check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb)
     326             : {
     327           4 :     if (olddb->db_encoding != newdb->db_encoding)
     328           0 :         pg_fatal("encodings for database \"%s\" do not match:  old \"%s\", new \"%s\"\n",
     329             :                  olddb->db_name,
     330             :                  pg_encoding_to_char(olddb->db_encoding),
     331             :                  pg_encoding_to_char(newdb->db_encoding));
     332           4 :     if (!equivalent_locale(LC_COLLATE, olddb->db_collate, newdb->db_collate))
     333           0 :         pg_fatal("lc_collate values for database \"%s\" do not match:  old \"%s\", new \"%s\"\n",
     334             :                  olddb->db_name, olddb->db_collate, newdb->db_collate);
     335           4 :     if (!equivalent_locale(LC_CTYPE, olddb->db_ctype, newdb->db_ctype))
     336           0 :         pg_fatal("lc_ctype values for database \"%s\" do not match:  old \"%s\", new \"%s\"\n",
     337             :                  olddb->db_name, olddb->db_ctype, newdb->db_ctype);
     338           4 : }
     339             : 
     340             : /*
     341             :  * equivalent_locale()
     342             :  *
     343             :  * Best effort locale-name comparison.  Return false if we are not 100% sure
     344             :  * the locales are equivalent.
     345             :  *
     346             :  * Note: The encoding parts of the names are ignored. This function is
     347             :  * currently used to compare locale names stored in pg_database, and
     348             :  * pg_database contains a separate encoding field. That's compared directly
     349             :  * in check_locale_and_encoding().
     350             :  */
     351             : static bool
     352           8 : equivalent_locale(int category, const char *loca, const char *locb)
     353             : {
     354             :     const char *chara;
     355             :     const char *charb;
     356             :     char       *canona;
     357             :     char       *canonb;
     358             :     int         lena;
     359             :     int         lenb;
     360             : 
     361             :     /*
     362             :      * If the names are equal, the locales are equivalent. Checking this first
     363             :      * avoids calling setlocale() in the common case that the names are equal.
     364             :      * That's a good thing, if setlocale() is buggy, for example.
     365             :      */
     366           8 :     if (pg_strcasecmp(loca, locb) == 0)
     367           8 :         return true;
     368             : 
     369             :     /*
     370             :      * Not identical. Canonicalize both names, remove the encoding parts, and
     371             :      * try again.
     372             :      */
     373           0 :     canona = get_canonical_locale_name(category, loca);
     374           0 :     chara = strrchr(canona, '.');
     375           0 :     lena = chara ? (chara - canona) : strlen(canona);
     376             : 
     377           0 :     canonb = get_canonical_locale_name(category, locb);
     378           0 :     charb = strrchr(canonb, '.');
     379           0 :     lenb = charb ? (charb - canonb) : strlen(canonb);
     380             : 
     381           0 :     if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0)
     382             :     {
     383           0 :         pg_free(canona);
     384           0 :         pg_free(canonb);
     385           0 :         return true;
     386             :     }
     387             : 
     388           0 :     pg_free(canona);
     389           0 :     pg_free(canonb);
     390           0 :     return false;
     391             : }
     392             : 
     393             : 
     394             : static void
     395           2 : check_new_cluster_is_empty(void)
     396             : {
     397             :     int         dbnum;
     398             : 
     399           6 :     for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
     400             :     {
     401             :         int         relnum;
     402           4 :         RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
     403             : 
     404          16 :         for (relnum = 0; relnum < rel_arr->nrels;
     405           8 :              relnum++)
     406             :         {
     407             :             /* pg_largeobject and its index should be skipped */
     408           8 :             if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
     409           0 :                 pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"\n",
     410           0 :                          new_cluster.dbarr.dbs[dbnum].db_name,
     411           0 :                          rel_arr->rels[relnum].nspname,
     412           0 :                          rel_arr->rels[relnum].relname);
     413             :         }
     414             :     }
     415           2 : }
     416             : 
     417             : /*
     418             :  * Check that every database that already exists in the new cluster is
     419             :  * compatible with the corresponding database in the old one.
     420             :  */
     421             : static void
     422           2 : check_databases_are_compatible(void)
     423             : {
     424             :     int         newdbnum;
     425             :     int         olddbnum;
     426             :     DbInfo     *newdbinfo;
     427             :     DbInfo     *olddbinfo;
     428             : 
     429           6 :     for (newdbnum = 0; newdbnum < new_cluster.dbarr.ndbs; newdbnum++)
     430             :     {
     431           4 :         newdbinfo = &new_cluster.dbarr.dbs[newdbnum];
     432             : 
     433             :         /* Find the corresponding database in the old cluster */
     434          14 :         for (olddbnum = 0; olddbnum < old_cluster.dbarr.ndbs; olddbnum++)
     435             :         {
     436          14 :             olddbinfo = &old_cluster.dbarr.dbs[olddbnum];
     437          14 :             if (strcmp(newdbinfo->db_name, olddbinfo->db_name) == 0)
     438             :             {
     439           4 :                 check_locale_and_encoding(olddbinfo, newdbinfo);
     440           4 :                 break;
     441             :             }
     442             :         }
     443             :     }
     444           2 : }
     445             : 
     446             : 
     447             : /*
     448             :  * create_script_for_cluster_analyze()
     449             :  *
     450             :  *  This incrementally generates better optimizer statistics
     451             :  */
     452             : void
     453           2 : create_script_for_cluster_analyze(char **analyze_script_file_name)
     454             : {
     455           2 :     FILE       *script = NULL;
     456             :     PQExpBufferData user_specification;
     457             : 
     458           2 :     prep_status("Creating script to analyze new cluster");
     459             : 
     460           2 :     initPQExpBuffer(&user_specification);
     461           2 :     if (os_info.user_specified)
     462             :     {
     463           0 :         appendPQExpBufferStr(&user_specification, "-U ");
     464           0 :         appendShellString(&user_specification, os_info.user);
     465           0 :         appendPQExpBufferChar(&user_specification, ' ');
     466             :     }
     467             : 
     468           2 :     *analyze_script_file_name = psprintf("%sanalyze_new_cluster.%s",
     469             :                                          SCRIPT_PREFIX, SCRIPT_EXT);
     470             : 
     471           2 :     if ((script = fopen_priv(*analyze_script_file_name, "w")) == NULL)
     472           0 :         pg_fatal("could not open file \"%s\": %s\n",
     473           0 :                  *analyze_script_file_name, strerror(errno));
     474             : 
     475             : #ifndef WIN32
     476             :     /* add shebang header */
     477           2 :     fprintf(script, "#!/bin/sh\n\n");
     478             : #else
     479             :     /* suppress command echoing */
     480             :     fprintf(script, "@echo off\n");
     481             : #endif
     482             : 
     483           2 :     fprintf(script, "echo %sThis script will generate minimal optimizer statistics rapidly%s\n",
     484             :             ECHO_QUOTE, ECHO_QUOTE);
     485           2 :     fprintf(script, "echo %sso your system is usable, and then gather statistics twice more%s\n",
     486             :             ECHO_QUOTE, ECHO_QUOTE);
     487           2 :     fprintf(script, "echo %swith increasing accuracy.  When it is done, your system will%s\n",
     488             :             ECHO_QUOTE, ECHO_QUOTE);
     489           2 :     fprintf(script, "echo %shave the default level of optimizer statistics.%s\n",
     490             :             ECHO_QUOTE, ECHO_QUOTE);
     491           2 :     fprintf(script, "echo%s\n\n", ECHO_BLANK);
     492             : 
     493           2 :     fprintf(script, "echo %sIf you have used ALTER TABLE to modify the statistics target for%s\n",
     494             :             ECHO_QUOTE, ECHO_QUOTE);
     495           2 :     fprintf(script, "echo %sany tables, you might want to remove them and restore them after%s\n",
     496             :             ECHO_QUOTE, ECHO_QUOTE);
     497           2 :     fprintf(script, "echo %srunning this script because they will delay fast statistics generation.%s\n",
     498             :             ECHO_QUOTE, ECHO_QUOTE);
     499           2 :     fprintf(script, "echo%s\n\n", ECHO_BLANK);
     500             : 
     501           2 :     fprintf(script, "echo %sIf you would like default statistics as quickly as possible, cancel%s\n",
     502             :             ECHO_QUOTE, ECHO_QUOTE);
     503           2 :     fprintf(script, "echo %sthis script and run:%s\n",
     504             :             ECHO_QUOTE, ECHO_QUOTE);
     505           2 :     fprintf(script, "echo %s    \"%s/vacuumdb\" %s--all %s%s\n", ECHO_QUOTE,
     506             :             new_cluster.bindir, user_specification.data,
     507             :     /* Did we copy the free space files? */
     508           2 :             (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
     509             :             "--analyze-only" : "--analyze", ECHO_QUOTE);
     510           2 :     fprintf(script, "echo%s\n\n", ECHO_BLANK);
     511             : 
     512           2 :     fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-in-stages\n",
     513             :             new_cluster.bindir, user_specification.data);
     514             :     /* Did we copy the free space files? */
     515           2 :     if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
     516           0 :         fprintf(script, "\"%s/vacuumdb\" %s--all\n", new_cluster.bindir,
     517             :                 user_specification.data);
     518             : 
     519           2 :     fprintf(script, "echo%s\n\n", ECHO_BLANK);
     520           2 :     fprintf(script, "echo %sDone%s\n",
     521             :             ECHO_QUOTE, ECHO_QUOTE);
     522             : 
     523           2 :     fclose(script);
     524             : 
     525             : #ifndef WIN32
     526           2 :     if (chmod(*analyze_script_file_name, S_IRWXU) != 0)
     527           0 :         pg_fatal("could not add execute permission to file \"%s\": %s\n",
     528           0 :                  *analyze_script_file_name, strerror(errno));
     529             : #endif
     530             : 
     531           2 :     termPQExpBuffer(&user_specification);
     532             : 
     533           2 :     check_ok();
     534           2 : }
     535             : 
     536             : 
     537             : /*
     538             :  * create_script_for_old_cluster_deletion()
     539             :  *
     540             :  *  This is particularly useful for tablespace deletion.
     541             :  */
     542             : void
     543           2 : create_script_for_old_cluster_deletion(char **deletion_script_file_name)
     544             : {
     545           2 :     FILE       *script = NULL;
     546             :     int         tblnum;
     547             :     char        old_cluster_pgdata[MAXPGPATH],
     548             :                 new_cluster_pgdata[MAXPGPATH];
     549             : 
     550           2 :     *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
     551             :                                           SCRIPT_PREFIX, SCRIPT_EXT);
     552             : 
     553           2 :     strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
     554           2 :     canonicalize_path(old_cluster_pgdata);
     555             : 
     556           2 :     strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
     557           2 :     canonicalize_path(new_cluster_pgdata);
     558             : 
     559             :     /* Some people put the new data directory inside the old one. */
     560           2 :     if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
     561             :     {
     562           0 :         pg_log(PG_WARNING,
     563             :                "\nWARNING:  new data directory should not be inside the old data directory, e.g. %s\n", old_cluster_pgdata);
     564             : 
     565             :         /* Unlink file in case it is left over from a previous run. */
     566           0 :         unlink(*deletion_script_file_name);
     567           0 :         pg_free(*deletion_script_file_name);
     568           0 :         *deletion_script_file_name = NULL;
     569           0 :         return;
     570             :     }
     571             : 
     572             :     /*
     573             :      * Some users (oddly) create tablespaces inside the cluster data
     574             :      * directory.  We can't create a proper old cluster delete script in that
     575             :      * case.
     576             :      */
     577           2 :     for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
     578             :     {
     579             :         char        old_tablespace_dir[MAXPGPATH];
     580             : 
     581           0 :         strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
     582           0 :         canonicalize_path(old_tablespace_dir);
     583           0 :         if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
     584             :         {
     585             :             /* reproduce warning from CREATE TABLESPACE that is in the log */
     586           0 :             pg_log(PG_WARNING,
     587             :                    "\nWARNING:  user-defined tablespace locations should not be inside the data directory, e.g. %s\n", old_tablespace_dir);
     588             : 
     589             :             /* Unlink file in case it is left over from a previous run. */
     590           0 :             unlink(*deletion_script_file_name);
     591           0 :             pg_free(*deletion_script_file_name);
     592           0 :             *deletion_script_file_name = NULL;
     593           0 :             return;
     594             :         }
     595             :     }
     596             : 
     597           2 :     prep_status("Creating script to delete old cluster");
     598             : 
     599           2 :     if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
     600           0 :         pg_fatal("could not open file \"%s\": %s\n",
     601           0 :                  *deletion_script_file_name, strerror(errno));
     602             : 
     603             : #ifndef WIN32
     604             :     /* add shebang header */
     605           2 :     fprintf(script, "#!/bin/sh\n\n");
     606             : #endif
     607             : 
     608             :     /* delete old cluster's default tablespace */
     609           2 :     fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
     610             :             fix_path_separator(old_cluster.pgdata), PATH_QUOTE);
     611             : 
     612             :     /* delete old cluster's alternate tablespaces */
     613           2 :     for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
     614             :     {
     615             :         /*
     616             :          * Do the old cluster's per-database directories share a directory
     617             :          * with a new version-specific tablespace?
     618             :          */
     619           0 :         if (strlen(old_cluster.tablespace_suffix) == 0)
     620             :         {
     621             :             /* delete per-database directories */
     622             :             int         dbnum;
     623             : 
     624           0 :             fprintf(script, "\n");
     625             :             /* remove PG_VERSION? */
     626           0 :             if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
     627           0 :                 fprintf(script, RM_CMD " %s%cPG_VERSION\n",
     628           0 :                         fix_path_separator(os_info.old_tablespaces[tblnum]),
     629             :                         PATH_SEPARATOR);
     630             : 
     631           0 :             for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
     632           0 :                 fprintf(script, RMDIR_CMD " %c%s%c%d%c\n", PATH_QUOTE,
     633           0 :                         fix_path_separator(os_info.old_tablespaces[tblnum]),
     634           0 :                         PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid,
     635             :                         PATH_QUOTE);
     636             :         }
     637             :         else
     638             :         {
     639           0 :             char       *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
     640             : 
     641             :             /*
     642             :              * Simply delete the tablespace directory, which might be ".old"
     643             :              * or a version-specific subdirectory.
     644             :              */
     645           0 :             fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
     646           0 :                     fix_path_separator(os_info.old_tablespaces[tblnum]),
     647             :                     fix_path_separator(suffix_path), PATH_QUOTE);
     648           0 :             pfree(suffix_path);
     649             :         }
     650             :     }
     651             : 
     652           2 :     fclose(script);
     653             : 
     654             : #ifndef WIN32
     655           2 :     if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
     656           0 :         pg_fatal("could not add execute permission to file \"%s\": %s\n",
     657           0 :                  *deletion_script_file_name, strerror(errno));
     658             : #endif
     659             : 
     660           2 :     check_ok();
     661             : }
     662             : 
     663             : 
     664             : /*
     665             :  *  check_is_install_user()
     666             :  *
     667             :  *  Check we are the install user, and that the new cluster
     668             :  *  has no other users.
     669             :  */
     670             : static void
     671           4 : check_is_install_user(ClusterInfo *cluster)
     672             : {
     673             :     PGresult   *res;
     674           4 :     PGconn     *conn = connectToServer(cluster, "template1");
     675             : 
     676           4 :     prep_status("Checking database user is the install user");
     677             : 
     678             :     /* Can't use pg_authid because only superusers can view it. */
     679           4 :     res = executeQueryOrDie(conn,
     680             :                             "SELECT rolsuper, oid "
     681             :                             "FROM pg_catalog.pg_roles "
     682             :                             "WHERE rolname = current_user "
     683             :                             "AND rolname !~ '^pg_'");
     684             : 
     685             :     /*
     686             :      * We only allow the install user in the new cluster (see comment below)
     687             :      * and we preserve pg_authid.oid, so this must be the install user in the
     688             :      * old cluster too.
     689             :      */
     690           8 :     if (PQntuples(res) != 1 ||
     691           4 :         atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
     692           0 :         pg_fatal("database user \"%s\" is not the install user\n",
     693             :                  os_info.user);
     694             : 
     695           4 :     PQclear(res);
     696             : 
     697           4 :     res = executeQueryOrDie(conn,
     698             :                             "SELECT COUNT(*) "
     699             :                             "FROM pg_catalog.pg_roles "
     700             :                             "WHERE rolname !~ '^pg_'");
     701             : 
     702           4 :     if (PQntuples(res) != 1)
     703           0 :         pg_fatal("could not determine the number of users\n");
     704             : 
     705             :     /*
     706             :      * We only allow the install user in the new cluster because other defined
     707             :      * users might match users defined in the old cluster and generate an
     708             :      * error during pg_dump restore.
     709             :      */
     710           4 :     if (cluster == &new_cluster && atooid(PQgetvalue(res, 0, 0)) != 1)
     711           0 :         pg_fatal("Only the install user can be defined in the new cluster.\n");
     712             : 
     713           4 :     PQclear(res);
     714             : 
     715           4 :     PQfinish(conn);
     716             : 
     717           4 :     check_ok();
     718           4 : }
     719             : 
     720             : 
     721             : static void
     722           2 : check_proper_datallowconn(ClusterInfo *cluster)
     723             : {
     724             :     int         dbnum;
     725             :     PGconn     *conn_template1;
     726             :     PGresult   *dbres;
     727             :     int         ntups;
     728             :     int         i_datname;
     729             :     int         i_datallowconn;
     730             : 
     731           2 :     prep_status("Checking database connection settings");
     732             : 
     733           2 :     conn_template1 = connectToServer(cluster, "template1");
     734             : 
     735             :     /* get database names */
     736           2 :     dbres = executeQueryOrDie(conn_template1,
     737             :                               "SELECT  datname, datallowconn "
     738             :                               "FROM    pg_catalog.pg_database");
     739             : 
     740           2 :     i_datname = PQfnumber(dbres, "datname");
     741           2 :     i_datallowconn = PQfnumber(dbres, "datallowconn");
     742             : 
     743           2 :     ntups = PQntuples(dbres);
     744          16 :     for (dbnum = 0; dbnum < ntups; dbnum++)
     745             :     {
     746          14 :         char       *datname = PQgetvalue(dbres, dbnum, i_datname);
     747          14 :         char       *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
     748             : 
     749          14 :         if (strcmp(datname, "template0") == 0)
     750             :         {
     751             :             /* avoid restore failure when pg_dumpall tries to create template0 */
     752           2 :             if (strcmp(datallowconn, "t") == 0)
     753           0 :                 pg_fatal("template0 must not allow connections, "
     754             :                          "i.e. its pg_database.datallowconn must be false\n");
     755             :         }
     756             :         else
     757             :         {
     758             :             /*
     759             :              * avoid datallowconn == false databases from being skipped on
     760             :              * restore
     761             :              */
     762          12 :             if (strcmp(datallowconn, "f") == 0)
     763           0 :                 pg_fatal("All non-template0 databases must allow connections, "
     764             :                          "i.e. their pg_database.datallowconn must be true\n");
     765             :         }
     766             :     }
     767             : 
     768           2 :     PQclear(dbres);
     769             : 
     770           2 :     PQfinish(conn_template1);
     771             : 
     772           2 :     check_ok();
     773           2 : }
     774             : 
     775             : 
     776             : /*
     777             :  *  check_for_prepared_transactions()
     778             :  *
     779             :  *  Make sure there are no prepared transactions because the storage format
     780             :  *  might have changed.
     781             :  */
     782             : static void
     783           4 : check_for_prepared_transactions(ClusterInfo *cluster)
     784             : {
     785             :     PGresult   *res;
     786           4 :     PGconn     *conn = connectToServer(cluster, "template1");
     787             : 
     788           4 :     prep_status("Checking for prepared transactions");
     789             : 
     790           4 :     res = executeQueryOrDie(conn,
     791             :                             "SELECT * "
     792             :                             "FROM pg_catalog.pg_prepared_xacts");
     793             : 
     794           4 :     if (PQntuples(res) != 0)
     795             :     {
     796           0 :         if (cluster == &old_cluster)
     797           0 :             pg_fatal("The source cluster contains prepared transactions\n");
     798             :         else
     799           0 :             pg_fatal("The target cluster contains prepared transactions\n");
     800             :     }
     801             : 
     802           4 :     PQclear(res);
     803             : 
     804           4 :     PQfinish(conn);
     805             : 
     806           4 :     check_ok();
     807           4 : }
     808             : 
     809             : 
     810             : /*
     811             :  *  check_for_isn_and_int8_passing_mismatch()
     812             :  *
     813             :  *  contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
     814             :  *  by value.  The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
     815             :  *  it must match for the old and new servers.
     816             :  */
     817             : static void
     818           2 : check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
     819             : {
     820             :     int         dbnum;
     821           2 :     FILE       *script = NULL;
     822           2 :     bool        found = false;
     823             :     char        output_path[MAXPGPATH];
     824             : 
     825           2 :     prep_status("Checking for contrib/isn with bigint-passing mismatch");
     826             : 
     827           4 :     if (old_cluster.controldata.float8_pass_by_value ==
     828           2 :         new_cluster.controldata.float8_pass_by_value)
     829             :     {
     830             :         /* no mismatch */
     831           2 :         check_ok();
     832           2 :         return;
     833             :     }
     834             : 
     835           0 :     snprintf(output_path, sizeof(output_path),
     836             :              "contrib_isn_and_int8_pass_by_value.txt");
     837             : 
     838           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
     839             :     {
     840             :         PGresult   *res;
     841           0 :         bool        db_used = false;
     842             :         int         ntups;
     843             :         int         rowno;
     844             :         int         i_nspname,
     845             :                     i_proname;
     846           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
     847           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
     848             : 
     849             :         /* Find any functions coming from contrib/isn */
     850           0 :         res = executeQueryOrDie(conn,
     851             :                                 "SELECT n.nspname, p.proname "
     852             :                                 "FROM  pg_catalog.pg_proc p, "
     853             :                                 "      pg_catalog.pg_namespace n "
     854             :                                 "WHERE p.pronamespace = n.oid AND "
     855             :                                 "      p.probin = '$libdir/isn'");
     856             : 
     857           0 :         ntups = PQntuples(res);
     858           0 :         i_nspname = PQfnumber(res, "nspname");
     859           0 :         i_proname = PQfnumber(res, "proname");
     860           0 :         for (rowno = 0; rowno < ntups; rowno++)
     861             :         {
     862           0 :             found = true;
     863           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
     864           0 :                 pg_fatal("could not open file \"%s\": %s\n",
     865           0 :                          output_path, strerror(errno));
     866           0 :             if (!db_used)
     867             :             {
     868           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
     869           0 :                 db_used = true;
     870             :             }
     871           0 :             fprintf(script, "  %s.%s\n",
     872             :                     PQgetvalue(res, rowno, i_nspname),
     873             :                     PQgetvalue(res, rowno, i_proname));
     874             :         }
     875             : 
     876           0 :         PQclear(res);
     877             : 
     878           0 :         PQfinish(conn);
     879             :     }
     880             : 
     881           0 :     if (script)
     882           0 :         fclose(script);
     883             : 
     884           0 :     if (found)
     885             :     {
     886           0 :         pg_log(PG_REPORT, "fatal\n");
     887           0 :         pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
     888             :                  "bigint data type.  Your old and new clusters pass bigint values\n"
     889             :                  "differently so this cluster cannot currently be upgraded.  You can\n"
     890             :                  "manually upgrade databases that use \"contrib/isn\" facilities and remove\n"
     891             :                  "\"contrib/isn\" from the old cluster and restart the upgrade.  A list of\n"
     892             :                  "the problem functions is in the file:\n"
     893             :                  "    %s\n\n", output_path);
     894             :     }
     895             :     else
     896           0 :         check_ok();
     897             : }
     898             : 
     899             : 
     900             : /*
     901             :  * Verify that no tables are declared WITH OIDS.
     902             :  */
     903             : static void
     904           0 : check_for_tables_with_oids(ClusterInfo *cluster)
     905             : {
     906             :     int         dbnum;
     907           0 :     FILE       *script = NULL;
     908           0 :     bool        found = false;
     909             :     char        output_path[MAXPGPATH];
     910             : 
     911           0 :     prep_status("Checking for tables WITH OIDS");
     912             : 
     913           0 :     snprintf(output_path, sizeof(output_path),
     914             :              "tables_with_oids.txt");
     915             : 
     916             :     /* Find any tables declared WITH OIDS */
     917           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
     918             :     {
     919             :         PGresult   *res;
     920           0 :         bool        db_used = false;
     921             :         int         ntups;
     922             :         int         rowno;
     923             :         int         i_nspname,
     924             :                     i_relname;
     925           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
     926           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
     927             : 
     928           0 :         res = executeQueryOrDie(conn,
     929             :                                 "SELECT n.nspname, c.relname "
     930             :                                 "FROM  pg_catalog.pg_class c, "
     931             :                                 "      pg_catalog.pg_namespace n "
     932             :                                 "WHERE c.relnamespace = n.oid AND "
     933             :                                 "      c.relhasoids AND"
     934             :                                 "       n.nspname NOT IN ('pg_catalog')");
     935             : 
     936           0 :         ntups = PQntuples(res);
     937           0 :         i_nspname = PQfnumber(res, "nspname");
     938           0 :         i_relname = PQfnumber(res, "relname");
     939           0 :         for (rowno = 0; rowno < ntups; rowno++)
     940             :         {
     941           0 :             found = true;
     942           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
     943           0 :                 pg_fatal("could not open file \"%s\": %s\n",
     944           0 :                          output_path, strerror(errno));
     945           0 :             if (!db_used)
     946             :             {
     947           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
     948           0 :                 db_used = true;
     949             :             }
     950           0 :             fprintf(script, "  %s.%s\n",
     951             :                     PQgetvalue(res, rowno, i_nspname),
     952             :                     PQgetvalue(res, rowno, i_relname));
     953             :         }
     954             : 
     955           0 :         PQclear(res);
     956             : 
     957           0 :         PQfinish(conn);
     958             :     }
     959             : 
     960           0 :     if (script)
     961           0 :         fclose(script);
     962             : 
     963           0 :     if (found)
     964             :     {
     965           0 :         pg_log(PG_REPORT, "fatal\n");
     966           0 :         pg_fatal("Your installation contains tables declared WITH OIDS, which is not supported\n"
     967             :                  "anymore. Consider removing the oid column using\n"
     968             :                  "    ALTER TABLE ... SET WITHOUT OIDS;\n"
     969             :                  "A list of tables with the problem is in the file:\n"
     970             :                  "    %s\n\n", output_path);
     971             :     }
     972             :     else
     973           0 :         check_ok();
     974           0 : }
     975             : 
     976             : 
     977             : /*
     978             :  * check_for_reg_data_type_usage()
     979             :  *  pg_upgrade only preserves these system values:
     980             :  *      pg_class.oid
     981             :  *      pg_type.oid
     982             :  *      pg_enum.oid
     983             :  *
     984             :  *  Many of the reg* data types reference system catalog info that is
     985             :  *  not preserved, and hence these data types cannot be used in user
     986             :  *  tables upgraded by pg_upgrade.
     987             :  */
     988             : static void
     989           2 : check_for_reg_data_type_usage(ClusterInfo *cluster)
     990             : {
     991             :     int         dbnum;
     992           2 :     FILE       *script = NULL;
     993           2 :     bool        found = false;
     994             :     char        output_path[MAXPGPATH];
     995             : 
     996           2 :     prep_status("Checking for reg* data types in user tables");
     997             : 
     998           2 :     snprintf(output_path, sizeof(output_path), "tables_using_reg.txt");
     999             : 
    1000          14 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    1001             :     {
    1002             :         PGresult   *res;
    1003          12 :         bool        db_used = false;
    1004             :         int         ntups;
    1005             :         int         rowno;
    1006             :         int         i_nspname,
    1007             :                     i_relname,
    1008             :                     i_attname;
    1009          12 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
    1010          12 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
    1011             : 
    1012             :         /*
    1013             :          * While several relkinds don't store any data, e.g. views, they can
    1014             :          * be used to define data types of other columns, so we check all
    1015             :          * relkinds.
    1016             :          */
    1017          12 :         res = executeQueryOrDie(conn,
    1018             :                                 "SELECT n.nspname, c.relname, a.attname "
    1019             :                                 "FROM  pg_catalog.pg_class c, "
    1020             :                                 "      pg_catalog.pg_namespace n, "
    1021             :                                 "      pg_catalog.pg_attribute a, "
    1022             :                                 "      pg_catalog.pg_type t "
    1023             :                                 "WHERE c.oid = a.attrelid AND "
    1024             :                                 "      NOT a.attisdropped AND "
    1025             :                                 "       a.atttypid = t.oid AND "
    1026             :                                 "       t.typnamespace = "
    1027             :                                 "           (SELECT oid FROM pg_namespace "
    1028             :                                 "            WHERE nspname = 'pg_catalog') AND"
    1029             :                                 "      t.typname IN ( "
    1030             :         /* regclass.oid is preserved, so 'regclass' is OK */
    1031             :                                 "           'regconfig', "
    1032             :                                 "           'regdictionary', "
    1033             :                                 "           'regnamespace', "
    1034             :                                 "           'regoper', "
    1035             :                                 "           'regoperator', "
    1036             :                                 "           'regproc', "
    1037             :                                 "           'regprocedure' "
    1038             :         /* regrole.oid is preserved, so 'regrole' is OK */
    1039             :         /* regtype.oid is preserved, so 'regtype' is OK */
    1040             :                                 "          ) AND "
    1041             :                                 "      c.relnamespace = n.oid AND "
    1042             :                                 "      n.nspname NOT IN ('pg_catalog', 'information_schema')");
    1043             : 
    1044          12 :         ntups = PQntuples(res);
    1045          12 :         i_nspname = PQfnumber(res, "nspname");
    1046          12 :         i_relname = PQfnumber(res, "relname");
    1047          12 :         i_attname = PQfnumber(res, "attname");
    1048          12 :         for (rowno = 0; rowno < ntups; rowno++)
    1049             :         {
    1050           0 :             found = true;
    1051           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
    1052           0 :                 pg_fatal("could not open file \"%s\": %s\n",
    1053           0 :                          output_path, strerror(errno));
    1054           0 :             if (!db_used)
    1055             :             {
    1056           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
    1057           0 :                 db_used = true;
    1058             :             }
    1059           0 :             fprintf(script, "  %s.%s.%s\n",
    1060             :                     PQgetvalue(res, rowno, i_nspname),
    1061             :                     PQgetvalue(res, rowno, i_relname),
    1062             :                     PQgetvalue(res, rowno, i_attname));
    1063             :         }
    1064             : 
    1065          12 :         PQclear(res);
    1066             : 
    1067          12 :         PQfinish(conn);
    1068             :     }
    1069             : 
    1070           2 :     if (script)
    1071           0 :         fclose(script);
    1072             : 
    1073           2 :     if (found)
    1074             :     {
    1075           0 :         pg_log(PG_REPORT, "fatal\n");
    1076           0 :         pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
    1077             :                  "These data types reference system OIDs that are not preserved by\n"
    1078             :                  "pg_upgrade, so this cluster cannot currently be upgraded.  You can\n"
    1079             :                  "remove the problem tables and restart the upgrade.  A list of the problem\n"
    1080             :                  "columns is in the file:\n"
    1081             :                  "    %s\n\n", output_path);
    1082             :     }
    1083             :     else
    1084           2 :         check_ok();
    1085           2 : }
    1086             : 
    1087             : 
    1088             : /*
    1089             :  * check_for_jsonb_9_4_usage()
    1090             :  *
    1091             :  *  JSONB changed its storage format during 9.4 beta, so check for it.
    1092             :  */
    1093             : static void
    1094           0 : check_for_jsonb_9_4_usage(ClusterInfo *cluster)
    1095             : {
    1096             :     int         dbnum;
    1097           0 :     FILE       *script = NULL;
    1098           0 :     bool        found = false;
    1099             :     char        output_path[MAXPGPATH];
    1100             : 
    1101           0 :     prep_status("Checking for incompatible \"jsonb\" data type");
    1102             : 
    1103           0 :     snprintf(output_path, sizeof(output_path), "tables_using_jsonb.txt");
    1104             : 
    1105           0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    1106             :     {
    1107             :         PGresult   *res;
    1108           0 :         bool        db_used = false;
    1109             :         int         ntups;
    1110             :         int         rowno;
    1111             :         int         i_nspname,
    1112             :                     i_relname,
    1113             :                     i_attname;
    1114           0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
    1115           0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
    1116             : 
    1117             :         /*
    1118             :          * While several relkinds don't store any data, e.g. views, they can
    1119             :          * be used to define data types of other columns, so we check all
    1120             :          * relkinds.
    1121             :          */
    1122           0 :         res = executeQueryOrDie(conn,
    1123             :                                 "SELECT n.nspname, c.relname, a.attname "
    1124             :                                 "FROM  pg_catalog.pg_class c, "
    1125             :                                 "      pg_catalog.pg_namespace n, "
    1126             :                                 "      pg_catalog.pg_attribute a "
    1127             :                                 "WHERE c.oid = a.attrelid AND "
    1128             :                                 "      NOT a.attisdropped AND "
    1129             :                                 "      a.atttypid = 'pg_catalog.jsonb'::pg_catalog.regtype AND "
    1130             :                                 "      c.relnamespace = n.oid AND "
    1131             :         /* exclude possible orphaned temp tables */
    1132             :                                 "      n.nspname !~ '^pg_temp_' AND "
    1133             :                                 "      n.nspname NOT IN ('pg_catalog', 'information_schema')");
    1134             : 
    1135           0 :         ntups = PQntuples(res);
    1136           0 :         i_nspname = PQfnumber(res, "nspname");
    1137           0 :         i_relname = PQfnumber(res, "relname");
    1138           0 :         i_attname = PQfnumber(res, "attname");
    1139           0 :         for (rowno = 0; rowno < ntups; rowno++)
    1140             :         {
    1141           0 :             found = true;
    1142           0 :             if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
    1143           0 :                 pg_fatal("could not open file \"%s\": %s\n",
    1144           0 :                          output_path, strerror(errno));
    1145           0 :             if (!db_used)
    1146             :             {
    1147           0 :                 fprintf(script, "In database: %s\n", active_db->db_name);
    1148           0 :                 db_used = true;
    1149             :             }
    1150           0 :             fprintf(script, "  %s.%s.%s\n",
    1151             :                     PQgetvalue(res, rowno, i_nspname),
    1152             :                     PQgetvalue(res, rowno, i_relname),
    1153             :                     PQgetvalue(res, rowno, i_attname));
    1154             :         }
    1155             : 
    1156           0 :         PQclear(res);
    1157             : 
    1158           0 :         PQfinish(conn);
    1159             :     }
    1160             : 
    1161           0 :     if (script)
    1162           0 :         fclose(script);
    1163             : 
    1164           0 :     if (found)
    1165             :     {
    1166           0 :         pg_log(PG_REPORT, "fatal\n");
    1167           0 :         pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
    1168             :                  "The internal format of \"jsonb\" changed during 9.4 beta so this cluster cannot currently\n"
    1169             :                  "be upgraded.  You can remove the problem tables and restart the upgrade.  A list\n"
    1170             :                  "of the problem columns is in the file:\n"
    1171             :                  "    %s\n\n", output_path);
    1172             :     }
    1173             :     else
    1174           0 :         check_ok();
    1175           0 : }
    1176             : 
    1177             : /*
    1178             :  * check_for_pg_role_prefix()
    1179             :  *
    1180             :  *  Versions older than 9.6 should not have any pg_* roles
    1181             :  */
    1182             : static void
    1183           0 : check_for_pg_role_prefix(ClusterInfo *cluster)
    1184             : {
    1185             :     PGresult   *res;
    1186           0 :     PGconn     *conn = connectToServer(cluster, "template1");
    1187             : 
    1188           0 :     prep_status("Checking for roles starting with \"pg_\"");
    1189             : 
    1190           0 :     res = executeQueryOrDie(conn,
    1191             :                             "SELECT * "
    1192             :                             "FROM pg_catalog.pg_roles "
    1193             :                             "WHERE rolname ~ '^pg_'");
    1194             : 
    1195           0 :     if (PQntuples(res) != 0)
    1196             :     {
    1197           0 :         if (cluster == &old_cluster)
    1198           0 :             pg_fatal("The source cluster contains roles starting with \"pg_\"\n");
    1199             :         else
    1200           0 :             pg_fatal("The target cluster contains roles starting with \"pg_\"\n");
    1201             :     }
    1202             : 
    1203           0 :     PQclear(res);
    1204             : 
    1205           0 :     PQfinish(conn);
    1206             : 
    1207           0 :     check_ok();
    1208           0 : }
    1209             : 
    1210             : 
    1211             : /*
    1212             :  * get_canonical_locale_name
    1213             :  *
    1214             :  * Send the locale name to the system, and hope we get back a canonical
    1215             :  * version.  This should match the backend's check_locale() function.
    1216             :  */
    1217             : static char *
    1218           0 : get_canonical_locale_name(int category, const char *locale)
    1219             : {
    1220             :     char       *save;
    1221             :     char       *res;
    1222             : 
    1223             :     /* get the current setting, so we can restore it. */
    1224           0 :     save = setlocale(category, NULL);
    1225           0 :     if (!save)
    1226           0 :         pg_fatal("failed to get the current locale\n");
    1227             : 
    1228             :     /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
    1229           0 :     save = pg_strdup(save);
    1230             : 
    1231             :     /* set the locale with setlocale, to see if it accepts it. */
    1232           0 :     res = setlocale(category, locale);
    1233             : 
    1234           0 :     if (!res)
    1235           0 :         pg_fatal("failed to get system locale name for \"%s\"\n", locale);
    1236             : 
    1237           0 :     res = pg_strdup(res);
    1238             : 
    1239             :     /* restore old value. */
    1240           0 :     if (!setlocale(category, save))
    1241           0 :         pg_fatal("failed to restore old locale \"%s\"\n", save);
    1242             : 
    1243           0 :     pg_free(save);
    1244             : 
    1245           0 :     return res;
    1246             : }

Generated by: LCOV version 1.13