Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Enumerations | Functions | Variables

pg_upgrade.h File Reference

#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "libpq-fe.h"
Include dependency graph for pg_upgrade.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  RelInfo
struct  RelInfoArr
struct  FileNameMap
struct  DbInfo
struct  DbInfoArr
struct  ControlData
struct  ClusterInfo
struct  LogOpts
struct  UserOpts
struct  OSInfo

Defines

#define DEF_PGUPORT   50432
#define USER_NAME_SIZE   128
#define MAX_STRING   1024
#define LINE_ALLOC   4096
#define QUERY_ALLOC   8192
#define MIGRATOR_API_VERSION   1
#define MESSAGE_WIDTH   60
#define GET_MAJOR_VERSION(v)   ((v) / 100)
#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"
#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"
#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"
#define SERVER_LOG_FILE   "pg_upgrade_server.log"
#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"
#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"
#define SERVER_START_LOG_FILE   SERVER_LOG_FILE
#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE
#define pg_copy_file   copy_file
#define pg_mv_file   rename
#define pg_link_file   link
#define PATH_SEPARATOR   '/'
#define RM_CMD   "rm -f"
#define RMDIR_CMD   "rm -rf"
#define SCRIPT_EXT   "sh"
#define ECHO_QUOTE   "'"
#define ECHO_BLANK   ""
#define CLUSTER_NAME(cluster)
#define atooid(x)   ((Oid) strtoul((x), NULL, 10))
#define TABLE_SPACE_SUBDIRS_CAT_VER   201001111
#define BINARY_UPGRADE_SERVER_FLAG_CAT_VER   201104251
#define VISIBILITY_MAP_CRASHSAFE_CAT_VER   201107031
#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231
#define EXEC_PSQL_ARGS   "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"

Typedefs

typedef long pgpid_t
typedef void * pageCnvCtx

Enumerations

enum  transferMode { TRANSFER_MODE_COPY, TRANSFER_MODE_LINK }
enum  eLogType {
  PG_VERBOSE, PG_STATUS, PG_REPORT, PG_WARNING,
  PG_FATAL
}

Functions

void output_check_banner (bool live_check)
void check_and_dump_old_cluster (bool live_check, char **sequence_script_file_name)
void check_new_cluster (void)
void report_clusters_compatible (void)
void issue_warnings (char *sequence_script_file_name)
void output_completion_banner (char *analyze_script_file_name, char *deletion_script_file_name)
void check_cluster_versions (void)
void check_cluster_compatibility (bool live_check)
void create_script_for_old_cluster_deletion (char **deletion_script_file_name)
void create_script_for_cluster_analyze (char **analyze_script_file_name)
void get_control_data (ClusterInfo *cluster, bool live_check)
void check_control_data (ControlData *oldctrl, ControlData *newctrl)
void disable_old_cluster (void)
void generate_old_dump (void)
bool exec_prog (const char *log_file, const char *opt_log_file, bool throw_error, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
bool void verify_directories (void)
bool pid_lock_file_exists (const char *datadir)
const char * copyAndUpdateFile (pageCnvCtx *pageConverter, const char *src, const char *dst, bool force)
const char * linkAndUpdateFile (pageCnvCtx *pageConverter, const char *src, const char *dst)
void check_hard_link (void)
FILE * fopen_priv (const char *path, const char *mode)
void install_support_functions_in_new_db (const char *db_name)
void uninstall_support_functions_from_new_cluster (void)
void get_loadable_libraries (void)
void check_loadable_libraries (void)
FileNameMapgen_db_file_maps (DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
void get_db_and_rel_infos (ClusterInfo *cluster)
void print_maps (FileNameMap *maps, int n, const char *db_name)
void parseCommandLine (int argc, char *argv[])
void adjust_data_dir (ClusterInfo *cluster)
void get_sock_dir (ClusterInfo *cluster, bool live_check)
void get_pg_database_relfilenode (ClusterInfo *cluster)
void transfer_all_new_tablespaces (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
void transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
void init_tablespaces (void)
PGconnconnectToServer (ClusterInfo *cluster, const char *db_name)
PGresultexecuteQueryOrDie (PGconn *conn, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
PGresult char * cluster_conn_opts (ClusterInfo *cluster)
bool start_postmaster (ClusterInfo *cluster, bool throw_error)
void stop_postmaster (bool fast)
uint32 get_major_server_version (ClusterInfo *cluster)
void check_pghost_envvar (void)
char * quote_identifier (const char *s)
int get_user_info (char **user_name)
void check_ok (void)
void report_status (eLogType type, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
void void pg_log (eLogType type, char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
void void void end_progress_output (void)
void prep_status (const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
const char * getErrorText (int errNum)
unsigned int str2uint (const char *str)
void pg_putenv (const char *var, const char *val)
void new_9_0_populate_pg_largeobject_metadata (ClusterInfo *cluster, bool check_mode)
void old_8_3_check_for_name_data_type_usage (ClusterInfo *cluster)
void old_8_3_check_for_tsquery_usage (ClusterInfo *cluster)
void old_8_3_check_ltree_usage (ClusterInfo *cluster)
void old_8_3_rebuild_tsvector_tables (ClusterInfo *cluster, bool check_mode)
void old_8_3_invalidate_hash_gin_indexes (ClusterInfo *cluster, bool check_mode)
void old_8_3_invalidate_bpchar_pattern_ops_indexes (ClusterInfo *cluster, bool check_mode)
char * old_8_3_create_sequence_script (ClusterInfo *cluster)
void parallel_exec_prog (const char *log_file, const char *opt_log_file, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
void void parallel_transfer_all_new_dbs (DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, char *old_tablespace)
bool reap_child (bool wait_for_child)

Variables

char * output_files []
LogOpts log_opts
UserOpts user_opts
ClusterInfo old_cluster
ClusterInfo new_cluster
OSInfo os_info

Define Documentation

#define atooid (   x  )     ((Oid) strtoul((x), NULL, 10))

Definition at line 99 of file pg_upgrade.h.

#define BINARY_UPGRADE_SERVER_FLAG_CAT_VER   201104251

Definition at line 104 of file pg_upgrade.h.

Referenced by start_postmaster().

#define CLUSTER_NAME (   cluster  ) 
Value:
((cluster) == &old_cluster ? "old" : \
                                 (cluster) == &new_cluster ? "new" : "none")

Definition at line 96 of file pg_upgrade.h.

Referenced by adjust_data_dir(), check_for_prepared_transactions(), get_control_data(), get_db_and_rel_infos(), and start_postmaster().

#define DB_DUMP_FILE_MASK   "pg_upgrade_dump_%u.custom"

Definition at line 33 of file pg_upgrade.h.

Referenced by cleanup(), create_new_objects(), and generate_old_dump().

#define DB_DUMP_LOG_FILE_MASK   "pg_upgrade_dump_%u.log"

Definition at line 35 of file pg_upgrade.h.

Referenced by cleanup(), create_new_objects(), and generate_old_dump().

#define DEF_PGUPORT   50432

Definition at line 16 of file pg_upgrade.h.

Referenced by check_cluster_compatibility(), and get_sock_dir().

#define ECHO_BLANK   ""

Definition at line 81 of file pg_upgrade.h.

Referenced by create_script_for_cluster_analyze().

#define ECHO_QUOTE   "'"

Definition at line 80 of file pg_upgrade.h.

Referenced by create_script_for_cluster_analyze().

#define EXEC_PSQL_ARGS   "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"

Definition at line 342 of file pg_upgrade.h.

Referenced by issue_warnings(), and prepare_new_databases().

#define GET_MAJOR_VERSION (   v  )     ((v) / 100)
#define GLOBALS_DUMP_FILE   "pg_upgrade_dump_globals.sql"

Definition at line 32 of file pg_upgrade.h.

Referenced by cleanup(), generate_old_dump(), and prepare_new_databases().

#define INTERNAL_LOG_FILE   "pg_upgrade_internal.log"

Definition at line 38 of file pg_upgrade.h.

Referenced by parseCommandLine().

#define LINE_ALLOC   4096

Definition at line 22 of file pg_upgrade.h.

#define MAX_STRING   1024

Definition at line 21 of file pg_upgrade.h.

#define MESSAGE_WIDTH   60

Definition at line 27 of file pg_upgrade.h.

Referenced by pg_log(), and prep_status().

#define MIGRATOR_API_VERSION   1

Definition at line 25 of file pg_upgrade.h.

#define MULTIXACT_FORMATCHANGE_CAT_VER   201301231

Definition at line 117 of file pg_upgrade.h.

Referenced by copy_clog_xlog_xid(), and get_control_data().

#define PATH_SEPARATOR   '/'

Definition at line 76 of file pg_upgrade.h.

Referenced by create_script_for_old_cluster_deletion().

#define pg_copy_file   copy_file

Definition at line 73 of file pg_upgrade.h.

Referenced by copyAndUpdateFile().

#define pg_link_file   link

Definition at line 75 of file pg_upgrade.h.

Referenced by check_hard_link(), and linkAndUpdateFile().

#define pg_mv_file   rename

Definition at line 74 of file pg_upgrade.h.

Referenced by disable_old_cluster().

#define QUERY_ALLOC   8192

Definition at line 23 of file pg_upgrade.h.

#define RM_CMD   "rm -f"

Definition at line 77 of file pg_upgrade.h.

Referenced by create_script_for_old_cluster_deletion().

#define RMDIR_CMD   "rm -rf"

Definition at line 78 of file pg_upgrade.h.

Referenced by create_script_for_old_cluster_deletion().

#define SCRIPT_EXT   "sh"
#define SERVER_LOG_FILE   "pg_upgrade_server.log"

Definition at line 36 of file pg_upgrade.h.

Referenced by start_postmaster().

#define SERVER_START_LOG_FILE   SERVER_LOG_FILE

Definition at line 59 of file pg_upgrade.h.

Referenced by start_postmaster().

#define SERVER_STOP_LOG_FILE   SERVER_LOG_FILE

Definition at line 60 of file pg_upgrade.h.

Referenced by stop_postmaster().

#define TABLE_SPACE_SUBDIRS_CAT_VER   201001111

Definition at line 102 of file pg_upgrade.h.

Referenced by check_cluster_compatibility().

#define USER_NAME_SIZE   128

Definition at line 19 of file pg_upgrade.h.

#define UTILITY_LOG_FILE   "pg_upgrade_utility.log"
#define VISIBILITY_MAP_CRASHSAFE_CAT_VER   201107031

Definition at line 109 of file pg_upgrade.h.

Referenced by transfer_single_new_db().


Typedef Documentation

typedef void* pageCnvCtx

Definition at line 380 of file pg_upgrade.h.

typedef long pgpid_t

Definition at line 233 of file pg_upgrade.h.


Enumeration Type Documentation

enum eLogType
Enumerator:
PG_VERBOSE 
PG_STATUS 
PG_REPORT 
PG_WARNING 
PG_FATAL 

Definition at line 223 of file pg_upgrade.h.

{
    PG_VERBOSE,
    PG_STATUS,
    PG_REPORT,
    PG_WARNING,
    PG_FATAL
} eLogType;

Enumerator:
TRANSFER_MODE_COPY 
TRANSFER_MODE_LINK 

Definition at line 214 of file pg_upgrade.h.

{
    TRANSFER_MODE_COPY,
    TRANSFER_MODE_LINK
} transferMode;


Function Documentation

void adjust_data_dir ( ClusterInfo cluster  ) 

Definition at line 337 of file option.c.

References ClusterInfo::bindir, check_ok(), CLUSTER_NAME, filename, getErrorText(), NULL, PG_FATAL, pg_log(), pg_strdup(), ClusterInfo::pgconfig, ClusterInfo::pgdata, prep_status(), and snprintf().

Referenced by main().

{
    char        filename[MAXPGPATH];
    char        cmd[MAXPGPATH],
                cmd_output[MAX_STRING];
    FILE       *fp,
               *output;

    /* If there is no postgresql.conf, it can't be a config-only dir */
    snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig);
    if ((fp = fopen(filename, "r")) == NULL)
        return;
    fclose(fp);

    /* If PG_VERSION exists, it can't be a config-only dir */
    snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig);
    if ((fp = fopen(filename, "r")) != NULL)
    {
        fclose(fp);
        return;
    }

    /* Must be a configuration directory, so find the real data directory. */

    prep_status("Finding the real data directory for the %s cluster",
                CLUSTER_NAME(cluster));

    /*
     * We don't have a data directory yet, so we can't check the PG version,
     * so this might fail --- only works for PG 9.2+.   If this fails,
     * pg_upgrade will fail anyway because the data files will not be found.
     */
    snprintf(cmd, sizeof(cmd), "\"%s/postmaster\" -D \"%s\" -C data_directory",
             cluster->bindir, cluster->pgconfig);

    if ((output = popen(cmd, "r")) == NULL ||
        fgets(cmd_output, sizeof(cmd_output), output) == NULL)
        pg_log(PG_FATAL, "Could not get data directory using %s: %s\n",
               cmd, getErrorText(errno));

    pclose(output);

    /* Remove trailing newline */
    if (strchr(cmd_output, '\n') != NULL)
        *strchr(cmd_output, '\n') = '\0';

    cluster->pgdata = pg_strdup(cmd_output);

    check_ok();
}

void check_and_dump_old_cluster ( bool  live_check,
char **  sequence_script_file_name 
)

Definition at line 74 of file check.c.

References UserOpts::check, check_for_isn_and_int8_passing_mismatch(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_is_super_user(), generate_old_dump(), get_db_and_rel_infos(), get_loadable_libraries(), GET_MAJOR_VERSION, get_pg_database_relfilenode(), init_tablespaces(), ClusterInfo::major_version, new_9_0_populate_pg_largeobject_metadata(), old_8_3_check_for_name_data_type_usage(), old_8_3_check_for_tsquery_usage(), old_8_3_check_ltree_usage(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), old_cluster, set_locale_and_encoding(), start_postmaster(), stop_postmaster(), and user_opts.

Referenced by main().

{
    /* -- OLD -- */

    if (!live_check)
        start_postmaster(&old_cluster, true);

    set_locale_and_encoding(&old_cluster);

    get_pg_database_relfilenode(&old_cluster);

    /* Extract a list of databases and tables from the old cluster */
    get_db_and_rel_infos(&old_cluster);

    init_tablespaces();

    get_loadable_libraries();


    /*
     * Check for various failure cases
     */
    check_is_super_user(&old_cluster);
    check_for_prepared_transactions(&old_cluster);
    check_for_reg_data_type_usage(&old_cluster);
    check_for_isn_and_int8_passing_mismatch(&old_cluster);

    /* old = PG 8.3 checks? */
    if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
    {
        old_8_3_check_for_name_data_type_usage(&old_cluster);
        old_8_3_check_for_tsquery_usage(&old_cluster);
        old_8_3_check_ltree_usage(&old_cluster);
        if (user_opts.check)
        {
            old_8_3_rebuild_tsvector_tables(&old_cluster, true);
            old_8_3_invalidate_hash_gin_indexes(&old_cluster, true);
            old_8_3_invalidate_bpchar_pattern_ops_indexes(&old_cluster, true);
        }
        else

            /*
             * While we have the old server running, create the script to
             * properly restore its sequence values but we report this at the
             * end.
             */
            *sequence_script_file_name =
                old_8_3_create_sequence_script(&old_cluster);
    }

    /* Pre-PG 9.0 had no large object permissions */
    if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
        new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);

    /*
     * While not a check option, we do this now because this is the only time
     * the old server is running.
     */
    if (!user_opts.check)
        generate_old_dump();

    if (!live_check)
        stop_postmaster(false);
}

void check_cluster_compatibility ( bool  live_check  ) 

Definition at line 310 of file check.c.

References ControlData::cat_ver, check_control_data(), ClusterInfo::controldata, DEF_PGUPORT, get_control_data(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, PG_FATAL, pg_log(), ClusterInfo::port, and TABLE_SPACE_SUBDIRS_CAT_VER.

Referenced by main().

{
    /* get/check pg_control data of servers */
    get_control_data(&old_cluster, live_check);
    get_control_data(&new_cluster, false);
    check_control_data(&old_cluster.controldata, &new_cluster.controldata);

    /* Is it 9.0 but without tablespace directories? */
    if (GET_MAJOR_VERSION(new_cluster.major_version) == 900 &&
        new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS_CAT_VER)
        pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
               "because of backend API changes made during development.\n");

    /* We read the real port number for PG >= 9.1 */
    if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
        old_cluster.port == DEF_PGUPORT)
            pg_log(PG_FATAL, "When checking a pre-PG 9.1 live old server, "
                   "you must specify the old server's port number.\n");

    if (live_check && old_cluster.port == new_cluster.port)
        pg_log(PG_FATAL, "When checking a live server, "
               "the old and new port numbers must be different.\n");
}

void check_cluster_versions ( void   ) 

Definition at line 262 of file check.c.

References ClusterInfo::bin_version, check_ok(), get_bin_version(), get_major_server_version(), GET_MAJOR_VERSION, ClusterInfo::major_version, new_cluster, old_cluster, PG_FATAL, pg_log(), and prep_status().

Referenced by main().

{
    prep_status("Checking cluster versions");

    /* get old and new cluster versions */
    old_cluster.major_version = get_major_server_version(&old_cluster);
    new_cluster.major_version = get_major_server_version(&new_cluster);

    /*
     * We allow upgrades from/to the same major version for alpha/beta
     * upgrades
     */

    if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
        pg_log(PG_FATAL, "This utility can only upgrade from PostgreSQL version 8.3 and later.\n");

    /* Only current PG version is supported as a target */
    if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
        pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version %s.\n",
               PG_MAJORVERSION);

    /*
     * We can't allow downgrading because we use the target pg_dumpall, and
     * pg_dumpall cannot operate on new database versions, only older
     * versions.
     */
    if (old_cluster.major_version > new_cluster.major_version)
        pg_log(PG_FATAL, "This utility cannot be used to downgrade to older major PostgreSQL versions.\n");

    /* get old and new binary versions */
    get_bin_version(&old_cluster);
    get_bin_version(&new_cluster);

    /* Ensure binaries match the designated data directories */
    if (GET_MAJOR_VERSION(old_cluster.major_version) !=
        GET_MAJOR_VERSION(old_cluster.bin_version))
        pg_log(PG_FATAL,
               "Old cluster data and binary directories are from different major versions.\n");
    if (GET_MAJOR_VERSION(new_cluster.major_version) !=
        GET_MAJOR_VERSION(new_cluster.bin_version))
        pg_log(PG_FATAL,
               "New cluster data and binary directories are from different major versions.\n");

    check_ok();
}

void check_control_data ( ControlData oldctrl,
ControlData newctrl 
)

Definition at line 574 of file controldata.c.

References ControlData::align, ControlData::blocksz, ControlData::data_checksum_version, ControlData::date_is_int, ControlData::ident, ControlData::index, ControlData::largesz, PG_FATAL, pg_log(), PG_WARNING, ControlData::toast, ControlData::walseg, and ControlData::walsz.

Referenced by check_cluster_compatibility().

{
    if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
        pg_log(PG_FATAL,
               "old and new pg_controldata alignments are invalid or do not match\n"
               "Likely one cluster is a 32-bit install, the other 64-bit\n");

    if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
        pg_log(PG_FATAL,
               "old and new pg_controldata block sizes are invalid or do not match\n");

    if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
        pg_log(PG_FATAL,
               "old and new pg_controldata maximum relation segement sizes are invalid or do not match\n");

    if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
        pg_log(PG_FATAL,
               "old and new pg_controldata WAL block sizes are invalid or do not match\n");

    if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
        pg_log(PG_FATAL,
               "old and new pg_controldata WAL segment sizes are invalid or do not match\n");

    if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
        pg_log(PG_FATAL,
               "old and new pg_controldata maximum identifier lengths are invalid or do not match\n");

    if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
        pg_log(PG_FATAL,
               "old and new pg_controldata maximum indexed columns are invalid or do not match\n");

    if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
        pg_log(PG_FATAL,
               "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n");

    if (oldctrl->date_is_int != newctrl->date_is_int)
    {
        pg_log(PG_WARNING,
               "\nOld and new pg_controldata date/time storage types do not match.\n");

        /*
         * This is a common 8.3 -> 8.4 upgrade problem, so we are more verbose
         */
        pg_log(PG_FATAL,
            "You will need to rebuild the new server with configure option\n"
               "--disable-integer-datetimes or get server binaries built with those\n"
               "options.\n");
    }

    /* We might eventually allow upgrades from checksum to no-checksum clusters. */
    if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
    {
        pg_log(PG_FATAL,
               "old and new pg_controldata checksum versions are invalid or do not match\n");
    }
}

void check_hard_link ( void   ) 

Definition at line 197 of file file.c.

References getErrorText(), new_cluster, old_cluster, PG_FATAL, pg_link_file, pg_log(), ClusterInfo::pgdata, snprintf(), and unlink().

Referenced by check_new_cluster().

{
    char        existing_file[MAXPGPATH];
    char        new_link_file[MAXPGPATH];

    snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
    snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
    unlink(new_link_file);      /* might fail */

    if (pg_link_file(existing_file, new_link_file) == -1)
    {
        pg_log(PG_FATAL,
               "Could not create hard link between old and new data directories: %s\n"
               "In link mode the old and new data directories must be on the same file system volume.\n",
               getErrorText(errno));
    }
    unlink(new_link_file);
}

void check_loadable_libraries ( void   ) 

Definition at line 276 of file function.c.

References check_ok(), conn, connectToServer(), fopen_priv(), GET_MAJOR_VERSION, getErrorText(), OSInfo::libraries, ClusterInfo::major_version, MAXPGPATH, new_cluster, NULL, OSInfo::num_libraries, old_cluster, os_info, PG_FATAL, pg_log(), PG_REPORT, PG_UPGRADE_SUPPORT, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQexec(), PQfinish(), PQresultStatus(), prep_status(), and snprintf().

Referenced by check_new_cluster().

{
    PGconn     *conn = connectToServer(&new_cluster, "template1");
    int         libnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for presence of required libraries");

    snprintf(output_path, sizeof(output_path), "loadable_libraries.txt");

    for (libnum = 0; libnum < os_info.num_libraries; libnum++)
    {
        char       *lib = os_info.libraries[libnum];
        int         llen = strlen(lib);
        char        cmd[7 + 2 * MAXPGPATH + 1];
        PGresult   *res;

        /*
         * In Postgres 9.0, Python 3 support was added, and to do that, a
         * plpython2u language was created with library name plpython2.so as a
         * symbolic link to plpython.so.  In Postgres 9.1, only the
         * plpython2.so library was created, and both plpythonu and plpython2u
         * pointing to it.  For this reason, any reference to library name
         * "plpython" in an old PG <= 9.1 cluster must look for "plpython2" in
         * the new cluster.
         *
         * For this case, we could check pg_pltemplate, but that only works
         * for languages, and does not help with function shared objects, so
         * we just do a general fix.
         */
        if (GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
            strcmp(lib, "$libdir/plpython") == 0)
        {
            lib = "$libdir/plpython2";
            llen = strlen(lib);
        }

        strcpy(cmd, "LOAD '");
        PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
        strcat(cmd, "'");

        res = PQexec(conn, cmd);

        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            found = true;

            /* exit and report missing support library with special message */
            if (strcmp(lib, PG_UPGRADE_SUPPORT) == 0)
                pg_log(PG_FATAL,
                       "The pg_upgrade_support module must be created and installed in the new cluster.\n");

            if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
                       output_path, getErrorText(errno));
            fprintf(script, "Could not load library \"%s\"\n%s\n",
                    lib,
                    PQerrorMessage(conn));
        }

        PQclear(res);
    }

    PQfinish(conn);

    if (found)
    {
        fclose(script);
        pg_log(PG_REPORT, "fatal\n");
        pg_log(PG_FATAL,
               "Your installation references loadable libraries that are missing from the\n"
               "new installation.  You can add these libraries to the new installation,\n"
               "or remove the functions using them from the old installation.  A list of\n"
               "problem libraries is in the file:\n"
               "    %s\n\n", output_path);
    }
    else
        check_ok();
}

void check_new_cluster ( void   ) 

Definition at line 141 of file check.c.

References check_for_prepared_transactions(), check_hard_link(), check_is_super_user(), check_loadable_libraries(), check_locale_and_encoding(), check_new_cluster_is_empty(), ClusterInfo::controldata, get_db_and_rel_infos(), ClusterInfo::install_role_oid, new_cluster, old_cluster, PG_FATAL, pg_log(), ClusterInfo::role_count, set_locale_and_encoding(), UserOpts::transfer_mode, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

{
    set_locale_and_encoding(&new_cluster);

    check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata);

    get_db_and_rel_infos(&new_cluster);

    check_new_cluster_is_empty();

    check_loadable_libraries();

    if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
        check_hard_link();

    check_is_super_user(&new_cluster);

    /*
     *  We don't restore our own user, so both clusters must match have
     *  matching install-user oids.
     */
    if (old_cluster.install_role_oid != new_cluster.install_role_oid)
        pg_log(PG_FATAL,
        "Old and new cluster install users have different values for pg_authid.oid.\n");

    /*
     *  We only allow the install user in the new cluster because other
     *  defined users might match users defined in the old cluster and
     *  generate an error during pg_dump restore.
     */
    if (new_cluster.role_count != 1)
        pg_log(PG_FATAL, "Only the install user can be defined in the new cluster.\n");
    
    check_for_prepared_transactions(&new_cluster);
}

static void check_ok ( void   ) 

Definition at line 2380 of file initdb.c.

References PG_REPORT, and report_status().

Referenced by adjust_data_dir(), bootstrap_template1(), check_cluster_versions(), check_for_isn_and_int8_passing_mismatch(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_is_super_user(), check_loadable_libraries(), copy_clog_xlog_xid(), copy_subdir_files(), create_data_directory(), create_new_objects(), create_script_for_cluster_analyze(), create_script_for_old_cluster_deletion(), create_xlog_symlink(), disable_old_cluster(), generate_old_dump(), get_set_pwd(), initialize_data_directory(), issue_warnings(), load_plpgsql(), main(), make_postgres(), make_template0(), new_9_0_populate_pg_largeobject_metadata(), old_8_3_check_for_name_data_type_usage(), old_8_3_check_for_tsquery_usage(), old_8_3_check_ltree_usage(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), perform_fsync(), prepare_new_cluster(), prepare_new_databases(), set_frozenxids(), setup_auth(), setup_collation(), setup_config(), setup_conversion(), setup_depend(), setup_description(), setup_dictionary(), setup_privileges(), setup_schema(), setup_sysviews(), transfer_all_new_tablespaces(), uninstall_support_functions_from_new_cluster(), and vacuum_db().

{
    if (caught_signal)
    {
        printf(_("caught signal\n"));
        fflush(stdout);
        exit_nicely();
    }
    else if (output_failed)
    {
        printf(_("could not write to child process: %s\n"),
               strerror(output_errno));
        fflush(stdout);
        exit_nicely();
    }
    else
    {
        /* all seems well */
        printf(_("ok\n"));
        fflush(stdout);
    }
}

void check_pghost_envvar ( void   ) 

Definition at line 295 of file server.c.

References _PQconninfoOption::envvar, _PQconninfoOption::keyword, PG_FATAL, pg_log(), PQconndefaults(), PQconninfoFree(), and value.

Referenced by setup().

{
    PQconninfoOption *option;
    PQconninfoOption *start;

    /* Get valid libpq env vars from the PQconndefaults function */

    start = PQconndefaults();

    for (option = start; option->keyword != NULL; option++)
    {
        if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
                               strcmp(option->envvar, "PGHOSTADDR") == 0))
        {
            const char *value = getenv(option->envvar);

            if (value && strlen(value) > 0 &&
            /* check for 'local' host values */
                (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
                 strcmp(value, "::1") != 0 && value[0] != '/'))
                pg_log(PG_FATAL,
                       "libpq environment variable %s has a non-local server value: %s\n",
                       option->envvar, value);
        }
    }

    /* Free the memory that libpq allocated on our behalf */
    PQconninfoFree(start);
}

PGresult char* cluster_conn_opts ( ClusterInfo cluster  ) 

Definition at line 80 of file server.c.

References MAXPGPATH, NAMEDATALEN, os_info, ClusterInfo::port, snprintf(), ClusterInfo::sockdir, and OSInfo::user.

Referenced by create_new_objects(), generate_old_dump(), issue_warnings(), prepare_new_cluster(), and prepare_new_databases().

{
    static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];

    if (cluster->sockdir)
        snprintf(conn_opts, sizeof(conn_opts),
                 "--host \"%s\" --port %d --username \"%s\"",
                 cluster->sockdir, cluster->port, os_info.user);
    else
        snprintf(conn_opts, sizeof(conn_opts),
                 "--port %d --username \"%s\"",
                 cluster->port, os_info.user);

    return conn_opts;
}

PGconn* connectToServer ( ClusterInfo cluster,
const char *  db_name 
)
const char* copyAndUpdateFile ( pageCnvCtx pageConverter,
const char *  src,
const char *  dst,
bool  force 
)

Definition at line 32 of file file.c.

References buf, close, getErrorText(), NULL, pg_copy_file, read, and write.

Referenced by transfer_relfile().

{
    if (pageConverter == NULL)
    {
        if (pg_copy_file(src, dst, force) == -1)
            return getErrorText(errno);
        else
            return NULL;
    }
    else
    {
        /*
         * We have a pageConverter object - that implies that the
         * PageLayoutVersion differs between the two clusters so we have to
         * perform a page-by-page conversion.
         *
         * If the pageConverter can convert the entire file at once, invoke
         * that plugin function, otherwise, read each page in the relation
         * file and call the convertPage plugin function.
         */

#ifdef PAGE_CONVERSION
        if (pageConverter->convertFile)
            return pageConverter->convertFile(pageConverter->pluginData,
                                              dst, src);
        else
#endif
        {
            int         src_fd;
            int         dstfd;
            char        buf[BLCKSZ];
            ssize_t     bytesRead;
            const char *msg = NULL;

            if ((src_fd = open(src, O_RDONLY, 0)) < 0)
                return "could not open source file";

            if ((dstfd = open(dst, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
            {
                close(src_fd);
                return "could not create destination file";
            }

            while ((bytesRead = read(src_fd, buf, BLCKSZ)) == BLCKSZ)
            {
#ifdef PAGE_CONVERSION
                if ((msg = pageConverter->convertPage(pageConverter->pluginData, buf, buf)) != NULL)
                    break;
#endif
                if (write(dstfd, buf, BLCKSZ) != BLCKSZ)
                {
                    msg = "could not write new page to destination";
                    break;
                }
            }

            close(src_fd);
            close(dstfd);

            if (msg)
                return msg;
            else if (bytesRead != 0)
                return "found partial page in source file";
            else
                return NULL;
        }
    }
}

void create_script_for_cluster_analyze ( char **  analyze_script_file_name  ) 

Definition at line 461 of file check.c.

References ClusterInfo::bindir, check_ok(), ECHO_BLANK, ECHO_QUOTE, fopen_priv(), GET_MAJOR_VERSION, getErrorText(), ClusterInfo::major_version, MAXPGPATH, new_cluster, NULL, old_cluster, PG_FATAL, pg_log(), pg_malloc(), prep_status(), SCRIPT_EXT, and snprintf().

Referenced by main().

{
    FILE       *script = NULL;

    *analyze_script_file_name = pg_malloc(MAXPGPATH);

    prep_status("Creating script to analyze new cluster");

    snprintf(*analyze_script_file_name, MAXPGPATH, "analyze_new_cluster.%s",
             SCRIPT_EXT);

    if ((script = fopen_priv(*analyze_script_file_name, "w")) == NULL)
        pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
               *analyze_script_file_name, getErrorText(errno));

#ifndef WIN32
    /* add shebang header */
    fprintf(script, "#!/bin/sh\n\n");
#else
    /* suppress command echoing */
    fprintf(script, "@echo off\n");
#endif

    fprintf(script, "echo %sThis script will generate minimal optimizer statistics rapidly%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %sso your system is usable, and then gather statistics twice more%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %swith increasing accuracy.  When it is done, your system will%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %shave the default level of optimizer statistics.%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo%s\n\n", ECHO_BLANK);

    fprintf(script, "echo %sIf you have used ALTER TABLE to modify the statistics target for%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %sany tables, you might want to remove them and restore them after%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %srunning this script because they will delay fast statistics generation.%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo%s\n\n", ECHO_BLANK);

    fprintf(script, "echo %sIf you would like default statistics as quickly as possible, cancel%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %sthis script and run:%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %s    \"%s/vacuumdb\" --all %s%s\n", ECHO_QUOTE, new_cluster.bindir,
    /* Did we copy the free space files? */
            (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
            "--analyze-only" : "--analyze", ECHO_QUOTE);
    fprintf(script, "echo%s\n\n", ECHO_BLANK);

#ifndef WIN32
    fprintf(script, "sleep 2\n");
    fprintf(script, "PGOPTIONS='-c default_statistics_target=1 -c vacuum_cost_delay=0'\n");
    /* only need to export once */
    fprintf(script, "export PGOPTIONS\n");
#else
    fprintf(script, "REM simulate sleep 2\n");
    fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
    fprintf(script, "SET PGOPTIONS=-c default_statistics_target=1 -c vacuum_cost_delay=0\n");
#endif

    fprintf(script, "echo %sGenerating minimal optimizer statistics (1 target)%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %s--------------------------------------------------%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "\"%s/vacuumdb\" --all --analyze-only\n", new_cluster.bindir);
    fprintf(script, "echo%s\n", ECHO_BLANK);
    fprintf(script, "echo %sThe server is now available with minimal optimizer statistics.%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %sQuery performance will be optimal once this script completes.%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo%s\n\n", ECHO_BLANK);

#ifndef WIN32
    fprintf(script, "sleep 2\n");
    fprintf(script, "PGOPTIONS='-c default_statistics_target=10'\n");
#else
    fprintf(script, "REM simulate sleep\n");
    fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
    fprintf(script, "SET PGOPTIONS=-c default_statistics_target=10\n");
#endif

    fprintf(script, "echo %sGenerating medium optimizer statistics (10 targets)%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %s---------------------------------------------------%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "\"%s/vacuumdb\" --all --analyze-only\n", new_cluster.bindir);
    fprintf(script, "echo%s\n\n", ECHO_BLANK);

#ifndef WIN32
    fprintf(script, "unset PGOPTIONS\n");
#else
    fprintf(script, "SET PGOPTIONS\n");
#endif

    fprintf(script, "echo %sGenerating default (full) optimizer statistics (100 targets?)%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "echo %s-------------------------------------------------------------%s\n",
            ECHO_QUOTE, ECHO_QUOTE);
    fprintf(script, "\"%s/vacuumdb\" --all %s\n", new_cluster.bindir,
    /* Did we copy the free space files? */
            (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
            "--analyze-only" : "--analyze");

    fprintf(script, "echo%s\n\n", ECHO_BLANK);
    fprintf(script, "echo %sDone%s\n",
            ECHO_QUOTE, ECHO_QUOTE);

    fclose(script);

#ifndef WIN32
    if (chmod(*analyze_script_file_name, S_IRWXU) != 0)
        pg_log(PG_FATAL, "Could not add execute permission to file \"%s\": %s\n",
               *analyze_script_file_name, getErrorText(errno));
#endif

    check_ok();
}

void create_script_for_old_cluster_deletion ( char **  deletion_script_file_name  ) 

Definition at line 588 of file check.c.

References canonicalize_path(), check_ok(), DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, fix_path_separator(), fopen_priv(), GET_MAJOR_VERSION, getErrorText(), ClusterInfo::major_version, MAXPGPATH, DbInfoArr::ndbs, NULL, OSInfo::num_old_tablespaces, old_cluster, OSInfo::old_tablespaces, os_info, path_is_prefix_of_path(), PATH_SEPARATOR, PG_FATAL, pg_free(), pg_log(), pg_malloc(), ClusterInfo::pgdata, prep_status(), RM_CMD, RMDIR_CMD, SCRIPT_EXT, snprintf(), strlcpy(), ClusterInfo::tablespace_suffix, and unlink().

Referenced by main().

{
    FILE       *script = NULL;
    int         tblnum;
    char        old_cluster_pgdata[MAXPGPATH];

    *deletion_script_file_name = pg_malloc(MAXPGPATH);

    snprintf(*deletion_script_file_name, MAXPGPATH, "delete_old_cluster.%s",
             SCRIPT_EXT);

    /*
     *  Some users (oddly) create tablespaces inside the cluster data
     *  directory.  We can't create a proper old cluster delete script
     *  in that case.
     */
    strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
    canonicalize_path(old_cluster_pgdata);
    for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
    {
        char        old_tablespace_dir[MAXPGPATH];
        
        strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
        canonicalize_path(old_tablespace_dir);
        if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
        {
            /* Unlink file in case it is left over from a previous run. */
            unlink(*deletion_script_file_name);
            pg_free(*deletion_script_file_name);
            *deletion_script_file_name = NULL;
            return;
        }
    }

    prep_status("Creating script to delete old cluster");

    if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
        pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
               *deletion_script_file_name, getErrorText(errno));

#ifndef WIN32
    /* add shebang header */
    fprintf(script, "#!/bin/sh\n\n");
#endif

    /* delete old cluster's default tablespace */
    fprintf(script, RMDIR_CMD " %s\n", fix_path_separator(old_cluster.pgdata));

    /* delete old cluster's alternate tablespaces */
    for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
    {
        /*
         * Do the old cluster's per-database directories share a directory
         * with a new version-specific tablespace?
         */
        if (strlen(old_cluster.tablespace_suffix) == 0)
        {
            /* delete per-database directories */
            int         dbnum;

            fprintf(script, "\n");
            /* remove PG_VERSION? */
            if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
                fprintf(script, RM_CMD " %s%s%cPG_VERSION\n",
                        fix_path_separator(os_info.old_tablespaces[tblnum]), 
                        fix_path_separator(old_cluster.tablespace_suffix),
                        PATH_SEPARATOR);

            for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
            {
                fprintf(script, RMDIR_CMD " %s%s%c%d\n",
                        fix_path_separator(os_info.old_tablespaces[tblnum]),
                        fix_path_separator(old_cluster.tablespace_suffix),
                        PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
            }
        }
        else

            /*
             * Simply delete the tablespace directory, which might be ".old"
             * or a version-specific subdirectory.
             */
            fprintf(script, RMDIR_CMD " %s%s\n",
                    fix_path_separator(os_info.old_tablespaces[tblnum]), 
                    fix_path_separator(old_cluster.tablespace_suffix));
    }

    fclose(script);

#ifndef WIN32
    if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
        pg_log(PG_FATAL, "Could not add execute permission to file \"%s\": %s\n",
               *deletion_script_file_name, getErrorText(errno));
#endif

    check_ok();
}

void disable_old_cluster ( void   ) 

Definition at line 634 of file controldata.c.

References check_ok(), old_cluster, PG_FATAL, pg_log(), pg_mv_file, PG_REPORT, ClusterInfo::pgdata, prep_status(), and snprintf().

Referenced by main().

{
    char        old_path[MAXPGPATH],
                new_path[MAXPGPATH];

    /* rename pg_control so old server cannot be accidentally started */
    prep_status("Adding \".old\" suffix to old global/pg_control");

    snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
    snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
    if (pg_mv_file(old_path, new_path) != 0)
        pg_log(PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path);
    check_ok();

    pg_log(PG_REPORT, "\n"
           "If you want to start the old cluster, you will need to remove\n"
           "the \".old\" suffix from %s/global/pg_control.old.\n"
         "Because \"link\" mode was used, the old cluster cannot be safely\n"
    "started once the new cluster has been started.\n\n", old_cluster.pgdata);
}

void void void end_progress_output ( void   ) 

Definition at line 40 of file util.c.

References prep_status().

Referenced by create_new_objects(), generate_old_dump(), and transfer_all_new_tablespaces().

{
    /*
     *  In case nothing printed; pass a space so gcc doesn't complain about
     *  empty format string.
     */
    prep_status(" ");
}

bool exec_prog ( const char *  log_file,
const char *  opt_log_file,
bool  throw_error,
const char *  fmt,
  ... 
)
PGresult* executeQueryOrDie ( PGconn conn,
const char *  fmt,
  ... 
)
FILE* fopen_priv ( const char *  path,
const char *  mode 
)
FileNameMap* gen_db_file_maps ( DbInfo old_db,
DbInfo new_db,
int *  nmaps,
const char *  old_pgdata,
const char *  new_pgdata 
)

Definition at line 37 of file info.c.

References create_rel_filename_map(), DbInfo::db_name, GET_MAJOR_VERSION, ClusterInfo::major_version, maps, Min, RelInfoArr::nrels, RelInfo::nspname, old_cluster, PG_FATAL, pg_log(), pg_malloc(), DbInfo::rel_arr, RelInfo::relname, RelInfo::reloid, and RelInfoArr::rels.

Referenced by transfer_all_new_dbs().

{
    FileNameMap *maps;
    int         relnum;
    int         num_maps = 0;

    maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
                                     old_db->rel_arr.nrels);

    for (relnum = 0; relnum < Min(old_db->rel_arr.nrels, new_db->rel_arr.nrels);
         relnum++)
    {
        RelInfo    *old_rel = &old_db->rel_arr.rels[relnum];
        RelInfo    *new_rel = &new_db->rel_arr.rels[relnum];

        if (old_rel->reloid != new_rel->reloid)
            pg_log(PG_FATAL, "Mismatch of relation OID in database \"%s\": old OID %d, new OID %d\n",
                   old_db->db_name, old_rel->reloid, new_rel->reloid);

        /*
         * TOAST table names initially match the heap pg_class oid. In
         * pre-8.4, TOAST table names change during CLUSTER; in pre-9.0, TOAST
         * table names change during ALTER TABLE ALTER COLUMN SET TYPE. In >=
         * 9.0, TOAST relation names always use heap table oids, hence we
         * cannot check relation names when upgrading from pre-9.0. Clusters
         * upgraded to 9.0 will get matching TOAST names.
         * If index names don't match primary key constraint names, this will
         * fail because pg_dump dumps constraint names and pg_upgrade checks
         * index names.
         */
        if (strcmp(old_rel->nspname, new_rel->nspname) != 0 ||
            ((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 ||
              strcmp(old_rel->nspname, "pg_toast") != 0) &&
             strcmp(old_rel->relname, new_rel->relname) != 0))
            pg_log(PG_FATAL, "Mismatch of relation names in database \"%s\": "
                   "old name \"%s.%s\", new name \"%s.%s\"\n",
                   old_db->db_name, old_rel->nspname, old_rel->relname,
                   new_rel->nspname, new_rel->relname);

        create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
                                old_rel, new_rel, maps + num_maps);
        num_maps++;
    }

    /* Do this check after the loop so hopefully we will produce a clearer error above */
    if (old_db->rel_arr.nrels != new_db->rel_arr.nrels)
        pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n",
               old_db->db_name);

    *nmaps = num_maps;
    return maps;
}

void generate_old_dump ( void   ) 

Definition at line 17 of file dump.c.

References ClusterInfo::bindir, check_ok(), cluster_conn_opts(), DB_DUMP_FILE_MASK, DB_DUMP_LOG_FILE_MASK, DbInfo::db_name, DbInfo::db_oid, ClusterInfo::dbarr, DbInfoArr::dbs, end_progress_output(), exec_prog(), GLOBALS_DUMP_FILE, log_opts, DbInfoArr::ndbs, new_cluster, NULL, old_cluster, parallel_exec_prog(), pg_log(), PG_STATUS, prep_status(), reap_child(), snprintf(), UTILITY_LOG_FILE, and LogOpts::verbose.

Referenced by check_and_dump_old_cluster().

{
    int         dbnum;

    prep_status("Creating dump of global objects");

    /* run new pg_dumpall binary for globals */
    exec_prog(UTILITY_LOG_FILE, NULL, true,
              "\"%s/pg_dumpall\" %s --schema-only --globals-only --binary-upgrade %s -f %s",
              new_cluster.bindir, cluster_conn_opts(&old_cluster),
              log_opts.verbose ? "--verbose" : "",
              GLOBALS_DUMP_FILE);
    check_ok();

    prep_status("Creating dump of database schemas\n");

    /* create per-db dump files */
    for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
    {
        char        sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH];
        DbInfo     *old_db = &old_cluster.dbarr.dbs[dbnum];

        pg_log(PG_STATUS, "%s", old_db->db_name);
        snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
        snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);

        parallel_exec_prog(log_file_name, NULL,
                  "\"%s/pg_dump\" %s --schema-only --binary-upgrade --format=custom %s --file=\"%s\" \"%s\"",
                  new_cluster.bindir, cluster_conn_opts(&old_cluster),
                  log_opts.verbose ? "--verbose" : "", sql_file_name, old_db->db_name);
    }

    /* reap all children */
    while (reap_child(true) == true)
        ;
                
    end_progress_output();
    check_ok();
}

void get_control_data ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 34 of file controldata.c.

References ControlData::align, ClusterInfo::bindir, ControlData::blocksz, ControlData::cat_ver, ControlData::chkpnt_nxtmulti, ControlData::chkpnt_nxtmxoff, ControlData::chkpnt_nxtoid, ControlData::chkpnt_nxtxid, ControlData::chkpnt_oldstMulti, ControlData::chkpnt_tli, CLUSTER_NAME, ClusterInfo::controldata, ControlData::ctrl_ver, ControlData::data_checksum_version, ControlData::date_is_int, ControlData::float8_pass_by_value, GET_MAJOR_VERSION, getErrorText(), ControlData::ident, ControlData::index, isascii, ControlData::largesz, ControlData::lc_collate, lc_collate, ControlData::lc_ctype, lc_ctype, lc_messages, lc_monetary, lc_numeric, lc_time, ClusterInfo::major_version, MULTIXACT_FORMATCHANGE_CAT_VER, ControlData::nextxlogfile, NULL, PG_FATAL, pg_free(), pg_log(), pg_putenv(), PG_REPORT, pg_strdup(), PG_VERBOSE, ClusterInfo::pgdata, snprintf(), str2uint(), strlcpy(), SYSTEMQUOTE, ControlData::toast, ControlData::walseg, and ControlData::walsz.

Referenced by check_cluster_compatibility().

{
    char        cmd[MAXPGPATH];
    char        bufin[MAX_STRING];
    FILE       *output;
    char       *p;
    bool        got_xid = false;
    bool        got_oid = false;
    bool        got_nextxlogfile = false;
    bool        got_multi = false;
    bool        got_mxoff = false;
    bool        got_oldestmulti = false;
    bool        got_log_id = false;
    bool        got_log_seg = false;
    bool        got_tli = false;
    bool        got_align = false;
    bool        got_blocksz = false;
    bool        got_largesz = false;
    bool        got_walsz = false;
    bool        got_walseg = false;
    bool        got_ident = false;
    bool        got_index = false;
    bool        got_toast = false;
    bool        got_date_is_int = false;
    bool        got_float8_pass_by_value = false;
    bool        got_data_checksum_version = false;
    char       *lc_collate = NULL;
    char       *lc_ctype = NULL;
    char       *lc_monetary = NULL;
    char       *lc_numeric = NULL;
    char       *lc_time = NULL;
    char       *lang = NULL;
    char       *language = NULL;
    char       *lc_all = NULL;
    char       *lc_messages = NULL;
    uint32      logid = 0;
    uint32      segno = 0;
    uint32      tli = 0;


    /*
     * Because we test the pg_resetxlog output as strings, it has to be in
     * English.  Copied from pg_regress.c.
     */
    if (getenv("LC_COLLATE"))
        lc_collate = pg_strdup(getenv("LC_COLLATE"));
    if (getenv("LC_CTYPE"))
        lc_ctype = pg_strdup(getenv("LC_CTYPE"));
    if (getenv("LC_MONETARY"))
        lc_monetary = pg_strdup(getenv("LC_MONETARY"));
    if (getenv("LC_NUMERIC"))
        lc_numeric = pg_strdup(getenv("LC_NUMERIC"));
    if (getenv("LC_TIME"))
        lc_time = pg_strdup(getenv("LC_TIME"));
    if (getenv("LANG"))
        lang = pg_strdup(getenv("LANG"));
    if (getenv("LANGUAGE"))
        language = pg_strdup(getenv("LANGUAGE"));
    if (getenv("LC_ALL"))
        lc_all = pg_strdup(getenv("LC_ALL"));
    if (getenv("LC_MESSAGES"))
        lc_messages = pg_strdup(getenv("LC_MESSAGES"));

    pg_putenv("LC_COLLATE", NULL);
    pg_putenv("LC_CTYPE", NULL);
    pg_putenv("LC_MONETARY", NULL);
    pg_putenv("LC_NUMERIC", NULL);
    pg_putenv("LC_TIME", NULL);
    pg_putenv("LANG",
#ifndef WIN32
              NULL);
#else
    /* On Windows the default locale cannot be English, so force it */
              "en");
#endif
    pg_putenv("LANGUAGE", NULL);
    pg_putenv("LC_ALL", NULL);
    pg_putenv("LC_MESSAGES", "C");

    snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
             cluster->bindir,
             live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
             cluster->pgdata);
    fflush(stdout);
    fflush(stderr);

    if ((output = popen(cmd, "r")) == NULL)
        pg_log(PG_FATAL, "Could not get control data using %s: %s\n",
               cmd, getErrorText(errno));

    /* Only pre-8.4 has these so if they are not set below we will check later */
    cluster->controldata.lc_collate = NULL;
    cluster->controldata.lc_ctype = NULL;

    /* Only in <= 8.3 */
    if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
    {
        cluster->controldata.float8_pass_by_value = false;
        got_float8_pass_by_value = true;
    }

    /* Only in <= 9.2 */
    if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
    {
        cluster->controldata.data_checksum_version = 0;
        got_data_checksum_version = true;
    }

    /* we have the result of cmd in "output". so parse it line by line now */
    while (fgets(bufin, sizeof(bufin), output))
    {
        pg_log(PG_VERBOSE, "%s", bufin);

#ifdef WIN32

        /*
         * Due to an installer bug, LANG=C doesn't work for PG 8.3.3, but does
         * work 8.2.6 and 8.3.7, so check for non-ASCII output and suggest a
         * minor upgrade.
         */
        if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
        {
            for (p = bufin; *p; p++)
                if (!isascii(*p))
                    pg_log(PG_FATAL,
                           "The 8.3 cluster's pg_controldata is incapable of outputting ASCII, even\n"
                           "with LANG=C.  You must upgrade this cluster to a newer version of PostgreSQL\n"
                           "8.3 to fix this bug.  PostgreSQL 8.3.7 and later are known to work properly.\n");
        }
#endif

        if ((p = strstr(bufin, "pg_control version number:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: pg_resetxlog problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.ctrl_ver = str2uint(p);
        }
        else if ((p = strstr(bufin, "Catalog version number:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.cat_ver = str2uint(p);
        }
        else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
        {
            /* Skip the colon and any whitespace after it */
            p = strchr(p, ':');
            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
            p = strpbrk(p, "01234567890ABCDEF");
            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            /* Make sure it looks like a valid WAL file name */
            if (strspn(p, "0123456789ABCDEF") != 24)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            strlcpy(cluster->controldata.nextxlogfile, p, 25);
            got_nextxlogfile = true;
        }
        else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            logid = str2uint(p);
            got_log_id = true;
        }
        else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            segno = str2uint(p);
            got_log_seg = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.chkpnt_tli = str2uint(p);
            got_tli = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
        {
            char       *op = strchr(p, '/');

            if (op == NULL)
                op = strchr(p, ':');

            if (op == NULL || strlen(op) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            op++;               /* removing ':' char */
            cluster->controldata.chkpnt_nxtxid = str2uint(op);
            got_xid = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.chkpnt_nxtoid = str2uint(p);
            got_oid = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's NextMultiXactId:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.chkpnt_nxtmulti = str2uint(p);
            got_multi = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's oldestMultiXid:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.chkpnt_oldstMulti = str2uint(p);
            got_oldestmulti = true;
        }
        else if ((p = strstr(bufin, "Latest checkpoint's NextMultiOffset:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
            got_mxoff = true;
        }
        else if ((p = strstr(bufin, "Maximum data alignment:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.align = str2uint(p);
            got_align = true;
        }
        else if ((p = strstr(bufin, "Database block size:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.blocksz = str2uint(p);
            got_blocksz = true;
        }
        else if ((p = strstr(bufin, "Blocks per segment of large relation:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.largesz = str2uint(p);
            got_largesz = true;
        }
        else if ((p = strstr(bufin, "WAL block size:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.walsz = str2uint(p);
            got_walsz = true;
        }
        else if ((p = strstr(bufin, "Bytes per WAL segment:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.walseg = str2uint(p);
            got_walseg = true;
        }
        else if ((p = strstr(bufin, "Maximum length of identifiers:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.ident = str2uint(p);
            got_ident = true;
        }
        else if ((p = strstr(bufin, "Maximum columns in an index:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.index = str2uint(p);
            got_index = true;
        }
        else if ((p = strstr(bufin, "Maximum size of a TOAST chunk:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.toast = str2uint(p);
            got_toast = true;
        }
        else if ((p = strstr(bufin, "Date/time type storage:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            cluster->controldata.date_is_int = strstr(p, "64-bit integers") != NULL;
            got_date_is_int = true;
        }
        else if ((p = strstr(bufin, "Float8 argument passing:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            /* used later for contrib check */
            cluster->controldata.float8_pass_by_value = strstr(p, "by value") != NULL;
            got_float8_pass_by_value = true;
        }
        else if ((p = strstr(bufin, "checksum")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            /* used later for contrib check */
            cluster->controldata.data_checksum_version = str2uint(p);
            got_data_checksum_version = true;
        }
        /* In pre-8.4 only */
        else if ((p = strstr(bufin, "LC_COLLATE:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            /* skip leading spaces and remove trailing newline */
            p += strspn(p, " ");
            if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
                *(p + strlen(p) - 1) = '\0';
            cluster->controldata.lc_collate = pg_strdup(p);
        }
        /* In pre-8.4 only */
        else if ((p = strstr(bufin, "LC_CTYPE:")) != NULL)
        {
            p = strchr(p, ':');

            if (p == NULL || strlen(p) <= 1)
                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);

            p++;                /* removing ':' char */
            /* skip leading spaces and remove trailing newline */
            p += strspn(p, " ");
            if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
                *(p + strlen(p) - 1) = '\0';
            cluster->controldata.lc_ctype = pg_strdup(p);
        }
    }

    if (output)
        pclose(output);

    /*
     * Restore environment variables
     */
    pg_putenv("LC_COLLATE", lc_collate);
    pg_putenv("LC_CTYPE", lc_ctype);
    pg_putenv("LC_MONETARY", lc_monetary);
    pg_putenv("LC_NUMERIC", lc_numeric);
    pg_putenv("LC_TIME", lc_time);
    pg_putenv("LANG", lang);
    pg_putenv("LANGUAGE", language);
    pg_putenv("LC_ALL", lc_all);
    pg_putenv("LC_MESSAGES", lc_messages);

    pg_free(lc_collate);
    pg_free(lc_ctype);
    pg_free(lc_monetary);
    pg_free(lc_numeric);
    pg_free(lc_time);
    pg_free(lang);
    pg_free(language);
    pg_free(lc_all);
    pg_free(lc_messages);

    /*
     * Before 9.3, pg_resetxlog reported the xlogid and segno of the first
     * log file after reset as separate lines. Starting with 9.3, it reports
     * the WAL file name. If the old cluster is older than 9.3, we construct
     * the WAL file name from the xlogid and segno.
     */
    if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
    {
        if (got_log_id && got_log_seg)
        {
            snprintf(cluster->controldata.nextxlogfile, 25, "%08X%08X%08X",
                     tli, logid, segno);
            got_nextxlogfile = true;
        }
    }

    /* verify that we got all the mandatory pg_control data */
    if (!got_xid || !got_oid ||
        !got_multi || !got_mxoff ||
        (!got_oldestmulti &&
         cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) ||
        (!live_check && !got_nextxlogfile) ||
        !got_tli ||
        !got_align || !got_blocksz || !got_largesz || !got_walsz ||
        !got_walseg || !got_ident || !got_index || !got_toast ||
        !got_date_is_int || !got_float8_pass_by_value || !got_data_checksum_version)
    {
        pg_log(PG_REPORT,
            "The %s cluster lacks some required control information:\n",
            CLUSTER_NAME(cluster));

        if (!got_xid)
            pg_log(PG_REPORT, "  checkpoint next XID\n");

        if (!got_oid)
            pg_log(PG_REPORT, "  latest checkpoint next OID\n");

        if (!got_multi)
            pg_log(PG_REPORT, "  latest checkpoint next MultiXactId\n");

        if (!got_mxoff)
            pg_log(PG_REPORT, "  latest checkpoint next MultiXactOffset\n");

        if (!got_oldestmulti &&
            cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
            pg_log(PG_REPORT, "  latest checkpoint oldest MultiXactId\n");

        if (!live_check && !got_nextxlogfile)
            pg_log(PG_REPORT, "  first WAL segment after reset\n");

        if (!got_tli)
            pg_log(PG_REPORT, "  latest checkpoint timeline ID\n");

        if (!got_align)
            pg_log(PG_REPORT, "  maximum alignment\n");

        if (!got_blocksz)
            pg_log(PG_REPORT, "  block size\n");

        if (!got_largesz)
            pg_log(PG_REPORT, "  large relation segment size\n");

        if (!got_walsz)
            pg_log(PG_REPORT, "  WAL block size\n");

        if (!got_walseg)
            pg_log(PG_REPORT, "  WAL segment size\n");

        if (!got_ident)
            pg_log(PG_REPORT, "  maximum identifier length\n");

        if (!got_index)
            pg_log(PG_REPORT, "  maximum number of indexed columns\n");

        if (!got_toast)
            pg_log(PG_REPORT, "  maximum TOAST chunk size\n");

        if (!got_date_is_int)
            pg_log(PG_REPORT, "  dates/times are integers?\n");

        /* value added in Postgres 8.4 */
        if (!got_float8_pass_by_value)
            pg_log(PG_REPORT, "  float8 argument passing method\n");

        /* value added in Postgres 9.3 */
        if (!got_data_checksum_version)
            pg_log(PG_REPORT, "  data checksum version\n");

        pg_log(PG_FATAL,
               "Cannot continue without required control information, terminating\n");
    }
}

void get_db_and_rel_infos ( ClusterInfo cluster  ) 

Definition at line 170 of file info.c.

References CLUSTER_NAME, ClusterInfo::dbarr, DbInfoArr::dbs, free_db_and_rel_infos(), get_db_infos(), get_rel_infos(), log_opts, DbInfoArr::ndbs, NULL, pg_log(), PG_VERBOSE, print_db_infos(), and LogOpts::verbose.

Referenced by check_and_dump_old_cluster(), check_new_cluster(), create_new_objects(), and prepare_new_databases().

{
    int         dbnum;

    if (cluster->dbarr.dbs != NULL)
        free_db_and_rel_infos(&cluster->dbarr);

    get_db_infos(cluster);

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
        get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]);

    pg_log(PG_VERBOSE, "\n%s databases:\n", CLUSTER_NAME(cluster));
    if (log_opts.verbose)
        print_db_infos(&cluster->dbarr);
}

void get_loadable_libraries ( void   ) 

Definition at line 130 of file function.c.

References conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), FirstNormalObjectId, GET_MAJOR_VERSION, OSInfo::libraries, ClusterInfo::major_version, DbInfoArr::ndbs, OSInfo::num_libraries, old_cluster, os_info, PG_FATAL, pg_free(), pg_log(), pg_malloc(), pg_strdup(), PG_UPGRADE_SUPPORT, PG_WARNING, PQclear(), PQfinish(), PQgetvalue(), and PQntuples().

Referenced by check_and_dump_old_cluster().

{
    PGresult  **ress;
    int         totaltups;
    int         dbnum;
    bool        found_public_plpython_handler = false;

    ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
    totaltups = 0;

    /* Fetch all library names, removing duplicates within each DB */
    for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
    {
        DbInfo     *active_db = &old_cluster.dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(&old_cluster, active_db->db_name);

        /*
         * Fetch all libraries referenced in this DB.  We can't exclude the
         * "pg_catalog" schema because, while such functions are not
         * explicitly dumped by pg_dump, they do reference implicit objects
         * that pg_dump does dump, e.g. CREATE LANGUAGE plperl.
         */
        ress[dbnum] = executeQueryOrDie(conn,
                                        "SELECT DISTINCT probin "
                                        "FROM   pg_catalog.pg_proc "
                                        "WHERE  prolang = 13 /* C */ AND "
                                        "probin IS NOT NULL AND "
                                        "oid >= %u;",
                                        FirstNormalObjectId);
        totaltups += PQntuples(ress[dbnum]);

        /*
         * Systems that install plpython before 8.1 have
         * plpython_call_handler() defined in the "public" schema, causing
         * pg_dumpall to dump it.  However that function still references
         * "plpython" (no "2"), so it throws an error on restore.  This code
         * checks for the problem function, reports affected databases to the
         * user and explains how to remove them. 8.1 git commit:
         * e0dedd0559f005d60c69c9772163e69c204bac69
         * http://archives.postgresql.org/pgsql-hackers/2012-03/msg01101.php
         * http://archives.postgresql.org/pgsql-bugs/2012-05/msg00206.php
         */
        if (GET_MAJOR_VERSION(old_cluster.major_version) < 901)
        {
            PGresult   *res;

            res = executeQueryOrDie(conn,
                                    "SELECT 1 "
                           "FROM    pg_catalog.pg_proc JOIN pg_namespace "
                             "      ON pronamespace = pg_namespace.oid "
                               "WHERE proname = 'plpython_call_handler' AND "
                                    "nspname = 'public' AND "
                                    "prolang = 13 /* C */ AND "
                                    "probin = '$libdir/plpython' AND "
                                    "pg_proc.oid >= %u;",
                                    FirstNormalObjectId);
            if (PQntuples(res) > 0)
            {
                if (!found_public_plpython_handler)
                {
                    pg_log(PG_WARNING,
                           "\nThe old cluster has a \"plpython_call_handler\" function defined\n"
                           "in the \"public\" schema which is a duplicate of the one defined\n"
                           "in the \"pg_catalog\" schema.  You can confirm this by executing\n"
                           "in psql:\n"
                           "\n"
                           "    \\df *.plpython_call_handler\n"
                           "\n"
                           "The \"public\" schema version of this function was created by a\n"
                           "pre-8.1 install of plpython, and must be removed for pg_upgrade\n"
                           "to complete because it references a now-obsolete \"plpython\"\n"
                           "shared object file.  You can remove the \"public\" schema version\n"
                       "of this function by running the following command:\n"
                           "\n"
                         "  DROP FUNCTION public.plpython_call_handler()\n"
                           "\n"
                           "in each affected database:\n"
                           "\n");
                }
                pg_log(PG_WARNING, "    %s\n", active_db->db_name);
                found_public_plpython_handler = true;
            }
            PQclear(res);
        }

        PQfinish(conn);
    }

    if (found_public_plpython_handler)
        pg_log(PG_FATAL,
         "Remove the problem functions from the old cluster to continue.\n");

    totaltups++;                /* reserve for pg_upgrade_support */

    /* Allocate what's certainly enough space */
    os_info.libraries = (char **) pg_malloc(totaltups * sizeof(char *));

    /*
     * Now remove duplicates across DBs.  This is pretty inefficient code, but
     * there probably aren't enough entries to matter.
     */
    totaltups = 0;
    os_info.libraries[totaltups++] = pg_strdup(PG_UPGRADE_SUPPORT);

    for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
    {
        PGresult   *res = ress[dbnum];
        int         ntups;
        int         rowno;

        ntups = PQntuples(res);
        for (rowno = 0; rowno < ntups; rowno++)
        {
            char       *lib = PQgetvalue(res, rowno, 0);
            bool        dup = false;
            int         n;

            for (n = 0; n < totaltups; n++)
            {
                if (strcmp(lib, os_info.libraries[n]) == 0)
                {
                    dup = true;
                    break;
                }
            }
            if (!dup)
                os_info.libraries[totaltups++] = pg_strdup(lib);
        }

        PQclear(res);
    }

    os_info.num_libraries = totaltups;

    pg_free(ress);
}

uint32 get_major_server_version ( ClusterInfo cluster  ) 

Definition at line 142 of file server.c.

References ClusterInfo::major_version_str, NULL, PG_FATAL, pg_log(), ClusterInfo::pgdata, and snprintf().

Referenced by check_cluster_versions().

{
    FILE       *version_fd;
    char        ver_filename[MAXPGPATH];
    int         integer_version = 0;
    int         fractional_version = 0;

    snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION",
             cluster->pgdata);
    if ((version_fd = fopen(ver_filename, "r")) == NULL)
        pg_log(PG_FATAL, "could not open version file: %s\n", ver_filename);

    if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
        sscanf(cluster->major_version_str, "%d.%d", &integer_version,
               &fractional_version) != 2)
        pg_log(PG_FATAL, "could not get version from %s\n", cluster->pgdata);

    fclose(version_fd);

    return (100 * integer_version + fractional_version) * 100;
}

void get_pg_database_relfilenode ( ClusterInfo cluster  ) 

Definition at line 139 of file relfilenode.c.

References atooid, conn, connectToServer(), executeQueryOrDie(), ClusterInfo::pg_database_oid, PQclear(), PQfinish(), PQfnumber(), and PQgetvalue().

Referenced by check_and_dump_old_cluster(), and prepare_new_cluster().

{
    PGconn     *conn = connectToServer(cluster, "template1");
    PGresult   *res;
    int         i_relfile;

    res = executeQueryOrDie(conn,
                            "SELECT c.relname, c.relfilenode "
                            "FROM   pg_catalog.pg_class c, "
                            "       pg_catalog.pg_namespace n "
                            "WHERE  c.relnamespace = n.oid AND "
                            "       n.nspname = 'pg_catalog' AND "
                            "       c.relname = 'pg_database' "
                            "ORDER BY c.relname");

    i_relfile = PQfnumber(res, "relfilenode");
    cluster->pg_database_oid = atooid(PQgetvalue(res, 0, i_relfile));

    PQclear(res);
    PQfinish(conn);
}

void get_sock_dir ( ClusterInfo cluster,
bool  live_check 
)

Definition at line 398 of file option.c.

References DEF_PGUPORT, filename, GET_MAJOR_VERSION, LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR, ClusterInfo::major_version, Max, MAXPGPATH, NULL, old_cluster, PG_FATAL, pg_log(), pg_malloc(), PG_WARNING, ClusterInfo::pgdata, ClusterInfo::port, snprintf(), and ClusterInfo::sockdir.

Referenced by main().

{
#ifdef HAVE_UNIX_SOCKETS
    /*
     *  sockdir and port were added to postmaster.pid in PG 9.1.
     *  Pre-9.1 cannot process pg_ctl -w for sockets in non-default
     *  locations.
     */
    if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
    {
        if (!live_check)
        {
            /* Use the current directory for the socket */
            cluster->sockdir = pg_malloc(MAXPGPATH);
            if (!getcwd(cluster->sockdir, MAXPGPATH))
                pg_log(PG_FATAL, "cannot find current directory\n");
        }
        else
        {
            /*
             *  If we are doing a live check, we will use the old cluster's Unix
             *  domain socket directory so we can connect to the live server.
             */
            unsigned short orig_port = cluster->port;
            char        filename[MAXPGPATH], line[MAXPGPATH];
            FILE        *fp;
            int         lineno;
    
            snprintf(filename, sizeof(filename), "%s/postmaster.pid",
                     cluster->pgdata);
            if ((fp = fopen(filename, "r")) == NULL)
                pg_log(PG_FATAL, "Cannot open file %s: %m\n", filename);
    
            for (lineno = 1;
                 lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR);
                 lineno++)
            {
                if (fgets(line, sizeof(line), fp) == NULL)
                    pg_log(PG_FATAL, "Cannot read line %d from %s: %m\n", lineno, filename);
    
                /* potentially overwrite user-supplied value */
                if (lineno == LOCK_FILE_LINE_PORT)
                    sscanf(line, "%hu", &old_cluster.port);
                if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
                {
                    cluster->sockdir = pg_malloc(MAXPGPATH);
                    /* strip off newline */
                    sscanf(line, "%s\n", cluster->sockdir);
                }
            }
            fclose(fp);
    
            /* warn of port number correction */
            if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
                pg_log(PG_WARNING, "User-supplied old port number %hu corrected to %hu\n",
                orig_port, cluster->port);
        }
    }
    else
        /* Can't get sockdir and pg_ctl -w can't use a non-default, use default */
        cluster->sockdir = NULL;

#else /* !HAVE_UNIX_SOCKETS */
    cluster->sockdir = NULL;
#endif
}

int get_user_info ( char **  user_name  ) 

Definition at line 188 of file util.c.

References pg_strdup().

Referenced by parseCommandLine().

{
    int         user_id;

#ifndef WIN32
    struct passwd *pw = getpwuid(geteuid());

    user_id = geteuid();
#else                           /* the windows code */
    struct passwd_win32
    {
        int         pw_uid;
        char        pw_name[128];
    }           pass_win32;
    struct passwd_win32 *pw = &pass_win32;
    DWORD       pwname_size = sizeof(pass_win32.pw_name) - 1;

    GetUserName(pw->pw_name, &pwname_size);

    user_id = 1;
#endif

    *user_name = pg_strdup(pw->pw_name);

    return user_id;
}

const char* getErrorText ( int  errNum  ) 
void init_tablespaces ( void   ) 
void install_support_functions_in_new_db ( const char *  db_name  ) 

Definition at line 25 of file function.c.

References conn, connectToServer(), executeQueryOrDie(), new_cluster, PQclear(), and PQfinish().

Referenced by create_new_objects(), and prepare_new_databases().

{
    PGconn     *conn = connectToServer(&new_cluster, db_name);

    /* suppress NOTICE of dropped objects */
    PQclear(executeQueryOrDie(conn,
                              "SET client_min_messages = warning;"));
    PQclear(executeQueryOrDie(conn,
                           "DROP SCHEMA IF EXISTS binary_upgrade CASCADE;"));
    PQclear(executeQueryOrDie(conn,
                              "RESET client_min_messages;"));

    PQclear(executeQueryOrDie(conn,
                              "CREATE SCHEMA binary_upgrade;"));

    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                              "binary_upgrade.set_next_pg_type_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                            "binary_upgrade.set_next_array_pg_type_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                            "binary_upgrade.set_next_toast_pg_type_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                            "binary_upgrade.set_next_heap_pg_class_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                           "binary_upgrade.set_next_index_pg_class_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                           "binary_upgrade.set_next_toast_pg_class_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                              "binary_upgrade.set_next_pg_enum_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                              "binary_upgrade.set_next_pg_authid_oid(OID) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C STRICT;"));
    PQclear(executeQueryOrDie(conn,
                              "CREATE OR REPLACE FUNCTION "
                              "binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
                              "RETURNS VOID "
                              "AS '$libdir/pg_upgrade_support' "
                              "LANGUAGE C;"));
    PQfinish(conn);
}

void issue_warnings ( char *  sequence_script_file_name  ) 
const char* linkAndUpdateFile ( pageCnvCtx pageConverter,
const char *  src,
const char *  dst 
)

Definition at line 113 of file file.c.

References getErrorText(), NULL, and pg_link_file.

Referenced by transfer_relfile().

{
    if (pageConverter != NULL)
        return "Cannot in-place update this cluster, page-by-page conversion is required";

    if (pg_link_file(src, dst) == -1)
        return getErrorText(errno);
    else
        return NULL;
}

void new_9_0_populate_pg_largeobject_metadata ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 22 of file version.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), getErrorText(), DbInfoArr::ndbs, NULL, PG_FATAL, pg_log(), PG_WARNING, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), prep_status(), quote_identifier(), report_status(), and snprintf().

Referenced by check_and_dump_old_cluster(), and issue_warnings().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for large objects");

    snprintf(output_path, sizeof(output_path), "pg_largeobject.sql");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        int         i_count;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* find if there are any large objects */
        res = executeQueryOrDie(conn,
                                "SELECT count(*) "
                                "FROM   pg_catalog.pg_largeobject ");

        i_count = PQfnumber(res, "count");
        if (atoi(PQgetvalue(res, 0, i_count)) != 0)
        {
            found = true;
            if (!check_mode)
            {
                if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                    pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
                fprintf(script, "\\connect %s\n",
                        quote_identifier(active_db->db_name));
                fprintf(script,
                        "SELECT pg_catalog.lo_create(t.loid)\n"
                        "FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) AS t;\n");
            }
        }

        PQclear(res);
        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        report_status(PG_WARNING, "warning");
        if (check_mode)
            pg_log(PG_WARNING, "\n"
                   "Your installation contains large objects.  The new database has an\n"
                   "additional large object permission table.  After upgrading, you will be\n"
                   "given a command to populate the pg_largeobject permission table with\n"
                   "default permissions.\n\n");
        else
            pg_log(PG_WARNING, "\n"
                   "Your installation contains large objects.  The new database has an\n"
                   "additional large object permission table, so default permissions must be\n"
                   "defined for all large objects.  The file\n"
                   "    %s\n"
                   "when executed by psql by the database superuser will set the default\n"
                   "permissions.\n\n",
                   output_path);
    }
    else
        check_ok();
}

void old_8_3_check_for_name_data_type_usage ( ClusterInfo cluster  ) 

Definition at line 24 of file version_old_8_3.c.

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

Referenced by check_and_dump_old_cluster().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for invalid \"name\" user columns");

    snprintf(output_path, sizeof(output_path), "tables_using_name.txt");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname,
                    i_attname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /*
         * With a smaller alignment in 8.4, 'name' cannot be used in a
         * non-pg_catalog table, except as the first column. (We could tighten
         * that condition with enough analysis, but it seems not worth the
         * trouble.)
         */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname, a.attname "
                                "FROM   pg_catalog.pg_class c, "
                                "       pg_catalog.pg_namespace n, "
                                "       pg_catalog.pg_attribute a "
                                "WHERE  c.oid = a.attrelid AND "
                                "       a.attnum > 1 AND "
                                "       NOT a.attisdropped AND "
                                "       a.atttypid = 'pg_catalog.name'::pg_catalog.regtype AND "
                                "       c.relnamespace = n.oid AND "
        /* exclude possible orphaned temp tables */
                                "       n.nspname !~ '^pg_temp_' AND "
                         "      n.nspname !~ '^pg_toast_temp_' AND "
                                "       n.nspname NOT IN ('pg_catalog', 'information_schema')");

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        i_attname = PQfnumber(res, "attname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
            if (!db_used)
            {
                fprintf(script, "Database: %s\n", active_db->db_name);
                db_used = true;
            }
            fprintf(script, "  %s.%s.%s\n",
                    PQgetvalue(res, rowno, i_nspname),
                    PQgetvalue(res, rowno, i_relname),
                    PQgetvalue(res, rowno, i_attname));
        }

        PQclear(res);

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        pg_log(PG_REPORT, "fatal\n");
        pg_log(PG_FATAL,
               "Your installation contains the \"name\" data type in user tables.  This\n"
        "data type changed its internal alignment between your old and new\n"
               "clusters so this cluster cannot currently be upgraded.  You can remove\n"
        "the problem tables and restart the upgrade.  A list of the problem\n"
               "columns is in the file:\n"
               "    %s\n\n", output_path);
    }
    else
        check_ok();
}

void old_8_3_check_for_tsquery_usage ( ClusterInfo cluster  ) 

Definition at line 119 of file version_old_8_3.c.

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

Referenced by check_and_dump_old_cluster().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for tsquery user columns");

    snprintf(output_path, sizeof(output_path), "tables_using_tsquery.txt");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname,
                    i_attname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* Find any user-defined tsquery columns */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname, a.attname "
                                "FROM   pg_catalog.pg_class c, "
                                "       pg_catalog.pg_namespace n, "
                                "       pg_catalog.pg_attribute a "
        /* materialized views didn't exist in 8.3, so no need to check 'm' */
                                "WHERE  c.relkind = 'r' AND "
                                "       c.oid = a.attrelid AND "
                                "       NOT a.attisdropped AND "
                                "       a.atttypid = 'pg_catalog.tsquery'::pg_catalog.regtype AND "
                                "       c.relnamespace = n.oid AND "
        /* exclude possible orphaned temp tables */
                                "       n.nspname !~ '^pg_temp_' AND "
                         "      n.nspname !~ '^pg_toast_temp_' AND "
                                "       n.nspname NOT IN ('pg_catalog', 'information_schema')");

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        i_attname = PQfnumber(res, "attname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
            if (!db_used)
            {
                fprintf(script, "Database: %s\n", active_db->db_name);
                db_used = true;
            }
            fprintf(script, "  %s.%s.%s\n",
                    PQgetvalue(res, rowno, i_nspname),
                    PQgetvalue(res, rowno, i_relname),
                    PQgetvalue(res, rowno, i_attname));
        }

        PQclear(res);

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        pg_log(PG_REPORT, "fatal\n");
        pg_log(PG_FATAL,
               "Your installation contains the \"tsquery\" data type.    This data type\n"
               "added a new internal field between your old and new clusters so this\n"
        "cluster cannot currently be upgraded.  You can remove the problem\n"
               "columns and restart the upgrade.  A list of the problem columns is in the\n"
               "file:\n"
               "    %s\n\n", output_path);
    }
    else
        check_ok();
}

void old_8_3_check_ltree_usage ( ClusterInfo cluster  ) 

Definition at line 209 of file version_old_8_3.c.

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

Referenced by check_and_dump_old_cluster().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for contrib/ltree");

    snprintf(output_path, sizeof(output_path), "contrib_ltree.txt");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_proname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* Find any functions coming from contrib/ltree */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, p.proname "
                                "FROM   pg_catalog.pg_proc p, "
                                "       pg_catalog.pg_namespace n "
                                "WHERE  p.pronamespace = n.oid AND "
                                "       p.probin = '$libdir/ltree'");

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_proname = PQfnumber(res, "proname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
                       output_path, getErrorText(errno));
            if (!db_used)
            {
                fprintf(script, "Database: %s\n", active_db->db_name);
                db_used = true;
            }
            fprintf(script, "  %s.%s\n",
                    PQgetvalue(res, rowno, i_nspname),
                    PQgetvalue(res, rowno, i_proname));
        }

        PQclear(res);

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        pg_log(PG_REPORT, "fatal\n");
        pg_log(PG_FATAL,
               "Your installation contains the \"ltree\" data type.  This data type\n"
               "changed its internal storage format between your old and new clusters so this\n"
               "cluster cannot currently be upgraded.  You can manually upgrade databases\n"
               "that use \"contrib/ltree\" facilities and remove \"contrib/ltree\" from the old\n"
               "cluster and restart the upgrade.  A list of the problem functions is in the\n"
               "file:\n"
               "    %s\n\n", output_path);
    }
    else
        check_ok();
}

char* old_8_3_create_sequence_script ( ClusterInfo cluster  ) 

Definition at line 676 of file version_old_8_3.c.

References assert, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), getErrorText(), MAXPGPATH, DbInfoArr::ndbs, NULL, PG_FATAL, pg_free(), pg_log(), pg_malloc(), PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), and snprintf().

Referenced by check_and_dump_old_cluster().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char       *output_path = pg_malloc(MAXPGPATH);

    snprintf(output_path, MAXPGPATH, "adjust_sequences.sql");

    prep_status("Creating script to adjust sequences");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* Find any sequences */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname "
                                "FROM   pg_catalog.pg_class c, "
                                "       pg_catalog.pg_namespace n "
                                "WHERE  c.relkind = 'S' AND "
                                "       c.relnamespace = n.oid AND "
        /* exclude possible orphaned temp tables */
                                "       n.nspname !~ '^pg_temp_' AND "
                         "      n.nspname !~ '^pg_toast_temp_' AND "
                                "       n.nspname NOT IN ('pg_catalog', 'information_schema')");

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            PGresult   *seq_res;
            int         i_last_value,
                        i_is_called;
            const char *nspname = PQgetvalue(res, rowno, i_nspname);
            const char *relname = PQgetvalue(res, rowno, i_relname);

            found = true;

            if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
            if (!db_used)
            {
                fprintf(script, "\\connect %s\n\n",
                        quote_identifier(active_db->db_name));
                db_used = true;
            }

            /* Find the desired sequence */
            seq_res = executeQueryOrDie(conn,
                                        "SELECT s.last_value, s.is_called "
                                        "FROM   %s.%s s",
                                        quote_identifier(nspname),
                                        quote_identifier(relname));

            assert(PQntuples(seq_res) == 1);
            i_last_value = PQfnumber(seq_res, "last_value");
            i_is_called = PQfnumber(seq_res, "is_called");

            fprintf(script, "SELECT setval('%s.%s', %s, '%s');\n",
                    quote_identifier(nspname), quote_identifier(relname),
                    PQgetvalue(seq_res, 0, i_last_value), PQgetvalue(seq_res, 0, i_is_called));
            PQclear(seq_res);
        }
        if (db_used)
            fprintf(script, "\n");

        PQclear(res);

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    check_ok();

    if (found)
        return output_path;
    else
    {
        pg_free(output_path);
        return NULL;
    }
}

void old_8_3_invalidate_bpchar_pattern_ops_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 547 of file version_old_8_3.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), getErrorText(), DbInfoArr::ndbs, NULL, PG_FATAL, pg_log(), PG_WARNING, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), report_status(), SKIP_TSVECTOR_TABLES, and snprintf().

Referenced by check_and_dump_old_cluster(), and issue_warnings().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for bpchar_pattern_ops indexes");

    snprintf(output_path, sizeof(output_path), "reindex_bpchar_ops.sql");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* find bpchar_pattern_ops indexes */

        /*
         * Do only non-hash, non-gin indexees;  we already invalidated them
         * above; no need to reindex twice
         */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname "
                                "FROM   pg_catalog.pg_index i, "
                                "       pg_catalog.pg_class c, "
                                "       pg_catalog.pg_namespace n "
                                "WHERE  indexrelid = c.oid AND "
                                "       c.relnamespace = n.oid AND "
                                "       ( "
                                "           SELECT  o.oid "
                   "            FROM    pg_catalog.pg_opclass o, "
                  "                 pg_catalog.pg_am a"
        "           WHERE   a.amname NOT IN ('hash', 'gin') AND "
            "                   a.oid = o.opcmethod AND "
                                "                   o.opcname = 'bpchar_pattern_ops') "
                                "       = ANY (i.indclass) AND "
                                SKIP_TSVECTOR_TABLES);

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (!check_mode)
            {
                if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                    pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
                if (!db_used)
                {
                    fprintf(script, "\\connect %s\n",
                            quote_identifier(active_db->db_name));
                    db_used = true;
                }
                fprintf(script, "REINDEX INDEX %s.%s;\n",
                        quote_identifier(PQgetvalue(res, rowno, i_nspname)),
                        quote_identifier(PQgetvalue(res, rowno, i_relname)));
            }
        }

        PQclear(res);

        if (!check_mode && found)
            /* mark bpchar_pattern_ops indexes as invalid */
            PQclear(executeQueryOrDie(conn,
                                      "UPDATE pg_catalog.pg_index i "
                                      "SET  indisvalid = false "
                                      "FROM pg_catalog.pg_class c, "
                                      "     pg_catalog.pg_namespace n "
                                      "WHERE    indexrelid = c.oid AND "
                                      "     c.relnamespace = n.oid AND "
                                      "     ( "
                                      "         SELECT  o.oid "
                         "          FROM    pg_catalog.pg_opclass o, "
                        "                   pg_catalog.pg_am a"
              "         WHERE   a.amname NOT IN ('hash', 'gin') AND "
                  "                 a.oid = o.opcmethod AND "
                                      "                 o.opcname = 'bpchar_pattern_ops') "
                                      "     = ANY (i.indclass)"));

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        report_status(PG_WARNING, "warning");
        if (check_mode)
            pg_log(PG_WARNING, "\n"
                   "Your installation contains indexes using \"bpchar_pattern_ops\".  These\n"
                   "indexes have different internal formats between your old and new clusters\n"
                   "so they must be reindexed with the REINDEX command.  After upgrading, you\n"
                   "will be given REINDEX instructions.\n\n");
        else
            pg_log(PG_WARNING, "\n"
                   "Your installation contains indexes using \"bpchar_pattern_ops\".  These\n"
                   "indexes have different internal formats between your old and new clusters\n"
            "so they must be reindexed with the REINDEX command.  The file:\n"
                   "    %s\n"
                   "when executed by psql by the database superuser will recreate all invalid\n"
              "indexes; until then, none of these indexes will be used.\n\n",
                   output_path);
    }
    else
        check_ok();
}

void old_8_3_invalidate_hash_gin_indexes ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 439 of file version_old_8_3.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), getErrorText(), DbInfoArr::ndbs, NULL, PG_FATAL, pg_log(), PG_WARNING, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), report_status(), SKIP_TSVECTOR_TABLES, and snprintf().

Referenced by check_and_dump_old_cluster(), and issue_warnings().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for hash and GIN indexes");

    snprintf(output_path, sizeof(output_path), "reindex_hash_and_gin.sql");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* find hash and gin indexes */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname "
                                "FROM   pg_catalog.pg_class c, "
                                "       pg_catalog.pg_index i, "
                                "       pg_catalog.pg_am a, "
                                "       pg_catalog.pg_namespace n "
                                "WHERE  i.indexrelid = c.oid AND "
                                "       c.relam = a.oid AND "
                                "       c.relnamespace = n.oid AND "
                            "       a.amname IN ('hash', 'gin') AND "
                                SKIP_TSVECTOR_TABLES);

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (!check_mode)
            {
                if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                    pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
                if (!db_used)
                {
                    fprintf(script, "\\connect %s\n",
                            quote_identifier(active_db->db_name));
                    db_used = true;
                }
                fprintf(script, "REINDEX INDEX %s.%s;\n",
                        quote_identifier(PQgetvalue(res, rowno, i_nspname)),
                        quote_identifier(PQgetvalue(res, rowno, i_relname)));
            }
        }

        PQclear(res);

        if (!check_mode && found)
            /* mark hash and gin indexes as invalid */
            PQclear(executeQueryOrDie(conn,
                                      "UPDATE pg_catalog.pg_index i "
                                      "SET  indisvalid = false "
                                      "FROM pg_catalog.pg_class c, "
                                      "     pg_catalog.pg_am a, "
                                      "     pg_catalog.pg_namespace n "
                                      "WHERE    i.indexrelid = c.oid AND "
                                      "     c.relam = a.oid AND "
                                      "     c.relnamespace = n.oid AND "
                                    "       a.amname IN ('hash', 'gin')"));

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        report_status(PG_WARNING, "warning");
        if (check_mode)
            pg_log(PG_WARNING, "\n"
                   "Your installation contains hash and/or GIN indexes.  These indexes have\n"
                   "different internal formats between your old and new clusters, so they\n"
                   "must be reindexed with the REINDEX command.  After upgrading, you will\n"
                   "be given REINDEX instructions.\n\n");
        else
            pg_log(PG_WARNING, "\n"
                   "Your installation contains hash and/or GIN indexes.  These indexes have\n"
                   "different internal formats between your old and new clusters, so they\n"
                   "must be reindexed with the REINDEX command.  The file:\n"
                   "    %s\n"
                   "when executed by psql by the database superuser will recreate all invalid\n"
              "indexes; until then, none of these indexes will be used.\n\n",
                   output_path);
    }
    else
        check_ok();
}

void old_8_3_rebuild_tsvector_tables ( ClusterInfo cluster,
bool  check_mode 
)

Definition at line 296 of file version_old_8_3.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), fopen_priv(), getErrorText(), DbInfoArr::ndbs, NULL, PG_FATAL, pg_log(), PG_WARNING, PQclear(), PQfinish(), PQfnumber(), PQgetvalue(), PQntuples(), prep_status(), quote_identifier(), report_status(), snprintf(), and strlcpy().

Referenced by check_and_dump_old_cluster(), and issue_warnings().

{
    int         dbnum;
    FILE       *script = NULL;
    bool        found = false;
    char        output_path[MAXPGPATH];

    prep_status("Checking for tsvector user columns");

    snprintf(output_path, sizeof(output_path), "rebuild_tsvector_tables.sql");

    for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
    {
        PGresult   *res;
        bool        db_used = false;
        char        nspname[NAMEDATALEN] = "",
                    relname[NAMEDATALEN] = "";
        int         ntups;
        int         rowno;
        int         i_nspname,
                    i_relname,
                    i_attname;
        DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(cluster, active_db->db_name);

        /* Find any user-defined tsvector columns */
        res = executeQueryOrDie(conn,
                                "SELECT n.nspname, c.relname, a.attname "
                                "FROM   pg_catalog.pg_class c, "
                                "       pg_catalog.pg_namespace n, "
                                "       pg_catalog.pg_attribute a "
        /* materialized views didn't exist in 8.3, so no need to check 'm' */
                                "WHERE  c.relkind = 'r' AND "
                                "       c.oid = a.attrelid AND "
                                "       NOT a.attisdropped AND "
                                "       a.atttypid = 'pg_catalog.tsvector'::pg_catalog.regtype AND "
                                "       c.relnamespace = n.oid AND "
        /* exclude possible orphaned temp tables */
                                "       n.nspname !~ '^pg_temp_' AND "
                         "      n.nspname !~ '^pg_toast_temp_' AND "
                                "       n.nspname NOT IN ('pg_catalog', 'information_schema')");

/*
 *  This macro is used below to avoid reindexing indexes already rebuilt
 *  because of tsvector columns.
 */
#define SKIP_TSVECTOR_TABLES \
                                "i.indrelid NOT IN ( "                  \
                                "SELECT DISTINCT c.oid "                \
                                "FROM   pg_catalog.pg_class c, "        \
                                "       pg_catalog.pg_namespace n, "    \
                                "       pg_catalog.pg_attribute a "     \
        /* materialized views didn't exist in 8.3, so no need to check 'm' */ \
                                "WHERE  c.relkind = 'r' AND "           \
                                "       c.oid = a.attrelid AND "        \
                                "       NOT a.attisdropped AND "        \
                                "       a.atttypid = 'pg_catalog.tsvector'::pg_catalog.regtype AND " \
                                "       c.relnamespace = n.oid AND "    \
                                "       n.nspname !~ '^pg_' AND "       \
                                "       n.nspname != 'information_schema') "

        ntups = PQntuples(res);
        i_nspname = PQfnumber(res, "nspname");
        i_relname = PQfnumber(res, "relname");
        i_attname = PQfnumber(res, "attname");
        for (rowno = 0; rowno < ntups; rowno++)
        {
            found = true;
            if (!check_mode)
            {
                if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
                    pg_log(PG_FATAL, "could not open file \"%s\": %s\n", output_path, getErrorText(errno));
                if (!db_used)
                {
                    fprintf(script, "\\connect %s\n\n",
                            quote_identifier(active_db->db_name));
                    db_used = true;
                }

                /* Rebuild all tsvector collumns with one ALTER TABLE command */
                if (strcmp(PQgetvalue(res, rowno, i_nspname), nspname) != 0 ||
                    strcmp(PQgetvalue(res, rowno, i_relname), relname) != 0)
                {
                    if (strlen(nspname) != 0 || strlen(relname) != 0)
                        fprintf(script, ";\n\n");
                    fprintf(script, "ALTER TABLE %s.%s\n",
                         quote_identifier(PQgetvalue(res, rowno, i_nspname)),
                        quote_identifier(PQgetvalue(res, rowno, i_relname)));
                }
                else
                    fprintf(script, ",\n");
                strlcpy(nspname, PQgetvalue(res, rowno, i_nspname), sizeof(nspname));
                strlcpy(relname, PQgetvalue(res, rowno, i_relname), sizeof(relname));

                fprintf(script, "ALTER COLUMN %s "
                /* This could have been a custom conversion function call. */
                        "TYPE pg_catalog.tsvector USING %s::pg_catalog.text::pg_catalog.tsvector",
                        quote_identifier(PQgetvalue(res, rowno, i_attname)),
                        quote_identifier(PQgetvalue(res, rowno, i_attname)));
            }
        }
        if (strlen(nspname) != 0 || strlen(relname) != 0)
            fprintf(script, ";\n\n");

        PQclear(res);

        /* XXX Mark tables as not accessible somehow */

        PQfinish(conn);
    }

    if (script)
        fclose(script);

    if (found)
    {
        report_status(PG_WARNING, "warning");
        if (check_mode)
            pg_log(PG_WARNING, "\n"
                   "Your installation contains tsvector columns.  The tsvector internal\n"
                   "storage format changed between your old and new clusters so the tables\n"
                   "must be rebuilt.  After upgrading, you will be given instructions.\n\n");
        else
            pg_log(PG_WARNING, "\n"
                   "Your installation contains tsvector columns.  The tsvector internal\n"
                   "storage format changed between your old and new clusters so the tables\n"
                   "must be rebuilt.  The file:\n"
                   "    %s\n"
                   "when executed by psql by the database superuser will rebuild all tables\n"
                   "with tsvector columns.\n\n",
                   output_path);
    }
    else
        check_ok();
}

void output_check_banner ( bool  live_check  ) 

Definition at line 58 of file check.c.

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

Referenced by main().

{
    if (user_opts.check && live_check)
    {
        pg_log(PG_REPORT, "Performing Consistency Checks on Old Live Server\n");
        pg_log(PG_REPORT, "------------------------------------------------\n");
    }
    else
    {
        pg_log(PG_REPORT, "Performing Consistency Checks\n");
        pg_log(PG_REPORT, "-----------------------------\n");
    }
}

void output_completion_banner ( char *  analyze_script_file_name,
char *  deletion_script_file_name 
)

Definition at line 232 of file check.c.

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

Referenced by main().

{
    /* Did we copy the free space files? */
    if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
        pg_log(PG_REPORT,
               "Optimizer statistics are not transferred by pg_upgrade so,\n"
               "once you start the new server, consider running:\n"
               "    %s\n\n", analyze_script_file_name);
    else
        pg_log(PG_REPORT,
               "Optimizer statistics and free space information are not transferred\n"
        "by pg_upgrade so, once you start the new server, consider running:\n"
               "    %s\n\n", analyze_script_file_name);


    if (deletion_script_file_name)
        pg_log(PG_REPORT,
               "Running this script will delete the old cluster's data files:\n"
               "    %s\n",
               deletion_script_file_name);
    else
        pg_log(PG_REPORT,
               "Could not create a script to delete the old cluster's data\n"
               "files because user-defined tablespaces exist in the old cluster\n"
               "directory.  The old cluster's contents must be deleted manually.\n");
}

void parallel_exec_prog ( const char *  log_file,
const char *  opt_log_file,
const char *  fmt,
  ... 
)
void void parallel_transfer_all_new_dbs ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata,
char *  old_tablespace 
)

Definition at line 170 of file parallel.c.

References i, UserOpts::jobs, NULL, parallel_jobs, PG_FATAL, pg_log(), pg_malloc(), reap_child(), strerror(), transfer_all_new_dbs(), and user_opts.

Referenced by transfer_all_new_tablespaces().

{
#ifndef WIN32
    pid_t       child;
#else
    HANDLE      child;
    transfer_thread_arg *new_arg;
#endif

    if (user_opts.jobs <= 1)
        /* throw_error must be true to allow jobs */
        transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata, NULL);
    else
    {
        /* parallel */
#ifdef WIN32
        cur_thread_args = (void **)transfer_thread_args;
#endif
        /* harvest any dead children */
        while (reap_child(false) == true)
            ;

        /* must we wait for a dead child? */
        if (parallel_jobs >= user_opts.jobs)
            reap_child(true);
            
        /* set this before we start the job */
        parallel_jobs++;
    
        /* Ensure stdio state is quiesced before forking */
        fflush(NULL);

#ifndef WIN32
        child = fork();
        if (child == 0)
        {
            transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, new_pgdata,
                                 old_tablespace);
            /* if we take another exit path, it will be non-zero */
            /* use _exit to skip atexit() functions */
            _exit(0);
        }
        else if (child < 0)
            /* fork failed */
            pg_log(PG_FATAL, "could not create worker process: %s\n", strerror(errno));
#else
        if (thread_handles == NULL)
        {
            int i;

            thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
            transfer_thread_args = pg_malloc(user_opts.jobs * sizeof(transfer_thread_arg *));

            /*
             *  For safety and performance, we keep the args allocated during
             *  the entire life of the process, and we don't free the args
             *  in a thread different from the one that allocated it.
             */
            for (i = 0; i < user_opts.jobs; i++)
                transfer_thread_args[i] = pg_malloc(sizeof(transfer_thread_arg));
        }

        /* use first empty array element */
        new_arg = transfer_thread_args[parallel_jobs-1];

        /* Can only pass one pointer into the function, so use a struct */
        new_arg->old_db_arr = old_db_arr;
        new_arg->new_db_arr = new_db_arr;
        strcpy(new_arg->old_pgdata, old_pgdata);
        strcpy(new_arg->new_pgdata, new_pgdata);
        strcpy(new_arg->old_tablespace, old_tablespace);

        child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog,
                        new_arg, 0, NULL);
        if (child == 0)
            pg_log(PG_FATAL, "could not create worker thread: %s\n", strerror(errno));

        thread_handles[parallel_jobs-1] = child;
#endif
    }

    return;
}

void parseCommandLine ( int  argc,
char *  argv[] 
)

Definition at line 39 of file option.c.

References ClusterInfo::bindir, UserOpts::check, check_required_directory(), filename, fopen_priv(), get_progname(), get_user_info(), getopt_long(), LogOpts::internal, INTERNAL_LOG_FILE, UserOpts::jobs, log_opts, new_cluster, NULL, old_cluster, optarg, os_info, output_files, PG_FATAL, pg_free(), pg_log(), pg_putenv(), PG_REPORT, pg_strdup(), ClusterInfo::pgconfig, ClusterInfo::pgdata, ClusterInfo::pgopts, ClusterInfo::port, OSInfo::progname, LogOpts::retain, UserOpts::transfer_mode, usage(), OSInfo::user, and LogOpts::verbose.

Referenced by main().

{
    static struct option long_options[] = {
        {"old-datadir", required_argument, NULL, 'd'},
        {"new-datadir", required_argument, NULL, 'D'},
        {"old-bindir", required_argument, NULL, 'b'},
        {"new-bindir", required_argument, NULL, 'B'},
        {"old-options", required_argument, NULL, 'o'},
        {"new-options", required_argument, NULL, 'O'},
        {"old-port", required_argument, NULL, 'p'},
        {"new-port", required_argument, NULL, 'P'},

        {"user", required_argument, NULL, 'u'},
        {"check", no_argument, NULL, 'c'},
        {"link", no_argument, NULL, 'k'},
        {"retain", no_argument, NULL, 'r'},
        {"jobs", required_argument, NULL, 'j'},
        {"verbose", no_argument, NULL, 'v'},
        {NULL, 0, NULL, 0}
    };
    int         option;         /* Command line option */
    int         optindex = 0;   /* used by getopt_long */
    int         os_user_effective_id;
    FILE       *fp;
    char      **filename;
    time_t      run_time = time(NULL);

    user_opts.transfer_mode = TRANSFER_MODE_COPY;

    os_info.progname = get_progname(argv[0]);

    /* Process libpq env. variables; load values here for usage() output */
    old_cluster.port = getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT;
    new_cluster.port = getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT;

    os_user_effective_id = get_user_info(&os_info.user);
    /* we override just the database user name;  we got the OS id above */
    if (getenv("PGUSER"))
    {
        pg_free(os_info.user);
        /* must save value, getenv()'s pointer is not stable */
        os_info.user = pg_strdup(getenv("PGUSER"));
    }

    if (argc > 1)
    {
        if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
            strcmp(argv[1], "-?") == 0)
        {
            usage();
            exit(0);
        }
        if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
        {
            puts("pg_upgrade (PostgreSQL) " PG_VERSION);
            exit(0);
        }
    }

    /* Allow help and version to be run as root, so do the test here. */
    if (os_user_effective_id == 0)
        pg_log(PG_FATAL, "%s: cannot be run as root\n", os_info.progname);

    if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
        pg_log(PG_FATAL, "cannot write to log file %s\n", INTERNAL_LOG_FILE);

    while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:ru:v",
                                 long_options, &optindex)) != -1)
    {
        switch (option)
        {
            case 'b':
                old_cluster.bindir = pg_strdup(optarg);
                break;

            case 'B':
                new_cluster.bindir = pg_strdup(optarg);
                break;

            case 'c':
                user_opts.check = true;
                break;

            case 'd':
                old_cluster.pgdata = pg_strdup(optarg);
                old_cluster.pgconfig = pg_strdup(optarg);
                break;

            case 'D':
                new_cluster.pgdata = pg_strdup(optarg);
                new_cluster.pgconfig = pg_strdup(optarg);
                break;

            case 'j':
                user_opts.jobs = atoi(optarg);
                break;

            case 'k':
                user_opts.transfer_mode = TRANSFER_MODE_LINK;
                break;

            case 'o':
                old_cluster.pgopts = pg_strdup(optarg);
                break;

            case 'O':
                new_cluster.pgopts = pg_strdup(optarg);
                break;

                /*
                 * Someday, the port number option could be removed and passed
                 * using -o/-O, but that requires postmaster -C to be
                 * supported on all old/new versions.
                 */
            case 'p':
                if ((old_cluster.port = atoi(optarg)) <= 0)
                {
                    pg_log(PG_FATAL, "invalid old port number\n");
                    exit(1);
                }
                break;

            case 'P':
                if ((new_cluster.port = atoi(optarg)) <= 0)
                {
                    pg_log(PG_FATAL, "invalid new port number\n");
                    exit(1);
                }
                break;

            case 'r':
                log_opts.retain = true;
                break;

            case 'u':
                pg_free(os_info.user);
                os_info.user = pg_strdup(optarg);

                /*
                 * Push the user name into the environment so pre-9.1
                 * pg_ctl/libpq uses it.
                 */
                pg_putenv("PGUSER", os_info.user);
                break;

            case 'v':
                pg_log(PG_REPORT, "Running in verbose mode\n");
                log_opts.verbose = true;
                break;

            default:
                pg_log(PG_FATAL,
                       "Try \"%s --help\" for more information.\n",
                       os_info.progname);
                break;
        }
    }

    /* label start of upgrade in logfiles */
    for (filename = output_files; *filename != NULL; filename++)
    {
        if ((fp = fopen_priv(*filename, "a")) == NULL)
            pg_log(PG_FATAL, "cannot write to log file %s\n", *filename);

        /* Start with newline because we might be appending to a file. */
        fprintf(fp, "\n"
        "-----------------------------------------------------------------\n"
                "  pg_upgrade run on %s"
                "-----------------------------------------------------------------\n\n",
                ctime(&run_time));
        fclose(fp);
    }

    /* Get values from env if not already set */
    check_required_directory(&old_cluster.bindir, NULL, "PGBINOLD", "-b",
                             "old cluster binaries reside");
    check_required_directory(&new_cluster.bindir, NULL, "PGBINNEW", "-B",
                             "new cluster binaries reside");
    check_required_directory(&old_cluster.pgdata, &old_cluster.pgconfig,
                             "PGDATAOLD", "-d", "old cluster data resides");
    check_required_directory(&new_cluster.pgdata, &new_cluster.pgconfig,
                             "PGDATANEW", "-D", "new cluster data resides");
}

void void pg_log ( eLogType  type,
char *  fmt,
  ... 
)

Referenced by adjust_data_dir(), check_cluster_compatibility(), check_cluster_versions(), check_control_data(), check_for_isn_and_int8_passing_mismatch(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_hard_link(), check_is_super_user(), check_loadable_libraries(), check_locale_and_encoding(), check_new_cluster(), check_new_cluster_is_empty(), check_pghost_envvar(), check_required_directory(), connectToServer(), copy_subdir_files(), create_new_objects(), create_script_for_cluster_analyze(), create_script_for_old_cluster_deletion(), disable_old_cluster(), exec_prog(), executeQueryOrDie(), gen_db_file_maps(), generate_old_dump(), get_bin_version(), get_canonical_locale_name(), get_control_data(), get_db_and_rel_infos(), get_loadable_libraries(), get_major_server_version(), get_sock_dir(), init_tablespaces(), main(), new_9_0_populate_pg_largeobject_metadata(), old_8_3_check_for_name_data_type_usage(), old_8_3_check_for_tsquery_usage(), old_8_3_check_ltree_usage(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), output_check_banner(), output_completion_banner(), parallel_exec_prog(), parallel_transfer_all_new_dbs(), parseCommandLine(), pid_lock_file_exists(), prep_status(), print_db_infos(), print_maps(), print_rel_infos(), reap_child(), report_clusters_compatible(), report_status(), setup(), start_postmaster(), transfer_all_new_dbs(), transfer_all_new_tablespaces(), transfer_relfile(), validate_exec(), and verify_directories().

void pg_putenv ( const char *  var,
const char *  val 
)

Definition at line 253 of file util.c.

References pg_malloc(), putenv, and unsetenv.

Referenced by get_control_data(), and parseCommandLine().

{
    if (val)
    {
#ifndef WIN32
        char       *envstr = (char *) pg_malloc(strlen(var) +
                                                strlen(val) + 2);

        sprintf(envstr, "%s=%s", var, val);
        putenv(envstr);

        /*
         * Do not free envstr because it becomes part of the environment on
         * some operating systems.  See port/unsetenv.c::unsetenv.
         */
#else
        SetEnvironmentVariableA(var, val);
#endif
    }
    else
    {
#ifndef WIN32
        unsetenv(var);
#else
        SetEnvironmentVariableA(var, "");
#endif
    }
}

bool pid_lock_file_exists ( const char *  datadir  ) 

Definition at line 148 of file exec.c.

References close, getErrorText(), PG_FATAL, pg_log(), and snprintf().

Referenced by setup().

{
    char        path[MAXPGPATH];
    int         fd;

    snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);

    if ((fd = open(path, O_RDONLY, 0)) < 0)
    {
        /* ENOTDIR means we will throw a more useful error later */
        if (errno != ENOENT && errno != ENOTDIR)
            pg_log(PG_FATAL, "could not open file \"%s\" for reading: %s\n",
                   path, getErrorText(errno));

        return false;
    }

    close(fd);
    return true;
}

void prep_status ( const char *  fmt,
  ... 
)
void print_maps ( FileNameMap maps,
int  n,
const char *  db_name 
)

Definition at line 144 of file info.c.

References log_opts, pg_log(), PG_VERBOSE, and LogOpts::verbose.

Referenced by transfer_all_new_dbs().

{
    if (log_opts.verbose)
    {
        int         mapnum;

        pg_log(PG_VERBOSE, "mappings for database \"%s\":\n", db_name);

        for (mapnum = 0; mapnum < n_maps; mapnum++)
            pg_log(PG_VERBOSE, "%s.%s: %u to %u\n",
                   maps[mapnum].nspname, maps[mapnum].relname,
                   maps[mapnum].old_relfilenode,
                   maps[mapnum].new_relfilenode);

        pg_log(PG_VERBOSE, "\n\n");
    }
}

char* quote_identifier ( const char *  s  ) 

Definition at line 163 of file util.c.

Referenced by ConvertTriggerToFK(), decompile_column_index_array(), deparseAnalyzeSql(), deparseColumnRef(), deparseFuncExpr(), deparseOperatorName(), deparseRelation(), execute_extension_script(), explain_get_index_name(), ExplainTargetRel(), flatten_set_variable_args(), format_operator_internal(), generate_operator_name(), get_column_alias_list(), get_delete_query_def(), get_from_clause_coldeflist(), get_from_clause_item(), get_insert_query_def(), get_opclass_name(), get_rule_expr(), get_rule_windowclause(), get_rule_windowspec(), get_select_query_def(), get_target_list(), get_update_query_def(), get_utility_query_def(), get_variable(), get_windowfunc_expr(), get_with_clause(), getObjectIdentity(), make_ruledef(), NameListToQuotedString(), new_9_0_populate_pg_largeobject_metadata(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), pg_get_constraintdef_worker(), pg_get_functiondef(), pg_get_indexdef_worker(), pg_get_triggerdef_worker(), pg_identify_object(), PLy_quote_ident(), print_function_arguments(), processIndirection(), quote_ident(), quote_object_name(), quote_qualified_identifier(), regoperout(), ri_add_cast_to(), ri_GenerateQual(), sepgsql_attribute_post_create(), sepgsql_database_post_create(), sepgsql_relation_post_create(), sepgsql_schema_post_create(), serialize_deflist(), text_format_string_conversion(), and worker_spi_main().

{
    char       *result = pg_malloc(strlen(s) * 2 + 3);
    char       *r = result;

    *r++ = '"';
    while (*s)
    {
        if (*s == '"')
            *r++ = *s;
        *r++ = *s;
        s++;
    }
    *r++ = '"';
    *r++ = '\0';

    return result;
}

bool reap_child ( bool  wait_for_child  ) 

Definition at line 274 of file parallel.c.

References UserOpts::jobs, parallel_jobs, PG_FATAL, pg_log(), strerror(), user_opts, WEXITSTATUS, and WIFEXITED.

Referenced by create_new_objects(), generate_old_dump(), parallel_exec_prog(), parallel_transfer_all_new_dbs(), and transfer_all_new_tablespaces().

{
#ifndef WIN32
    int work_status;
    int ret;
#else
    int             thread_num;
    DWORD           res;
#endif

    if (user_opts.jobs <= 1 || parallel_jobs == 0)
        return false;

#ifndef WIN32
    ret = waitpid(-1, &work_status, wait_for_child ? 0 : WNOHANG);

    /* no children or, for WNOHANG, no dead children */
    if (ret <= 0 || !WIFEXITED(work_status))
        return false;

    if (WEXITSTATUS(work_status) != 0)
        pg_log(PG_FATAL, "child worker exited abnormally: %s\n", strerror(errno));

#else
    /* wait for one to finish */
    thread_num = WaitForMultipleObjects(parallel_jobs, thread_handles,
                    false, wait_for_child ? INFINITE : 0);

    if (thread_num == WAIT_TIMEOUT || thread_num == WAIT_FAILED)
        return false;

    /* compute thread index in active_threads */
    thread_num -= WAIT_OBJECT_0;
    
    /* get the result */
    GetExitCodeThread(thread_handles[thread_num], &res);
    if (res != 0)
        pg_log(PG_FATAL, "child worker exited abnormally: %s\n", strerror(errno));

    /* dispose of handle to stop leaks */
    CloseHandle(thread_handles[thread_num]);

    /*  Move last slot into dead child's position */
    if (thread_num != parallel_jobs - 1)
    {
        void *tmp_args;
    
        thread_handles[thread_num] = thread_handles[parallel_jobs - 1];

        /*
         *  We must swap the arg struct pointers because the thread we
         *  just moved is active, and we must make sure it is not
         *  reused by the next created thread.  Instead, the new thread
         *  will use the arg struct of the thread that just died.
         */
        tmp_args = cur_thread_args[thread_num];
        cur_thread_args[thread_num] = cur_thread_args[parallel_jobs - 1];
        cur_thread_args[parallel_jobs - 1] = tmp_args;
    }
#endif

    /* do this after job has been removed */
    parallel_jobs--;

    return true;
}

void report_clusters_compatible ( void   ) 

Definition at line 179 of file check.c.

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

Referenced by main().

{
    if (user_opts.check)
    {
        pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
        /* stops new cluster */
        stop_postmaster(false);
        exit(0);
    }

    pg_log(PG_REPORT, "\n"
           "If pg_upgrade fails after this point, you must re-initdb the\n"
           "new cluster before continuing.\n");
}

void report_status ( eLogType  type,
const char *  fmt,
  ... 
)
bool start_postmaster ( ClusterInfo cluster,
bool  throw_error 
)

Definition at line 174 of file server.c.

References BINARY_UPGRADE_SERVER_FLAG_CAT_VER, ClusterInfo::bindir, ControlData::cat_ver, CLUSTER_NAME, conn, CONNECTION_OK, ClusterInfo::controldata, exec_prog(), get_db_conn(), GET_MAJOR_VERSION, ClusterInfo::major_version, MAXPGPATH, new_cluster, NULL, os_info, PG_FATAL, pg_log(), PG_REPORT, ClusterInfo::pgconfig, ClusterInfo::pgopts, ClusterInfo::port, PQerrorMessage(), PQfinish(), PQstatus(), OSInfo::running_cluster, SERVER_LOG_FILE, SERVER_START_LOG_FILE, snprintf(), ClusterInfo::sockdir, and stop_postmaster_atexit().

Referenced by check_and_dump_old_cluster(), do_start(), issue_warnings(), main(), and setup().

{
    char        cmd[MAXPGPATH * 4 + 1000];
    PGconn     *conn;
    bool        exit_hook_registered = false;
    bool        pg_ctl_return = false;
    char        socket_string[MAXPGPATH + 200];

    if (!exit_hook_registered)
    {
        atexit(stop_postmaster_atexit);
        exit_hook_registered = true;
    }

    socket_string[0] = '\0';

#ifdef HAVE_UNIX_SOCKETS
    /* prevent TCP/IP connections, restrict socket access */
    strcat(socket_string,
           " -c listen_addresses='' -c unix_socket_permissions=0700");

    /* Have a sockdir?  Tell the postmaster. */
    if (cluster->sockdir)
        snprintf(socket_string + strlen(socket_string),
                 sizeof(socket_string) - strlen(socket_string),
                 " -c %s='%s'",
                 (GET_MAJOR_VERSION(cluster->major_version) < 903) ?
                 "unix_socket_directory" : "unix_socket_directories",
                 cluster->sockdir);
#endif

    /*
     * Using autovacuum=off disables cleanup vacuum and analyze, but freeze
     * vacuums can still happen, so we set autovacuum_freeze_max_age to its
     * maximum.  We assume all datfrozenxid and relfrozen values are less than
     * a gap of 2000000000 from the current xid counter, so autovacuum will
     * not touch them.
     *
     * Turn off durability requirements to improve object creation speed, and
     * we only modify the new cluster, so only use it there.  If there is a
     * crash, the new cluster has to be recreated anyway.  fsync=off is a big
     * win on ext4.
     */
    snprintf(cmd, sizeof(cmd),
             "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start",
          cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
             (cluster->controldata.cat_ver >=
              BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" :
             " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
             (cluster == &new_cluster) ?
                " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
             cluster->pgopts ? cluster->pgopts : "", socket_string);

    /*
     * Don't throw an error right away, let connecting throw the error because
     * it might supply a reason for the failure.
     */
    pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
                              /* pass both file names if they differ */
                              (strcmp(SERVER_LOG_FILE,
                                      SERVER_START_LOG_FILE) != 0) ?
                              SERVER_LOG_FILE : NULL,
                              false,
                              "%s", cmd);

    if (!pg_ctl_return && !throw_error)
        return false;
                              
    /* Check to see if we can connect to the server; if not, report it. */
    if ((conn = get_db_conn(cluster, "template1")) == NULL ||
        PQstatus(conn) != CONNECTION_OK)
    {
        pg_log(PG_REPORT, "\nconnection to database failed: %s\n",
               PQerrorMessage(conn));
        if (conn)
            PQfinish(conn);
        pg_log(PG_FATAL, "could not connect to %s postmaster started with the command:\n"
               "%s\n",
               CLUSTER_NAME(cluster), cmd);
    }
    PQfinish(conn);

    /* If the connection didn't fail, fail now */
    if (!pg_ctl_return)
        pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
               CLUSTER_NAME(cluster));

    os_info.running_cluster = cluster;

    return true;
}

void stop_postmaster ( bool  fast  ) 

Definition at line 268 of file server.c.

References ClusterInfo::bindir, exec_prog(), new_cluster, NULL, old_cluster, os_info, ClusterInfo::pgconfig, ClusterInfo::pgopts, OSInfo::running_cluster, and SERVER_STOP_LOG_FILE.

Referenced by check_and_dump_old_cluster(), issue_warnings(), main(), regression_main(), report_clusters_compatible(), setup(), and stop_postmaster_atexit().

{
    ClusterInfo *cluster;

    if (os_info.running_cluster == &old_cluster)
        cluster = &old_cluster;
    else if (os_info.running_cluster == &new_cluster)
        cluster = &new_cluster;
    else
        return;                 /* no cluster running */

    exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
              "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
              cluster->bindir, cluster->pgconfig,
              cluster->pgopts ? cluster->pgopts : "",
              fast ? "-m fast" : "");

    os_info.running_cluster = NULL;
}

unsigned int str2uint ( const char *  str  ) 

Definition at line 240 of file util.c.

References NULL.

Referenced by get_control_data().

{
    return strtoul(str, NULL, 10);
}

void transfer_all_new_dbs ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata,
char *  old_tablespace 
)

Definition at line 77 of file relfilenode.c.

References DbInfo::db_name, DbInfoArr::dbs, gen_db_file_maps(), DbInfoArr::ndbs, PG_FATAL, pg_free(), pg_log(), print_maps(), and transfer_single_new_db().

Referenced by parallel_transfer_all_new_dbs().

{
    int         old_dbnum,
                new_dbnum;

    /* Scan the old cluster databases and transfer their files */
    for (old_dbnum = new_dbnum = 0;
         old_dbnum < old_db_arr->ndbs;
         old_dbnum++, new_dbnum++)
    {
        DbInfo     *old_db = &old_db_arr->dbs[old_dbnum],
                   *new_db = NULL;
        FileNameMap *mappings;
        int         n_maps;
        pageCnvCtx *pageConverter = NULL;

        /*
         * Advance past any databases that exist in the new cluster but not in
         * the old, e.g. "postgres".  (The user might have removed the
         * 'postgres' database from the old cluster.)
         */
        for (; new_dbnum < new_db_arr->ndbs; new_dbnum++)
        {
            new_db = &new_db_arr->dbs[new_dbnum];
            if (strcmp(old_db->db_name, new_db->db_name) == 0)
                break;
        }

        if (new_dbnum >= new_db_arr->ndbs)
            pg_log(PG_FATAL, "old database \"%s\" not found in the new cluster\n",
                   old_db->db_name);

        n_maps = 0;
        mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
                                    new_pgdata);

        if (n_maps)
        {
            print_maps(mappings, n_maps, new_db->db_name);

#ifdef PAGE_CONVERSION
            pageConverter = setupPageConverter();
#endif
            transfer_single_new_db(pageConverter, mappings, n_maps,
                                   old_tablespace);

            pg_free(mappings);
        }
    }

    return;
}

void transfer_all_new_tablespaces ( DbInfoArr old_db_arr,
DbInfoArr new_db_arr,
char *  old_pgdata,
char *  new_pgdata 
)

Definition at line 31 of file relfilenode.c.

References check_ok(), end_progress_output(), UserOpts::jobs, NULL, OSInfo::num_old_tablespaces, OSInfo::old_tablespaces, os_info, parallel_transfer_all_new_dbs(), pg_log(), PG_REPORT, reap_child(), UserOpts::transfer_mode, TRANSFER_MODE_LINK, and user_opts.

Referenced by main().

{
    pg_log(PG_REPORT, "%s user relation files\n",
      user_opts.transfer_mode == TRANSFER_MODE_LINK ? "Linking" : "Copying");

    /*
     *  Transfering files by tablespace is tricky because a single database
     *  can use multiple tablespaces.  For non-parallel mode, we just pass a
     *  NULL tablespace path, which matches all tablespaces.  In parallel mode,
     *  we pass the default tablespace and all user-created tablespaces
     *  and let those operations happen in parallel.
     */
    if (user_opts.jobs <= 1)
        parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
                                      new_pgdata, NULL);
    else
    {
        int tblnum;

        /* transfer default tablespace */
        parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
                              new_pgdata, old_pgdata);

        for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
            parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
                                  new_pgdata, os_info.old_tablespaces[tblnum]);
        /* reap all children */
        while (reap_child(true) == true)
            ;
    }

    end_progress_output();
    check_ok();

    return;
}

void uninstall_support_functions_from_new_cluster ( void   ) 

Definition at line 99 of file function.c.

References check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, DbInfoArr::dbs, executeQueryOrDie(), DbInfoArr::ndbs, new_cluster, PQclear(), PQfinish(), and prep_status().

Referenced by create_new_objects().

{
    int         dbnum;

    prep_status("Removing support functions from new cluster");

    for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
    {
        DbInfo     *new_db = &new_cluster.dbarr.dbs[dbnum];
        PGconn     *conn = connectToServer(&new_cluster, new_db->db_name);

        /* suppress NOTICE of dropped objects */
        PQclear(executeQueryOrDie(conn,
                                  "SET client_min_messages = warning;"));
        PQclear(executeQueryOrDie(conn,
                                  "DROP SCHEMA binary_upgrade CASCADE;"));
        PQclear(executeQueryOrDie(conn,
                                  "RESET client_min_messages;"));
        PQfinish(conn);
    }
    check_ok();
}

bool void verify_directories ( void   ) 

Definition at line 179 of file exec.c.

References check_bin_dir(), check_data_dir(), new_cluster, old_cluster, PG_FATAL, pg_log(), and ClusterInfo::pgdata.

Referenced by setup().

{

#ifndef WIN32
    if (access(".", R_OK | W_OK | X_OK) != 0)
#else
    if (win32_check_directory_write_permissions() != 0)
#endif
        pg_log(PG_FATAL,
          "You must have read and write access in the current directory.\n");

    check_bin_dir(&old_cluster);
    check_data_dir(old_cluster.pgdata);
    check_bin_dir(&new_cluster);
    check_data_dir(new_cluster.pgdata);
}


Variable Documentation

char* output_files[]

Definition at line 58 of file pg_upgrade.c.

Referenced by cleanup(), and parseCommandLine().