summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/Makefile1
-rw-r--r--contrib/pg_upgrade/.gitignore8
-rw-r--r--contrib/pg_upgrade/IMPLEMENTATION100
-rw-r--r--contrib/pg_upgrade/Makefile34
-rw-r--r--contrib/pg_upgrade/TESTING83
-rw-r--r--contrib/pg_upgrade/check.c1016
-rw-r--r--contrib/pg_upgrade/controldata.c606
-rw-r--r--contrib/pg_upgrade/dump.c139
-rw-r--r--contrib/pg_upgrade/exec.c379
-rw-r--r--contrib/pg_upgrade/file.c250
-rw-r--r--contrib/pg_upgrade/function.c240
-rw-r--r--contrib/pg_upgrade/info.c535
-rw-r--r--contrib/pg_upgrade/option.c518
-rw-r--r--contrib/pg_upgrade/page.c164
-rw-r--r--contrib/pg_upgrade/parallel.c357
-rw-r--r--contrib/pg_upgrade/pg_upgrade.c616
-rw-r--r--contrib/pg_upgrade/pg_upgrade.h481
-rw-r--r--contrib/pg_upgrade/relfilenode.c294
-rw-r--r--contrib/pg_upgrade/server.c350
-rw-r--r--contrib/pg_upgrade/tablespace.c124
-rw-r--r--contrib/pg_upgrade/test.sh224
-rw-r--r--contrib/pg_upgrade/util.c298
-rw-r--r--contrib/pg_upgrade/version.c178
23 files changed, 0 insertions, 6995 deletions
diff --git a/contrib/Makefile b/contrib/Makefile
index 074e39477b1..cc60d680fca 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -36,7 +36,6 @@ SUBDIRS = \
pg_test_fsync \
pg_test_timing \
pg_trgm \
- pg_upgrade \
pgcrypto \
pgrowlocks \
pgstattuple \
diff --git a/contrib/pg_upgrade/.gitignore b/contrib/pg_upgrade/.gitignore
deleted file mode 100644
index d24ec60184f..00000000000
--- a/contrib/pg_upgrade/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/pg_upgrade
-# Generated by test suite
-/analyze_new_cluster.sh
-/delete_old_cluster.sh
-/analyze_new_cluster.bat
-/delete_old_cluster.bat
-/log/
-/tmp_check/
diff --git a/contrib/pg_upgrade/IMPLEMENTATION b/contrib/pg_upgrade/IMPLEMENTATION
deleted file mode 100644
index a0cfcf15dac..00000000000
--- a/contrib/pg_upgrade/IMPLEMENTATION
+++ /dev/null
@@ -1,100 +0,0 @@
-contrib/pg_upgrade/IMPLEMENTATION
-
-------------------------------------------------------------------------------
-PG_UPGRADE: IN-PLACE UPGRADES FOR POSTGRESQL
-------------------------------------------------------------------------------
-
-Upgrading a PostgreSQL database from one major release to another can be
-an expensive process. For minor upgrades, you can simply install new
-executables and forget about upgrading existing data. But for major
-upgrades, you have to export all of your data using pg_dump, install the
-new release, run initdb to create a new cluster, and then import your
-old data. If you have a lot of data, that can take a considerable amount
-of time. If you have too much data, you may have to buy more storage
-since you need enough room to hold the original data plus the exported
-data. pg_upgrade can reduce the amount of time and disk space required
-for many upgrades.
-
-The URL http://momjian.us/main/writings/pgsql/pg_upgrade.pdf contains a
-presentation about pg_upgrade internals that mirrors the text
-description below.
-
-------------------------------------------------------------------------------
-WHAT IT DOES
-------------------------------------------------------------------------------
-
-pg_upgrade is a tool that performs an in-place upgrade of existing
-data. Some upgrades change the on-disk representation of data;
-pg_upgrade cannot help in those upgrades. However, many upgrades do
-not change the on-disk representation of a user-defined table. In those
-cases, pg_upgrade can move existing user-defined tables from the old
-database cluster into the new cluster.
-
-There are two factors that determine whether an in-place upgrade is
-practical.
-
-Every table in a cluster shares the same on-disk representation of the
-table headers and trailers and the on-disk representation of tuple
-headers. If this changes between the old version of PostgreSQL and the
-new version, pg_upgrade cannot move existing tables to the new cluster;
-you will have to pg_dump the old data and then import that data into the
-new cluster.
-
-Second, all data types should have the same binary representation
-between the two major PostgreSQL versions.
-
-------------------------------------------------------------------------------
-HOW IT WORKS
-------------------------------------------------------------------------------
-
-To use pg_upgrade during an upgrade, start by installing a fresh
-cluster using the newest version in a new directory. When you've
-finished installation, the new cluster will contain the new executables
-and the usual template0, template1, and postgres, but no user-defined
-tables. At this point, you can shut down the old and new postmasters and
-invoke pg_upgrade.
-
-When pg_upgrade starts, it ensures that all required executables are
-present and contain the expected version numbers. The verification
-process also checks the old and new $PGDATA directories to ensure that
-the expected files and subdirectories are in place. If the verification
-process succeeds, pg_upgrade starts the old postmaster and runs
-pg_dumpall --schema-only to capture the metadata contained in the old
-cluster. The script produced by pg_dumpall will be used in a later step
-to recreate all user-defined objects in the new cluster.
-
-Note that the script produced by pg_dumpall will only recreate
-user-defined objects, not system-defined objects. The new cluster will
-contain the system-defined objects created by the latest version of
-PostgreSQL.
-
-Once pg_upgrade has extracted the metadata from the old cluster, it
-performs a number of bookkeeping tasks required to 'sync up' the new
-cluster with the existing data.
-
-First, pg_upgrade copies the commit status information and 'next
-transaction ID' from the old cluster to the new cluster. This is the
-steps ensures that the proper tuples are visible from the new cluster.
-Remember, pg_upgrade does not export/import the content of user-defined
-tables so the transaction IDs in the new cluster must match the
-transaction IDs in the old data. pg_upgrade also copies the starting
-address for write-ahead logs from the old cluster to the new cluster.
-
-Now pg_upgrade begins reconstructing the metadata obtained from the old
-cluster using the first part of the pg_dumpall output.
-
-Next, pg_upgrade executes the remainder of the script produced earlier
-by pg_dumpall --- this script effectively creates the complete
-user-defined metadata from the old cluster to the new cluster. It
-preserves the relfilenode numbers so TOAST and other references
-to relfilenodes in user data is preserved. (See binary-upgrade usage
-in pg_dump).
-
-Finally, pg_upgrade links or copies each user-defined table and its
-supporting indexes and toast tables from the old cluster to the new
-cluster.
-
-An important feature of the pg_upgrade design is that it leaves the
-original cluster intact --- if a problem occurs during the upgrade, you
-can still run the previous version, after renaming the tablespaces back
-to the original names.
diff --git a/contrib/pg_upgrade/Makefile b/contrib/pg_upgrade/Makefile
deleted file mode 100644
index 87da4b8e834..00000000000
--- a/contrib/pg_upgrade/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# contrib/pg_upgrade/Makefile
-
-PGFILEDESC = "pg_upgrade - an in-place binary upgrade utility"
-PGAPPICON = win32
-
-PROGRAM = pg_upgrade
-OBJS = check.o controldata.o dump.o exec.o file.o function.o info.o \
- option.o page.o parallel.o pg_upgrade.o relfilenode.o server.o \
- tablespace.o util.o version.o $(WIN32RES)
-
-PG_CPPFLAGS = -DFRONTEND -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir)
-PG_LIBS = $(libpq_pgport)
-
-EXTRA_CLEAN = analyze_new_cluster.sh delete_old_cluster.sh log/ tmp_check/ \
- pg_upgrade_dump_globals.sql \
- pg_upgrade_dump_*.custom pg_upgrade_*.log
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_upgrade
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
-
-check: test.sh all
- MAKE=$(MAKE) bindir=$(bindir) libdir=$(libdir) EXTRA_REGRESS_OPTS="$(EXTRA_REGRESS_OPTS)" $(SHELL) $< --install
-
-# disabled because it upsets the build farm
-#installcheck: test.sh
-# MAKE=$(MAKE) bindir=$(bindir) libdir=$(libdir) $(SHELL) $<
diff --git a/contrib/pg_upgrade/TESTING b/contrib/pg_upgrade/TESTING
deleted file mode 100644
index 359688c6645..00000000000
--- a/contrib/pg_upgrade/TESTING
+++ /dev/null
@@ -1,83 +0,0 @@
-contrib/pg_upgrade/TESTING
-
-The most effective way to test pg_upgrade, aside from testing on user
-data, is by upgrading the PostgreSQL regression database.
-
-This testing process first requires the creation of a valid regression
-database dump. Such files contain most database features and are
-specific to each major version of Postgres.
-
-Here are the steps needed to create a regression database dump file:
-
-1) Create and populate the regression database in the old cluster
- This database can be created by running 'make installcheck' from
- src/test/regression.
-
-2) Use pg_dump to dump out the regression database. Use the new
- cluster's pg_dump on the old database to minimize whitespace
- differences in the diff.
-
-3) Adjust the regression database dump file
-
- a) Perform the load/dump twice
- This fixes problems with the ordering of COPY columns for
- inherited tables.
-
- b) Change CREATE FUNCTION shared object paths to use '$libdir'
- The old and new cluster will have different shared object paths.
-
- c) Fix any wrapping format differences
- Commands like CREATE TRIGGER and ALTER TABLE sometimes have
- differences.
-
- d) For pre-9.0, change CREATE OR REPLACE LANGUAGE to CREATE LANGUAGE
-
- e) For pre-9.0, remove 'regex_flavor'
-
- f) For pre-9.0, adjust extra_float_digits
- Postgres 9.0 pg_dump uses extra_float_digits=-2 for pre-9.0
- databases, and extra_float_digits=-3 for >= 9.0 databases.
- It is necessary to modify 9.0 pg_dump to always use -3, and
- modify the pre-9.0 old server to accept extra_float_digits=-3.
-
-Once the dump is created, it can be repeatedly loaded into the old
-database, upgraded, and dumped out of the new database, and then
-compared to the original version. To test the dump file, perform these
-steps:
-
-1) Create the old and new clusters in different directories.
-
-2) Copy the regression shared object files into the appropriate /lib
- directory for old and new clusters.
-
-3) Create the regression database in the old server.
-
-4) Load the dump file created above into the regression database;
- check for errors while loading.
-
-5) Upgrade the old database to the new major version, as outlined in
- the pg_upgrade manual section.
-
-6) Use pg_dump to dump out the regression database in the new cluster.
-
-7) Diff the regression database dump file with the regression dump
- file loaded into the old server.
-
-The shell script test.sh in this directory performs more or less this
-procedure. You can invoke it by running
-
- make check
-
-or by running
-
- make installcheck
-
-if "make install" (or "make install-world") were done beforehand.
-When invoked without arguments, it will run an upgrade from the
-version in this source tree to a new instance of the same version. To
-test an upgrade from a different version, invoke it like this:
-
- make installcheck oldbindir=...otherversion/bin oldsrc=...somewhere/postgresql
-
-In this case, you will have to manually eyeball the resulting dump
-diff for version-specific differences, as explained above.
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
deleted file mode 100644
index 6a498c3bd5c..00000000000
--- a/contrib/pg_upgrade/check.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * check.c
- *
- * server checks and output routines
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/check.c
- */
-
-#include "postgres_fe.h"
-
-#include "catalog/pg_authid.h"
-#include "mb/pg_wchar.h"
-#include "pg_upgrade.h"
-
-
-static void check_new_cluster_is_empty(void);
-static void check_databases_are_compatible(void);
-static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb);
-static bool equivalent_locale(int category, const char *loca, const char *locb);
-static void check_is_install_user(ClusterInfo *cluster);
-static void check_for_prepared_transactions(ClusterInfo *cluster);
-static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
-static void check_for_reg_data_type_usage(ClusterInfo *cluster);
-static void check_for_jsonb_9_4_usage(ClusterInfo *cluster);
-static void get_bin_version(ClusterInfo *cluster);
-static char *get_canonical_locale_name(int category, const char *locale);
-
-
-/*
- * fix_path_separator
- * For non-Windows, just return the argument.
- * For Windows convert any forward slash to a backslash
- * such as is suitable for arguments to builtin commands
- * like RMDIR and DEL.
- */
-static char *
-fix_path_separator(char *path)
-{
-#ifdef WIN32
-
- char *result;
- char *c;
-
- result = pg_strdup(path);
-
- for (c = result; *c != '\0'; c++)
- if (*c == '/')
- *c = '\\';
-
- return result;
-#else
-
- return path;
-#endif
-}
-
-void
-output_check_banner(bool live_check)
-{
- 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
-check_and_dump_old_cluster(bool live_check)
-{
- /* -- OLD -- */
-
- if (!live_check)
- start_postmaster(&old_cluster, true);
-
- 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_install_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);
- if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 &&
- old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
- check_for_jsonb_9_4_usage(&old_cluster);
-
- /* Pre-PG 9.4 had a different 'line' data type internal format */
- if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
- old_9_3_check_for_line_data_type_usage(&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_new_cluster(void)
-{
- get_db_and_rel_infos(&new_cluster);
-
- check_new_cluster_is_empty();
- check_databases_are_compatible();
-
- check_loadable_libraries();
-
- if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
- check_hard_link();
-
- check_is_install_user(&new_cluster);
-
- check_for_prepared_transactions(&new_cluster);
-}
-
-
-void
-report_clusters_compatible(void)
-{
- 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
-issue_warnings(void)
-{
- /* Create dummy large object permissions for old < PG 9.0? */
- if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
- {
- start_postmaster(&new_cluster, true);
- new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
- stop_postmaster(false);
- }
-}
-
-
-void
-output_completion_banner(char *analyze_script_file_name,
- char *deletion_script_file_name)
-{
- /* 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
-check_cluster_versions(void)
-{
- 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) < 804)
- pg_fatal("This utility can only upgrade from PostgreSQL version 8.4 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_fatal("This utility can only upgrade to PostgreSQL version %s.\n",
- PG_MAJORVERSION);
-
- /*
- * We can't allow downgrading because we use the target pg_dump, and
- * pg_dump cannot operate on newer database versions, only current and
- * older versions.
- */
- if (old_cluster.major_version > new_cluster.major_version)
- 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_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_fatal("New cluster data and binary directories are from different major versions.\n");
-
- check_ok();
-}
-
-
-void
-check_cluster_compatibility(bool live_check)
-{
- /* 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_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_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_fatal("When checking a live server, "
- "the old and new port numbers must be different.\n");
-}
-
-
-/*
- * check_locale_and_encoding()
- *
- * Check that locale and encoding of a database in the old and new clusters
- * are compatible.
- */
-static void
-check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb)
-{
- if (olddb->db_encoding != newdb->db_encoding)
- pg_fatal("encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
- olddb->db_name,
- pg_encoding_to_char(olddb->db_encoding),
- pg_encoding_to_char(newdb->db_encoding));
- if (!equivalent_locale(LC_COLLATE, olddb->db_collate, newdb->db_collate))
- pg_fatal("lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
- olddb->db_name, olddb->db_collate, newdb->db_collate);
- if (!equivalent_locale(LC_CTYPE, olddb->db_ctype, newdb->db_ctype))
- pg_fatal("lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
- olddb->db_name, olddb->db_ctype, newdb->db_ctype);
-}
-
-/*
- * equivalent_locale()
- *
- * Best effort locale-name comparison. Return false if we are not 100% sure
- * the locales are equivalent.
- *
- * Note: The encoding parts of the names are ignored. This function is
- * currently used to compare locale names stored in pg_database, and
- * pg_database contains a separate encoding field. That's compared directly
- * in check_locale_and_encoding().
- */
-static bool
-equivalent_locale(int category, const char *loca, const char *locb)
-{
- const char *chara;
- const char *charb;
- char *canona;
- char *canonb;
- int lena;
- int lenb;
-
- /*
- * If the names are equal, the locales are equivalent. Checking this
- * first avoids calling setlocale() in the common case that the names
- * are equal. That's a good thing, if setlocale() is buggy, for example.
- */
- if (pg_strcasecmp(loca, locb) == 0)
- return true;
-
- /*
- * Not identical. Canonicalize both names, remove the encoding parts,
- * and try again.
- */
- canona = get_canonical_locale_name(category, loca);
- chara = strrchr(canona, '.');
- lena = chara ? (chara - canona) : strlen(canona);
-
- canonb = get_canonical_locale_name(category, locb);
- charb = strrchr(canonb, '.');
- lenb = charb ? (charb - canonb) : strlen(canonb);
-
- if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0)
- return true;
-
- return false;
-}
-
-
-static void
-check_new_cluster_is_empty(void)
-{
- int dbnum;
-
- for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
- {
- int relnum;
- RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
-
- for (relnum = 0; relnum < rel_arr->nrels;
- relnum++)
- {
- /* pg_largeobject and its index should be skipped */
- if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
- pg_fatal("New cluster database \"%s\" is not empty\n",
- new_cluster.dbarr.dbs[dbnum].db_name);
- }
- }
-}
-
-/*
- * Check that every database that already exists in the new cluster is
- * compatible with the corresponding database in the old one.
- */
-static void
-check_databases_are_compatible(void)
-{
- int newdbnum;
- int olddbnum;
- DbInfo *newdbinfo;
- DbInfo *olddbinfo;
-
- for (newdbnum = 0; newdbnum < new_cluster.dbarr.ndbs; newdbnum++)
- {
- newdbinfo = &new_cluster.dbarr.dbs[newdbnum];
-
- /* Find the corresponding database in the old cluster */
- for (olddbnum = 0; olddbnum < old_cluster.dbarr.ndbs; olddbnum++)
- {
- olddbinfo = &old_cluster.dbarr.dbs[olddbnum];
- if (strcmp(newdbinfo->db_name, olddbinfo->db_name) == 0)
- {
- check_locale_and_encoding(olddbinfo, newdbinfo);
- break;
- }
- }
- }
-}
-
-
-/*
- * create_script_for_cluster_analyze()
- *
- * This incrementally generates better optimizer statistics
- */
-void
-create_script_for_cluster_analyze(char **analyze_script_file_name)
-{
- FILE *script = NULL;
- char *user_specification = "";
-
- prep_status("Creating script to analyze new cluster");
-
- if (os_info.user_specified)
- user_specification = psprintf("-U \"%s\" ", os_info.user);
-
- *analyze_script_file_name = psprintf("%sanalyze_new_cluster.%s",
- SCRIPT_PREFIX, SCRIPT_EXT);
-
- if ((script = fopen_priv(*analyze_script_file_name, "w")) == NULL)
- 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\" %s--all %s%s\n", ECHO_QUOTE,
- new_cluster.bindir, user_specification,
- /* 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);
-
- fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-in-stages\n",
- new_cluster.bindir, user_specification);
- /* Did we copy the free space files? */
- if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
- fprintf(script, "\"%s/vacuumdb\" %s--all\n", new_cluster.bindir,
- user_specification);
-
- 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_fatal("Could not add execute permission to file \"%s\": %s\n",
- *analyze_script_file_name, getErrorText(errno));
-#endif
-
- if (os_info.user_specified)
- pg_free(user_specification);
-
- check_ok();
-}
-
-
-/*
- * create_script_for_old_cluster_deletion()
- *
- * This is particularly useful for tablespace deletion.
- */
-void
-create_script_for_old_cluster_deletion(char **deletion_script_file_name)
-{
- FILE *script = NULL;
- int tblnum;
- char old_cluster_pgdata[MAXPGPATH];
-
- *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
- SCRIPT_PREFIX, 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_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%cPG_VERSION\n",
- fix_path_separator(os_info.old_tablespaces[tblnum]),
- PATH_SEPARATOR);
-
- for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
- fprintf(script, RMDIR_CMD " \"%s%c%d\"\n",
- fix_path_separator(os_info.old_tablespaces[tblnum]),
- PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
- }
- else
- {
- char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
-
- /*
- * 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(suffix_path));
- pfree(suffix_path);
- }
- }
-
- fclose(script);
-
-#ifndef WIN32
- if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
- pg_fatal("Could not add execute permission to file \"%s\": %s\n",
- *deletion_script_file_name, getErrorText(errno));
-#endif
-
- check_ok();
-}
-
-
-/*
- * check_is_install_user()
- *
- * Check we are the install user, and that the new cluster
- * has no other users.
- */
-static void
-check_is_install_user(ClusterInfo *cluster)
-{
- PGresult *res;
- PGconn *conn = connectToServer(cluster, "template1");
-
- prep_status("Checking database user is the install user");
-
- /* Can't use pg_authid because only superusers can view it. */
- res = executeQueryOrDie(conn,
- "SELECT rolsuper, oid "
- "FROM pg_catalog.pg_roles "
- "WHERE rolname = current_user");
-
- /*
- * We only allow the install user in the new cluster (see comment below)
- * and we preserve pg_authid.oid, so this must be the install user in
- * the old cluster too.
- */
- if (PQntuples(res) != 1 ||
- atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
- pg_fatal("database user \"%s\" is not the install user\n",
- os_info.user);
-
- PQclear(res);
-
- res = executeQueryOrDie(conn,
- "SELECT COUNT(*) "
- "FROM pg_catalog.pg_roles ");
-
- if (PQntuples(res) != 1)
- pg_fatal("could not determine the number of users\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 (cluster == &new_cluster && atooid(PQgetvalue(res, 0, 0)) != 1)
- pg_fatal("Only the install user can be defined in the new cluster.\n");
-
- PQclear(res);
-
- PQfinish(conn);
-
- check_ok();
-}
-
-
-/*
- * check_for_prepared_transactions()
- *
- * Make sure there are no prepared transactions because the storage format
- * might have changed.
- */
-static void
-check_for_prepared_transactions(ClusterInfo *cluster)
-{
- PGresult *res;
- PGconn *conn = connectToServer(cluster, "template1");
-
- prep_status("Checking for prepared transactions");
-
- res = executeQueryOrDie(conn,
- "SELECT * "
- "FROM pg_catalog.pg_prepared_xacts");
-
- if (PQntuples(res) != 0)
- pg_fatal("The %s cluster contains prepared transactions\n",
- CLUSTER_NAME(cluster));
-
- PQclear(res);
-
- PQfinish(conn);
-
- check_ok();
-}
-
-
-/*
- * check_for_isn_and_int8_passing_mismatch()
- *
- * contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
- * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
- * it must match for the old and new servers.
- */
-static void
-check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
-{
- int dbnum;
- FILE *script = NULL;
- bool found = false;
- char output_path[MAXPGPATH];
-
- prep_status("Checking for contrib/isn with bigint-passing mismatch");
-
- if (old_cluster.controldata.float8_pass_by_value ==
- new_cluster.controldata.float8_pass_by_value)
- {
- /* no mismatch */
- check_ok();
- return;
- }
-
- snprintf(output_path, sizeof(output_path),
- "contrib_isn_and_int8_pass_by_value.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/isn */
- 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/isn'");
-
- 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_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_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
- "bigint data type. Your old and new clusters pass bigint values\n"
- "differently so this cluster cannot currently be upgraded. You can\n"
- "manually upgrade databases that use \"contrib/isn\" facilities and remove\n"
- "\"contrib/isn\" from the old cluster and restart the upgrade. A list of\n"
- "the problem functions is in the file:\n"
- " %s\n\n", output_path);
- }
- else
- check_ok();
-}
-
-
-/*
- * check_for_reg_data_type_usage()
- * pg_upgrade only preserves these system values:
- * pg_class.oid
- * pg_type.oid
- * pg_enum.oid
- *
- * Many of the reg* data types reference system catalog info that is
- * not preserved, and hence these data types cannot be used in user
- * tables upgraded by pg_upgrade.
- */
-static void
-check_for_reg_data_type_usage(ClusterInfo *cluster)
-{
- int dbnum;
- FILE *script = NULL;
- bool found = false;
- char output_path[MAXPGPATH];
-
- prep_status("Checking for reg* system OID user data types");
-
- snprintf(output_path, sizeof(output_path), "tables_using_reg.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);
-
- /*
- * While several relkinds don't store any data, e.g. views, they can
- * be used to define data types of other columns, so we check all
- * relkinds.
- */
- 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 "
- " NOT a.attisdropped AND "
- " a.atttypid IN ( "
- " 'pg_catalog.regproc'::pg_catalog.regtype, "
- " 'pg_catalog.regprocedure'::pg_catalog.regtype, "
- " 'pg_catalog.regoper'::pg_catalog.regtype, "
- " 'pg_catalog.regoperator'::pg_catalog.regtype, "
- /* regclass.oid is preserved, so 'regclass' is OK */
- /* regtype.oid is preserved, so 'regtype' is OK */
- " 'pg_catalog.regconfig'::pg_catalog.regtype, "
- " 'pg_catalog.regdictionary'::pg_catalog.regtype) AND "
- " c.relnamespace = n.oid 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_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_fatal("Your installation contains one of the reg* data types in user tables.\n"
- "These data types reference system OIDs that are not preserved by\n"
- "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
- "remove 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();
-}
-
-
-/*
- * check_for_jsonb_9_4_usage()
- *
- * JSONB changed its storage format during 9.4 beta, so check for it.
- */
-static void
-check_for_jsonb_9_4_usage(ClusterInfo *cluster)
-{
- int dbnum;
- FILE *script = NULL;
- bool found = false;
- char output_path[MAXPGPATH];
-
- prep_status("Checking for JSONB user data types");
-
- snprintf(output_path, sizeof(output_path), "tables_using_jsonb.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);
-
- /*
- * While several relkinds don't store any data, e.g. views, they can
- * be used to define data types of other columns, so we check all
- * relkinds.
- */
- 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 "
- " NOT a.attisdropped AND "
- " a.atttypid = 'pg_catalog.jsonb'::pg_catalog.regtype AND "
- " c.relnamespace = n.oid AND "
- /* exclude possible orphaned temp tables */
- " n.nspname !~ '^pg_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_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_fatal("Your installation contains one of the JSONB data types in user tables.\n"
- "The internal format of JSONB changed during 9.4 beta so this cluster cannot currently\n"
- "be upgraded. You can remove the problem tables and restart the upgrade. A list\n"
- "of the problem columns is in the file:\n"
- " %s\n\n", output_path);
- }
- else
- check_ok();
-}
-
-
-static void
-get_bin_version(ClusterInfo *cluster)
-{
- char cmd[MAXPGPATH],
- cmd_output[MAX_STRING];
- FILE *output;
- int pre_dot,
- post_dot;
-
- snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
-
- if ((output = popen(cmd, "r")) == NULL ||
- fgets(cmd_output, sizeof(cmd_output), output) == NULL)
- pg_fatal("Could not get pg_ctl version data using %s: %s\n",
- cmd, getErrorText(errno));
-
- pclose(output);
-
- /* Remove trailing newline */
- if (strchr(cmd_output, '\n') != NULL)
- *strchr(cmd_output, '\n') = '\0';
-
- if (sscanf(cmd_output, "%*s %*s %d.%d", &pre_dot, &post_dot) != 2)
- pg_fatal("could not get version from %s\n", cmd);
-
- cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
-}
-
-
-/*
- * get_canonical_locale_name
- *
- * Send the locale name to the system, and hope we get back a canonical
- * version. This should match the backend's check_locale() function.
- */
-static char *
-get_canonical_locale_name(int category, const char *locale)
-{
- char *save;
- char *res;
-
- /* get the current setting, so we can restore it. */
- save = setlocale(category, NULL);
- if (!save)
- pg_fatal("failed to get the current locale\n");
-
- /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
- save = pg_strdup(save);
-
- /* set the locale with setlocale, to see if it accepts it. */
- res = setlocale(category, locale);
-
- if (!res)
- pg_fatal("failed to get system locale name for \"%s\"\n", locale);
-
- res = pg_strdup(res);
-
- /* restore old value. */
- if (!setlocale(category, save))
- pg_fatal("failed to restore old locale \"%s\"\n", save);
-
- pg_free(save);
-
- return res;
-}
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
deleted file mode 100644
index 0e70b6f80b4..00000000000
--- a/contrib/pg_upgrade/controldata.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * controldata.c
- *
- * controldata functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/controldata.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <ctype.h>
-
-/*
- * get_control_data()
- *
- * gets pg_control information in "ctrl". Assumes that bindir and
- * datadir are valid absolute paths to postgresql bin and pgdata
- * directories respectively *and* pg_resetxlog is version compatible
- * with datadir. The main purpose of this function is to get pg_control
- * data in a version independent manner.
- *
- * The approach taken here is to invoke pg_resetxlog with -n option
- * and then pipe its output. With little string parsing we get the
- * pg_control data. pg_resetxlog cannot be run while the server is running
- * so we use pg_controldata; pg_controldata doesn't provide all the fields
- * we need to actually perform the upgrade, but it provides enough for
- * check mode. We do not implement pg_resetxlog -n because it is hard to
- * return valid xid data for a running server.
- */
-void
-get_control_data(ClusterInfo *cluster, bool live_check)
-{
- 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_large_object = 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), "\"%s/%s \"%s\"",
- cluster->bindir,
- live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
- cluster->pgdata);
- fflush(stdout);
- fflush(stderr);
-
- if ((output = popen(cmd, "r")) == NULL)
- pg_fatal("Could not get control data using %s: %s\n",
- cmd, getErrorText(errno));
-
- /* 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);
-
- if ((p = strstr(bufin, "pg_control version number:")) != NULL)
- {
- p = strchr(p, ':');
-
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: pg_resetxlog problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
- p = strpbrk(p, "01234567890ABCDEF");
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- /* Make sure it looks like a valid WAL file name */
- if (strspn(p, "0123456789ABCDEF") != 24)
- 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' char */
- cluster->controldata.chkpnt_tli = str2uint(p);
- got_tli = true;
- }
- else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
- {
- p = strchr(p, ':');
-
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' char */
- cluster->controldata.chkpnt_nxtepoch = str2uint(p);
-
- p = strchr(p, '/');
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove '/' char */
- cluster->controldata.chkpnt_nxtxid = str2uint(p);
- got_xid = true;
- }
- else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
- {
- p = strchr(p, ':');
-
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' char */
- cluster->controldata.toast = str2uint(p);
- got_toast = true;
- }
- else if ((p = strstr(bufin, "Size of a large-object chunk:")) != NULL)
- {
- p = strchr(p, ':');
-
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' char */
- cluster->controldata.large_object = str2uint(p);
- got_large_object = true;
- }
- else if ((p = strstr(bufin, "Date/time type storage:")) != NULL)
- {
- p = strchr(p, ':');
-
- if (p == NULL || strlen(p) <= 1)
- pg_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' 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_fatal("%d: controldata retrieval problem\n", __LINE__);
-
- p++; /* remove ':' char */
- /* used later for contrib check */
- cluster->controldata.data_checksum_version = str2uint(p);
- got_data_checksum_version = true;
- }
- }
-
- 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_large_object &&
- cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) ||
- !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_large_object &&
- cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER)
- pg_log(PG_REPORT, " large-object chunk size\n");
-
- if (!got_date_is_int)
- pg_log(PG_REPORT, " dates/times are integers?\n");
-
- 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_fatal("Cannot continue without required control information, terminating\n");
- }
-}
-
-
-/*
- * check_control_data()
- *
- * check to make sure the control data settings are compatible
- */
-void
-check_control_data(ControlData *oldctrl,
- ControlData *newctrl)
-{
- if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
- 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_fatal("old and new pg_controldata block sizes are invalid or do not match\n");
-
- if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
- 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_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_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_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_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_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n");
-
- /* large_object added in 9.5, so it might not exist in the old cluster */
- if (oldctrl->large_object != 0 &&
- oldctrl->large_object != newctrl->large_object)
- pg_fatal("old and new pg_controldata large-object chunk sizes are invalid or do not match\n");
-
- if (oldctrl->date_is_int != newctrl->date_is_int)
- pg_fatal("old and new pg_controldata date/time storage types do not match\n");
-
- /*
- * We might eventually allow upgrades from checksum to no-checksum
- * clusters.
- */
- if (oldctrl->data_checksum_version == 0 &&
- newctrl->data_checksum_version != 0)
- pg_fatal("old cluster does not use data checksums but the new one does\n");
- else if (oldctrl->data_checksum_version != 0 &&
- newctrl->data_checksum_version == 0)
- pg_fatal("old cluster uses data checksums but the new one does not\n");
- else if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
- pg_fatal("old and new cluster pg_controldata checksum versions do not match\n");
-}
-
-
-void
-disable_old_cluster(void)
-{
- 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_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);
-}
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
deleted file mode 100644
index 906e85f2b53..00000000000
--- a/contrib/pg_upgrade/dump.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * dump.c
- *
- * dump functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/dump.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <sys/types.h>
-#include "catalog/binary_upgrade.h"
-
-
-void
-generate_old_dump(void)
-{
- int dbnum;
- mode_t old_umask;
-
- 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 --globals-only --quote-all-identifiers "
- "--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");
-
- /*
- * Set umask for this function, all functions it calls, and all
- * subprocesses/threads it creates. We can't use fopen_priv() as Windows
- * uses threads and umask is process-global.
- */
- old_umask = umask(S_IRWXG | S_IRWXO);
-
- /* 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 --quote-all-identifiers "
- "--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)
- ;
-
- umask(old_umask);
-
- end_progress_output();
- check_ok();
-}
-
-
-/*
- * It is possible for there to be a mismatch in the need for TOAST tables
- * between the old and new servers, e.g. some pre-9.1 tables didn't need
- * TOAST tables but will need them in 9.1+. (There are also opposite cases,
- * but these are handled by setting binary_upgrade_next_toast_pg_class_oid.)
- *
- * We can't allow the TOAST table to be created by pg_dump with a
- * pg_dump-assigned oid because it might conflict with a later table that
- * uses that oid, causing a "file exists" error for pg_class conflicts, and
- * a "duplicate oid" error for pg_type conflicts. (TOAST tables need pg_type
- * entries.)
- *
- * Therefore, a backend in binary-upgrade mode will not create a TOAST
- * table unless an OID as passed in via pg_upgrade_support functions.
- * This function is called after the restore and uses ALTER TABLE to
- * auto-create any needed TOAST tables which will not conflict with
- * restored oids.
- */
-void
-optionally_create_toast_tables(void)
-{
- int dbnum;
-
- prep_status("Creating newly-required TOAST tables");
-
- for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
- {
- PGresult *res;
- int ntups;
- int rowno;
- int i_nspname,
- i_relname;
- DbInfo *active_db = &new_cluster.dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(&new_cluster, active_db->db_name);
-
- res = executeQueryOrDie(conn,
- "SELECT n.nspname, c.relname "
- "FROM pg_catalog.pg_class c, "
- " pg_catalog.pg_namespace n "
- "WHERE c.relnamespace = n.oid AND "
- " n.nspname NOT IN ('pg_catalog', 'information_schema') AND "
- "c.relkind IN ('r', 'm') AND "
- "c.reltoastrelid = 0");
-
- ntups = PQntuples(res);
- i_nspname = PQfnumber(res, "nspname");
- i_relname = PQfnumber(res, "relname");
- for (rowno = 0; rowno < ntups; rowno++)
- {
- /* enable auto-oid-numbered TOAST creation if needed */
- PQclear(executeQueryOrDie(conn, "SELECT pg_catalog.binary_upgrade_set_next_toast_pg_class_oid('%d'::pg_catalog.oid);",
- OPTIONALLY_CREATE_TOAST_OID));
-
- /* dummy command that also triggers check for required TOAST table */
- PQclear(executeQueryOrDie(conn, "ALTER TABLE %s.%s RESET (binary_upgrade_dummy_option);",
- quote_identifier(PQgetvalue(res, rowno, i_nspname)),
- quote_identifier(PQgetvalue(res, rowno, i_relname))));
- }
-
- PQclear(res);
-
- PQfinish(conn);
- }
-
- check_ok();
-}
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
deleted file mode 100644
index bf87419b187..00000000000
--- a/contrib/pg_upgrade/exec.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * exec.c
- *
- * execution functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/exec.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <fcntl.h>
-#include <sys/types.h>
-
-static void check_data_dir(const char *pg_data);
-static void check_bin_dir(ClusterInfo *cluster);
-static void validate_exec(const char *dir, const char *cmdName);
-
-#ifdef WIN32
-static int win32_check_directory_write_permissions(void);
-#endif
-
-
-/*
- * exec_prog()
- * Execute an external program with stdout/stderr redirected, and report
- * errors
- *
- * Formats a command from the given argument list, logs it to the log file,
- * and attempts to execute that command. If the command executes
- * successfully, exec_prog() returns true.
- *
- * If the command fails, an error message is saved to the specified log_file.
- * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
- * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
- * returns false.
- *
- * The code requires it be called first from the primary thread on Windows.
- */
-bool
-exec_prog(const char *log_file, const char *opt_log_file,
- bool throw_error, const char *fmt,...)
-{
- int result = 0;
- int written;
-
-#define MAXCMDLEN (2 * MAXPGPATH)
- char cmd[MAXCMDLEN];
- FILE *log;
- va_list ap;
-
-#ifdef WIN32
- static DWORD mainThreadId = 0;
-
- /* We assume we are called from the primary thread first */
- if (mainThreadId == 0)
- mainThreadId = GetCurrentThreadId();
-#endif
-
- written = 0;
- va_start(ap, fmt);
- written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
- va_end(ap);
- if (written >= MAXCMDLEN)
- pg_fatal("command too long\n");
- written += snprintf(cmd + written, MAXCMDLEN - written,
- " >> \"%s\" 2>&1", log_file);
- if (written >= MAXCMDLEN)
- pg_fatal("command too long\n");
-
- pg_log(PG_VERBOSE, "%s\n", cmd);
-
-#ifdef WIN32
-
- /*
- * For some reason, Windows issues a file-in-use error if we write data to
- * the log file from a non-primary thread just before we create a
- * subprocess that also writes to the same log file. One fix is to sleep
- * for 100ms. A cleaner fix is to write to the log file _after_ the
- * subprocess has completed, so we do this only when writing from a
- * non-primary thread. fflush(), running system() twice, and pre-creating
- * the file do not see to help.
- */
- if (mainThreadId != GetCurrentThreadId())
- result = system(cmd);
-#endif
-
- log = fopen(log_file, "a");
-
-#ifdef WIN32
- {
- /*
- * "pg_ctl -w stop" might have reported that the server has stopped
- * because the postmaster.pid file has been removed, but "pg_ctl -w
- * start" might still be in the process of closing and might still be
- * holding its stdout and -l log file descriptors open. Therefore,
- * try to open the log file a few more times.
- */
- int iter;
-
- for (iter = 0; iter < 4 && log == NULL; iter++)
- {
- pg_usleep(1000000); /* 1 sec */
- log = fopen(log_file, "a");
- }
- }
-#endif
-
- if (log == NULL)
- pg_fatal("cannot write to log file %s\n", log_file);
-
-#ifdef WIN32
- /* Are we printing "command:" before its output? */
- if (mainThreadId == GetCurrentThreadId())
- fprintf(log, "\n\n");
-#endif
- fprintf(log, "command: %s\n", cmd);
-#ifdef WIN32
- /* Are we printing "command:" after its output? */
- if (mainThreadId != GetCurrentThreadId())
- fprintf(log, "\n\n");
-#endif
-
- /*
- * In Windows, we must close the log file at this point so the file is not
- * open while the command is running, or we get a share violation.
- */
- fclose(log);
-
-#ifdef WIN32
- /* see comment above */
- if (mainThreadId == GetCurrentThreadId())
-#endif
- result = system(cmd);
-
- if (result != 0)
- {
- /* we might be in on a progress status line, so go to the next line */
- report_status(PG_REPORT, "\n*failure*");
- fflush(stdout);
-
- pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
- if (opt_log_file)
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\" or \"%s\" for\n"
- "the probable cause of the failure.\n",
- log_file, opt_log_file);
- else
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\" for\n"
- "the probable cause of the failure.\n",
- log_file);
- }
-
-#ifndef WIN32
-
- /*
- * We can't do this on Windows because it will keep the "pg_ctl start"
- * output filename open until the server stops, so we do the \n\n above on
- * that platform. We use a unique filename for "pg_ctl start" that is
- * never reused while the server is running, so it works fine. We could
- * log these commands to a third file, but that just adds complexity.
- */
- if ((log = fopen(log_file, "a")) == NULL)
- pg_fatal("cannot write to log file %s\n", log_file);
- fprintf(log, "\n\n");
- fclose(log);
-#endif
-
- return result == 0;
-}
-
-
-/*
- * pid_lock_file_exists()
- *
- * Checks whether the postmaster.pid file exists.
- */
-bool
-pid_lock_file_exists(const char *datadir)
-{
- 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_fatal("could not open file \"%s\" for reading: %s\n",
- path, getErrorText(errno));
-
- return false;
- }
-
- close(fd);
- return true;
-}
-
-
-/*
- * verify_directories()
- *
- * does all the hectic work of verifying directories and executables
- * of old and new server.
- *
- * NOTE: May update the values of all parameters
- */
-void
-verify_directories(void)
-{
-#ifndef WIN32
- if (access(".", R_OK | W_OK | X_OK) != 0)
-#else
- if (win32_check_directory_write_permissions() != 0)
-#endif
- 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);
-}
-
-
-#ifdef WIN32
-/*
- * win32_check_directory_write_permissions()
- *
- * access() on WIN32 can't check directory permissions, so we have to
- * optionally create, then delete a file to check.
- * http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
- */
-static int
-win32_check_directory_write_permissions(void)
-{
- int fd;
-
- /*
- * We open a file we would normally create anyway. We do this even in
- * 'check' mode, which isn't ideal, but this is the best we can do.
- */
- if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
- return -1;
- close(fd);
-
- return unlink(GLOBALS_DUMP_FILE);
-}
-#endif
-
-
-/*
- * check_data_dir()
- *
- * This function validates the given cluster directory - we search for a
- * small set of subdirectories that we expect to find in a valid $PGDATA
- * directory. If any of the subdirectories are missing (or secured against
- * us) we display an error message and exit()
- *
- */
-static void
-check_data_dir(const char *pg_data)
-{
- char subDirName[MAXPGPATH];
- int subdirnum;
-
- /* start check with top-most directory */
- const char *requiredSubdirs[] = {"", "base", "global", "pg_clog",
- "pg_multixact", "pg_subtrans", "pg_tblspc", "pg_twophase",
- "pg_xlog"};
-
- for (subdirnum = 0;
- subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]);
- ++subdirnum)
- {
- struct stat statBuf;
-
- snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
- /* Win32 can't stat() a directory with a trailing slash. */
- *requiredSubdirs[subdirnum] ? "/" : "",
- requiredSubdirs[subdirnum]);
-
- if (stat(subDirName, &statBuf) != 0)
- report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
- subDirName, getErrorText(errno));
- else if (!S_ISDIR(statBuf.st_mode))
- report_status(PG_FATAL, "%s is not a directory\n",
- subDirName);
- }
-}
-
-
-/*
- * check_bin_dir()
- *
- * This function searches for the executables that we expect to find
- * in the binaries directory. If we find that a required executable
- * is missing (or secured against us), we display an error message and
- * exit().
- */
-static void
-check_bin_dir(ClusterInfo *cluster)
-{
- struct stat statBuf;
-
- /* check bindir */
- if (stat(cluster->bindir, &statBuf) != 0)
- report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
- cluster->bindir, getErrorText(errno));
- else if (!S_ISDIR(statBuf.st_mode))
- report_status(PG_FATAL, "%s is not a directory\n",
- cluster->bindir);
-
- validate_exec(cluster->bindir, "postgres");
- validate_exec(cluster->bindir, "pg_ctl");
- validate_exec(cluster->bindir, "pg_resetxlog");
- if (cluster == &new_cluster)
- {
- /* these are only needed in the new cluster */
- validate_exec(cluster->bindir, "psql");
- validate_exec(cluster->bindir, "pg_dump");
- validate_exec(cluster->bindir, "pg_dumpall");
- }
-}
-
-
-/*
- * validate_exec()
- *
- * validate "path" as an executable file
- */
-static void
-validate_exec(const char *dir, const char *cmdName)
-{
- char path[MAXPGPATH];
- struct stat buf;
-
- snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
-
-#ifdef WIN32
- /* Windows requires a .exe suffix for stat() */
- if (strlen(path) <= strlen(EXE_EXT) ||
- pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
- strlcat(path, EXE_EXT, sizeof(path));
-#endif
-
- /*
- * Ensure that the file exists and is a regular file.
- */
- if (stat(path, &buf) < 0)
- pg_fatal("check for \"%s\" failed: %s\n",
- path, getErrorText(errno));
- else if (!S_ISREG(buf.st_mode))
- pg_fatal("check for \"%s\" failed: not an executable file\n",
- path);
-
- /*
- * Ensure that the file is both executable and readable (required for
- * dynamic loading).
- */
-#ifndef WIN32
- if (access(path, R_OK) != 0)
-#else
- if ((buf.st_mode & S_IRUSR) == 0)
-#endif
- pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
- path);
-
-#ifndef WIN32
- if (access(path, X_OK) != 0)
-#else
- if ((buf.st_mode & S_IXUSR) == 0)
-#endif
- pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
- path);
-}
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
deleted file mode 100644
index 5a8d17ae0f4..00000000000
--- a/contrib/pg_upgrade/file.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * file.c
- *
- * file system operations
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/file.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <fcntl.h>
-
-
-
-#ifndef WIN32
-static int copy_file(const char *fromfile, const char *tofile, bool force);
-#else
-static int win32_pghardlink(const char *src, const char *dst);
-#endif
-
-
-/*
- * copyAndUpdateFile()
- *
- * Copies a relation file from src to dst. If pageConverter is non-NULL, this function
- * uses that pageConverter to do a page-by-page conversion.
- */
-const char *
-copyAndUpdateFile(pageCnvCtx *pageConverter,
- const char *src, const char *dst, bool force)
-{
- 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;
- }
- }
-}
-
-
-/*
- * linkAndUpdateFile()
- *
- * Creates a hard link between the given relation files. We use
- * this function to perform a true in-place update. If the on-disk
- * format of the new cluster is bit-for-bit compatible with the on-disk
- * format of the old cluster, we can simply link each relation
- * instead of copying the data from the old cluster to the new cluster.
- */
-const char *
-linkAndUpdateFile(pageCnvCtx *pageConverter,
- const char *src, const char *dst)
-{
- 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;
-}
-
-
-#ifndef WIN32
-static int
-copy_file(const char *srcfile, const char *dstfile, bool force)
-{
-#define COPY_BUF_SIZE (50 * BLCKSZ)
-
- int src_fd;
- int dest_fd;
- char *buffer;
- int ret = 0;
- int save_errno = 0;
-
- if ((srcfile == NULL) || (dstfile == NULL))
- {
- errno = EINVAL;
- return -1;
- }
-
- if ((src_fd = open(srcfile, O_RDONLY, 0)) < 0)
- return -1;
-
- if ((dest_fd = open(dstfile, O_RDWR | O_CREAT | (force ? 0 : O_EXCL), S_IRUSR | S_IWUSR)) < 0)
- {
- save_errno = errno;
-
- if (src_fd != 0)
- close(src_fd);
-
- errno = save_errno;
- return -1;
- }
-
- buffer = (char *) pg_malloc(COPY_BUF_SIZE);
-
- /* perform data copying i.e read src source, write to destination */
- while (true)
- {
- ssize_t nbytes = read(src_fd, buffer, COPY_BUF_SIZE);
-
- if (nbytes < 0)
- {
- save_errno = errno;
- ret = -1;
- break;
- }
-
- if (nbytes == 0)
- break;
-
- errno = 0;
-
- if (write(dest_fd, buffer, nbytes) != nbytes)
- {
- /* if write didn't set errno, assume problem is no disk space */
- if (errno == 0)
- errno = ENOSPC;
- save_errno = errno;
- ret = -1;
- break;
- }
- }
-
- pg_free(buffer);
-
- if (src_fd != 0)
- close(src_fd);
-
- if (dest_fd != 0)
- close(dest_fd);
-
- if (save_errno != 0)
- errno = save_errno;
-
- return ret;
-}
-#endif
-
-
-void
-check_hard_link(void)
-{
- 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_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);
-}
-
-#ifdef WIN32
-static int
-win32_pghardlink(const char *src, const char *dst)
-{
- /*
- * CreateHardLinkA returns zero for failure
- * http://msdn.microsoft.com/en-us/library/aa363860(VS.85).aspx
- */
- if (CreateHardLinkA(dst, src, NULL) == 0)
- return -1;
- else
- return 0;
-}
-#endif
-
-
-/* fopen() file with no group/other permissions */
-FILE *
-fopen_priv(const char *path, const char *mode)
-{
- mode_t old_umask = umask(S_IRWXG | S_IRWXO);
- FILE *fp;
-
- fp = fopen(path, mode);
- umask(old_umask);
-
- return fp;
-}
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
deleted file mode 100644
index d8009d195d8..00000000000
--- a/contrib/pg_upgrade/function.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * function.c
- *
- * server-side function support
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/function.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include "access/transam.h"
-
-
-/*
- * get_loadable_libraries()
- *
- * Fetch the names of all old libraries containing C-language functions.
- * We will later check that they all exist in the new installation.
- */
-void
-get_loadable_libraries(void)
-{
- 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_dump 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_fatal("Remove the problem functions from the old cluster to continue.\n");
-
- /* 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;
-
- 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);
-}
-
-
-/*
- * check_loadable_libraries()
- *
- * Check that the new cluster contains all required libraries.
- * We do this by actually trying to LOAD each one, thereby testing
- * compatibility as well as presence.
- */
-void
-check_loadable_libraries(void)
-{
- 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;
-
- if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
- 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_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();
-}
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
deleted file mode 100644
index 12549342707..00000000000
--- a/contrib/pg_upgrade/info.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * info.c
- *
- * information support functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/info.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include "access/transam.h"
-
-
-static void create_rel_filename_map(const char *old_data, const char *new_data,
- const DbInfo *old_db, const DbInfo *new_db,
- const RelInfo *old_rel, const RelInfo *new_rel,
- FileNameMap *map);
-static void free_db_and_rel_infos(DbInfoArr *db_arr);
-static void get_db_infos(ClusterInfo *cluster);
-static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
-static void free_rel_infos(RelInfoArr *rel_arr);
-static void print_db_infos(DbInfoArr *dbinfo);
-static void print_rel_infos(RelInfoArr *rel_arr);
-
-
-/*
- * gen_db_file_maps()
- *
- * generates database mappings for "old_db" and "new_db". Returns a malloc'ed
- * array of mappings. nmaps is a return parameter which refers to the number
- * mappings.
- */
-FileNameMap *
-gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
- int *nmaps, const char *old_pgdata, const char *new_pgdata)
-{
- FileNameMap *maps;
- int old_relnum, new_relnum;
- int num_maps = 0;
-
- maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
- old_db->rel_arr.nrels);
-
- /*
- * The old database shouldn't have more relations than the new one.
- * We force the new cluster to have a TOAST table if the old table
- * had one.
- */
- if (old_db->rel_arr.nrels > new_db->rel_arr.nrels)
- pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n",
- old_db->db_name);
-
- /* Drive the loop using new_relnum, which might be higher. */
- for (old_relnum = new_relnum = 0; new_relnum < new_db->rel_arr.nrels;
- new_relnum++)
- {
- RelInfo *old_rel;
- RelInfo *new_rel = &new_db->rel_arr.rels[new_relnum];
-
- /*
- * It is possible that the new cluster has a TOAST table for a table
- * that didn't need one in the old cluster, e.g. 9.0 to 9.1 changed the
- * NUMERIC length computation. Therefore, if we have a TOAST table
- * in the new cluster that doesn't match, skip over it and continue
- * processing. It is possible this TOAST table used an OID that was
- * reserved in the old cluster, but we have no way of testing that,
- * and we would have already gotten an error at the new cluster schema
- * creation stage. Fortunately, since we only restore the OID counter
- * after schema restore, and restore in OID order via pg_dump, a
- * conflict would only happen if the new TOAST table had a very low
- * OID. However, TOAST tables created long after initial table
- * creation can have any OID, particularly after OID wraparound.
- */
- if (old_relnum == old_db->rel_arr.nrels)
- {
- if (strcmp(new_rel->nspname, "pg_toast") == 0)
- continue;
- else
- pg_fatal("Extra non-TOAST relation found in database \"%s\": new OID %d\n",
- old_db->db_name, new_rel->reloid);
- }
-
- old_rel = &old_db->rel_arr.rels[old_relnum];
-
- if (old_rel->reloid != new_rel->reloid)
- {
- if (strcmp(new_rel->nspname, "pg_toast") == 0)
- continue;
- else
- 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_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++;
- old_relnum++;
- }
-
- /* Did we fail to exhaust the old array? */
- if (old_relnum != old_db->rel_arr.nrels)
- pg_fatal("old and new databases \"%s\" have a mismatched number of relations\n",
- old_db->db_name);
-
- *nmaps = num_maps;
- return maps;
-}
-
-
-/*
- * create_rel_filename_map()
- *
- * fills a file node map structure and returns it in "map".
- */
-static void
-create_rel_filename_map(const char *old_data, const char *new_data,
- const DbInfo *old_db, const DbInfo *new_db,
- const RelInfo *old_rel, const RelInfo *new_rel,
- FileNameMap *map)
-{
- if (strlen(old_rel->tablespace) == 0)
- {
- /*
- * relation belongs to the default tablespace, hence relfiles should
- * exist in the data directories.
- */
- map->old_tablespace = old_data;
- map->new_tablespace = new_data;
- map->old_tablespace_suffix = "/base";
- map->new_tablespace_suffix = "/base";
- }
- else
- {
- /* relation belongs to a tablespace, so use the tablespace location */
- map->old_tablespace = old_rel->tablespace;
- map->new_tablespace = new_rel->tablespace;
- map->old_tablespace_suffix = old_cluster.tablespace_suffix;
- map->new_tablespace_suffix = new_cluster.tablespace_suffix;
- }
-
- map->old_db_oid = old_db->db_oid;
- map->new_db_oid = new_db->db_oid;
-
- /*
- * old_relfilenode might differ from pg_class.oid (and hence
- * new_relfilenode) because of CLUSTER, REINDEX, or VACUUM FULL.
- */
- map->old_relfilenode = old_rel->relfilenode;
-
- /* new_relfilenode will match old and new pg_class.oid */
- map->new_relfilenode = new_rel->relfilenode;
-
- /* used only for logging and error reporing, old/new are identical */
- map->nspname = old_rel->nspname;
- map->relname = old_rel->relname;
-}
-
-
-void
-print_maps(FileNameMap *maps, int n_maps, const char *db_name)
-{
- 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");
- }
-}
-
-
-/*
- * get_db_and_rel_infos()
- *
- * higher level routine to generate dbinfos for the database running
- * on the given "port". Assumes that server is already running.
- */
-void
-get_db_and_rel_infos(ClusterInfo *cluster)
-{
- 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);
-}
-
-
-/*
- * get_db_infos()
- *
- * Scans pg_database system catalog and populates all user
- * databases.
- */
-static void
-get_db_infos(ClusterInfo *cluster)
-{
- PGconn *conn = connectToServer(cluster, "template1");
- PGresult *res;
- int ntups;
- int tupnum;
- DbInfo *dbinfos;
- int i_datname,
- i_oid,
- i_encoding,
- i_datcollate,
- i_datctype,
- i_spclocation;
- char query[QUERY_ALLOC];
-
- snprintf(query, sizeof(query),
- "SELECT d.oid, d.datname, d.encoding, d.datcollate, d.datctype, "
- "%s AS spclocation "
- "FROM pg_catalog.pg_database d "
- " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
- " ON d.dattablespace = t.oid "
- "WHERE d.datallowconn = true "
- /* we don't preserve pg_database.oid so we sort by name */
- "ORDER BY 2",
- /* 9.2 removed the spclocation column */
- (GET_MAJOR_VERSION(cluster->major_version) <= 901) ?
- "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid)");
-
- res = executeQueryOrDie(conn, "%s", query);
-
- i_oid = PQfnumber(res, "oid");
- i_datname = PQfnumber(res, "datname");
- i_encoding = PQfnumber(res, "encoding");
- i_datcollate = PQfnumber(res, "datcollate");
- i_datctype = PQfnumber(res, "datctype");
- i_spclocation = PQfnumber(res, "spclocation");
-
- ntups = PQntuples(res);
- dbinfos = (DbInfo *) pg_malloc(sizeof(DbInfo) * ntups);
-
- for (tupnum = 0; tupnum < ntups; tupnum++)
- {
- dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
- dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
- dbinfos[tupnum].db_encoding = atoi(PQgetvalue(res, tupnum, i_encoding));
- dbinfos[tupnum].db_collate = pg_strdup(PQgetvalue(res, tupnum, i_datcollate));
- dbinfos[tupnum].db_ctype = pg_strdup(PQgetvalue(res, tupnum, i_datctype));
- snprintf(dbinfos[tupnum].db_tablespace, sizeof(dbinfos[tupnum].db_tablespace), "%s",
- PQgetvalue(res, tupnum, i_spclocation));
- }
- PQclear(res);
-
- PQfinish(conn);
-
- cluster->dbarr.dbs = dbinfos;
- cluster->dbarr.ndbs = ntups;
-}
-
-
-/*
- * get_rel_infos()
- *
- * gets the relinfos for all the user tables of the database referred
- * by "db".
- *
- * NOTE: we assume that relations/entities with oids greater than
- * FirstNormalObjectId belongs to the user
- */
-static void
-get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
-{
- PGconn *conn = connectToServer(cluster,
- dbinfo->db_name);
- PGresult *res;
- RelInfo *relinfos;
- int ntups;
- int relnum;
- int num_rels = 0;
- char *nspname = NULL;
- char *relname = NULL;
- char *tablespace = NULL;
- int i_spclocation,
- i_nspname,
- i_relname,
- i_oid,
- i_relfilenode,
- i_reltablespace;
- char query[QUERY_ALLOC];
- char *last_namespace = NULL,
- *last_tablespace = NULL;
-
- /*
- * pg_largeobject contains user data that does not appear in pg_dump
- * --schema-only output, so we have to copy that system table heap and
- * index. We could grab the pg_largeobject oids from template1, but it is
- * easy to treat it as a normal table. Order by oid so we can join old/new
- * structures efficiently.
- */
-
- snprintf(query, sizeof(query),
- /* get regular heap */
- "WITH regular_heap (reloid) AS ( "
- " SELECT c.oid "
- " FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
- " ON c.relnamespace = n.oid "
- " LEFT OUTER JOIN pg_catalog.pg_index i "
- " ON c.oid = i.indexrelid "
- " WHERE relkind IN ('r', 'm', 'i', 'S') AND "
- /*
- * pg_dump only dumps valid indexes; testing indisready is necessary in
- * 9.2, and harmless in earlier/later versions.
- */
- " i.indisvalid IS DISTINCT FROM false AND "
- " i.indisready IS DISTINCT FROM false AND "
- /* exclude possible orphaned temp tables */
- " ((n.nspname !~ '^pg_temp_' AND "
- " n.nspname !~ '^pg_toast_temp_' AND "
- /* skip pg_toast because toast index have relkind == 'i', not 't' */
- " n.nspname NOT IN ('pg_catalog', 'information_schema', "
- " 'binary_upgrade', 'pg_toast') AND "
- " c.oid >= %u) OR "
- " (n.nspname = 'pg_catalog' AND "
- " relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) ))), "
- /*
- * We have to gather the TOAST tables in later steps because we
- * can't schema-qualify TOAST tables.
- */
- /* get TOAST heap */
- " toast_heap (reloid) AS ( "
- " SELECT reltoastrelid "
- " FROM regular_heap JOIN pg_catalog.pg_class c "
- " ON regular_heap.reloid = c.oid "
- " AND c.reltoastrelid != %u), "
- /* get indexes on regular and TOAST heap */
- " all_index (reloid) AS ( "
- " SELECT indexrelid "
- " FROM pg_index "
- " WHERE indisvalid "
- " AND indrelid IN (SELECT reltoastrelid "
- " FROM (SELECT reloid FROM regular_heap "
- " UNION ALL "
- " SELECT reloid FROM toast_heap) all_heap "
- " JOIN pg_catalog.pg_class c "
- " ON all_heap.reloid = c.oid "
- " AND c.reltoastrelid != %u)) "
- /* get all rels */
- "SELECT c.oid, n.nspname, c.relname, "
- " c.relfilenode, c.reltablespace, %s "
- "FROM (SELECT reloid FROM regular_heap "
- " UNION ALL "
- " SELECT reloid FROM toast_heap "
- " UNION ALL "
- " SELECT reloid FROM all_index) all_rels "
- " JOIN pg_catalog.pg_class c "
- " ON all_rels.reloid = c.oid "
- " JOIN pg_catalog.pg_namespace n "
- " ON c.relnamespace = n.oid "
- " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
- " ON c.reltablespace = t.oid "
- /* we preserve pg_class.oid so we sort by it to match old/new */
- "ORDER BY 1;",
- FirstNormalObjectId,
- /* does pg_largeobject_metadata need to be migrated? */
- (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
- "" : ", 'pg_largeobject_metadata', 'pg_largeobject_metadata_oid_index'",
- InvalidOid, InvalidOid,
- /* 9.2 removed the spclocation column */
- (GET_MAJOR_VERSION(cluster->major_version) <= 901) ?
- "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation");
-
- res = executeQueryOrDie(conn, "%s", query);
-
- ntups = PQntuples(res);
-
- relinfos = (RelInfo *) pg_malloc(sizeof(RelInfo) * ntups);
-
- i_oid = PQfnumber(res, "oid");
- i_nspname = PQfnumber(res, "nspname");
- i_relname = PQfnumber(res, "relname");
- i_relfilenode = PQfnumber(res, "relfilenode");
- i_reltablespace = PQfnumber(res, "reltablespace");
- i_spclocation = PQfnumber(res, "spclocation");
-
- for (relnum = 0; relnum < ntups; relnum++)
- {
- RelInfo *curr = &relinfos[num_rels++];
-
- curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
-
- nspname = PQgetvalue(res, relnum, i_nspname);
- curr->nsp_alloc = false;
-
- /*
- * Many of the namespace and tablespace strings are identical, so we
- * try to reuse the allocated string pointers where possible to reduce
- * memory consumption.
- */
- /* Can we reuse the previous string allocation? */
- if (last_namespace && strcmp(nspname, last_namespace) == 0)
- curr->nspname = last_namespace;
- else
- {
- last_namespace = curr->nspname = pg_strdup(nspname);
- curr->nsp_alloc = true;
- }
-
- relname = PQgetvalue(res, relnum, i_relname);
- curr->relname = pg_strdup(relname);
-
- curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
- curr->tblsp_alloc = false;
-
- /* Is the tablespace oid non-zero? */
- if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
- {
- /*
- * The tablespace location might be "", meaning the cluster
- * default location, i.e. pg_default or pg_global.
- */
- tablespace = PQgetvalue(res, relnum, i_spclocation);
-
- /* Can we reuse the previous string allocation? */
- if (last_tablespace && strcmp(tablespace, last_tablespace) == 0)
- curr->tablespace = last_tablespace;
- else
- {
- last_tablespace = curr->tablespace = pg_strdup(tablespace);
- curr->tblsp_alloc = true;
- }
- }
- else
- /* A zero reltablespace oid indicates the database tablespace. */
- curr->tablespace = dbinfo->db_tablespace;
- }
- PQclear(res);
-
- PQfinish(conn);
-
- dbinfo->rel_arr.rels = relinfos;
- dbinfo->rel_arr.nrels = num_rels;
-}
-
-
-static void
-free_db_and_rel_infos(DbInfoArr *db_arr)
-{
- int dbnum;
-
- for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
- {
- free_rel_infos(&db_arr->dbs[dbnum].rel_arr);
- pg_free(db_arr->dbs[dbnum].db_name);
- }
- pg_free(db_arr->dbs);
- db_arr->dbs = NULL;
- db_arr->ndbs = 0;
-}
-
-
-static void
-free_rel_infos(RelInfoArr *rel_arr)
-{
- int relnum;
-
- for (relnum = 0; relnum < rel_arr->nrels; relnum++)
- {
- if (rel_arr->rels[relnum].nsp_alloc)
- pg_free(rel_arr->rels[relnum].nspname);
- pg_free(rel_arr->rels[relnum].relname);
- if (rel_arr->rels[relnum].tblsp_alloc)
- pg_free(rel_arr->rels[relnum].tablespace);
- }
- pg_free(rel_arr->rels);
- rel_arr->nrels = 0;
-}
-
-
-static void
-print_db_infos(DbInfoArr *db_arr)
-{
- int dbnum;
-
- for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
- {
- pg_log(PG_VERBOSE, "Database: %s\n", db_arr->dbs[dbnum].db_name);
- print_rel_infos(&db_arr->dbs[dbnum].rel_arr);
- pg_log(PG_VERBOSE, "\n\n");
- }
-}
-
-
-static void
-print_rel_infos(RelInfoArr *rel_arr)
-{
- int relnum;
-
- for (relnum = 0; relnum < rel_arr->nrels; relnum++)
- pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n",
- rel_arr->rels[relnum].nspname,
- rel_arr->rels[relnum].relname,
- rel_arr->rels[relnum].reloid,
- rel_arr->rels[relnum].tablespace);
-}
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
deleted file mode 100644
index 742d133e391..00000000000
--- a/contrib/pg_upgrade/option.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * opt.c
- *
- * options functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/option.c
- */
-
-#include "postgres_fe.h"
-
-#include "miscadmin.h"
-#include "getopt_long.h"
-
-#include "pg_upgrade.h"
-
-#include <time.h>
-#include <sys/types.h>
-#ifdef WIN32
-#include <io.h>
-#endif
-
-
-static void usage(void);
-static void check_required_directory(char **dirpath, char **configpath,
- char *envVarName, char *cmdLineOption, char *description);
-#define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false"
-
-
-UserOpts user_opts;
-
-
-/*
- * parseCommandLine()
- *
- * Parses the command line (argc, argv[]) and loads structures
- */
-void
-parseCommandLine(int argc, char *argv[])
-{
- 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'},
-
- {"username", 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], "-?") == 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_fatal("%s: cannot be run as root\n", os_info.progname);
-
- if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
- 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':
- /* append option? */
- if (!old_cluster.pgopts)
- old_cluster.pgopts = pg_strdup(optarg);
- else
- {
- char *old_pgopts = old_cluster.pgopts;
-
- old_cluster.pgopts = psprintf("%s %s", old_pgopts, optarg);
- free(old_pgopts);
- }
- break;
-
- case 'O':
- /* append option? */
- if (!new_cluster.pgopts)
- new_cluster.pgopts = pg_strdup(optarg);
- else
- {
- char *new_pgopts = new_cluster.pgopts;
-
- new_cluster.pgopts = psprintf("%s %s", new_pgopts, optarg);
- free(new_pgopts);
- }
- 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 (added in PG 9.2).
- */
- case 'p':
- if ((old_cluster.port = atoi(optarg)) <= 0)
- {
- pg_fatal("invalid old port number\n");
- exit(1);
- }
- break;
-
- case 'P':
- if ((new_cluster.port = atoi(optarg)) <= 0)
- {
- 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);
- os_info.user_specified = true;
-
- /*
- * 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_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_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);
- }
-
- /* Turn off read-only mode; add prefix to PGOPTIONS? */
- if (getenv("PGOPTIONS"))
- {
- char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
- getenv("PGOPTIONS"));
-
- pg_putenv("PGOPTIONS", pgoptions);
- pfree(pgoptions);
- }
- else
- pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY);
-
- /* 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");
-
-#ifdef WIN32
- /*
- * On Windows, initdb --sync-only will fail with a "Permission denied"
- * error on file pg_upgrade_utility.log if pg_upgrade is run inside
- * the new cluster directory, so we do a check here.
- */
- {
- char cwd[MAXPGPATH], new_cluster_pgdata[MAXPGPATH];
-
- strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
- canonicalize_path(new_cluster_pgdata);
-
- if (!getcwd(cwd, MAXPGPATH))
- pg_fatal("cannot find current directory\n");
- canonicalize_path(cwd);
- if (path_is_prefix_of_path(new_cluster_pgdata, cwd))
- pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows\n");
- }
-#endif
-}
-
-
-static void
-usage(void)
-{
- printf(_("pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n\
-\nUsage:\n\
- pg_upgrade [OPTION]...\n\
-\n\
-Options:\n\
- -b, --old-bindir=BINDIR old cluster executable directory\n\
- -B, --new-bindir=BINDIR new cluster executable directory\n\
- -c, --check check clusters only, don't change any data\n\
- -d, --old-datadir=DATADIR old cluster data directory\n\
- -D, --new-datadir=DATADIR new cluster data directory\n\
- -j, --jobs number of simultaneous processes or threads to use\n\
- -k, --link link instead of copying files to new cluster\n\
- -o, --old-options=OPTIONS old cluster options to pass to the server\n\
- -O, --new-options=OPTIONS new cluster options to pass to the server\n\
- -p, --old-port=PORT old cluster port number (default %d)\n\
- -P, --new-port=PORT new cluster port number (default %d)\n\
- -r, --retain retain SQL and log files after success\n\
- -U, --username=NAME cluster superuser (default \"%s\")\n\
- -v, --verbose enable verbose internal logging\n\
- -V, --version display version information, then exit\n\
- -?, --help show this help, then exit\n\
-\n\
-Before running pg_upgrade you must:\n\
- create a new database cluster (using the new version of initdb)\n\
- shutdown the postmaster servicing the old cluster\n\
- shutdown the postmaster servicing the new cluster\n\
-\n\
-When you run pg_upgrade, you must provide the following information:\n\
- the data directory for the old cluster (-d DATADIR)\n\
- the data directory for the new cluster (-D DATADIR)\n\
- the \"bin\" directory for the old version (-b BINDIR)\n\
- the \"bin\" directory for the new version (-B BINDIR)\n\
-\n\
-For example:\n\
- pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n\
-or\n"), old_cluster.port, new_cluster.port, os_info.user);
-#ifndef WIN32
- printf(_("\
- $ export PGDATAOLD=oldCluster/data\n\
- $ export PGDATANEW=newCluster/data\n\
- $ export PGBINOLD=oldCluster/bin\n\
- $ export PGBINNEW=newCluster/bin\n\
- $ pg_upgrade\n"));
-#else
- printf(_("\
- C:\\> set PGDATAOLD=oldCluster/data\n\
- C:\\> set PGDATANEW=newCluster/data\n\
- C:\\> set PGBINOLD=oldCluster/bin\n\
- C:\\> set PGBINNEW=newCluster/bin\n\
- C:\\> pg_upgrade\n"));
-#endif
- printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
-}
-
-
-/*
- * check_required_directory()
- *
- * Checks a directory option.
- * dirpath - the directory name supplied on the command line
- * configpath - optional configuration directory
- * envVarName - the name of an environment variable to get if dirpath is NULL
- * cmdLineOption - the command line option corresponds to this directory (-o, -O, -n, -N)
- * description - a description of this directory option
- *
- * We use the last two arguments to construct a meaningful error message if the
- * user hasn't provided the required directory name.
- */
-static void
-check_required_directory(char **dirpath, char **configpath,
- char *envVarName, char *cmdLineOption,
- char *description)
-{
- if (*dirpath == NULL || strlen(*dirpath) == 0)
- {
- const char *envVar;
-
- if ((envVar = getenv(envVarName)) && strlen(envVar))
- {
- *dirpath = pg_strdup(envVar);
- if (configpath)
- *configpath = pg_strdup(envVar);
- }
- else
- pg_fatal("You must identify the directory where the %s.\n"
- "Please use the %s command-line option or the %s environment variable.\n",
- description, cmdLineOption, envVarName);
- }
-
- /*
- * Trim off any trailing path separators because we construct paths by
- * appending to this path.
- */
-#ifndef WIN32
- if ((*dirpath)[strlen(*dirpath) - 1] == '/')
-#else
- if ((*dirpath)[strlen(*dirpath) - 1] == '/' ||
- (*dirpath)[strlen(*dirpath) - 1] == '\\')
-#endif
- (*dirpath)[strlen(*dirpath) - 1] = 0;
-}
-
-/*
- * adjust_data_dir
- *
- * If a configuration-only directory was specified, find the real data dir
- * by quering the running server. This has limited checking because we
- * can't check for a running server because we can't find postmaster.pid.
- */
-void
-adjust_data_dir(ClusterInfo *cluster)
-{
- 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/postgres\" -D \"%s\" -C data_directory",
- cluster->bindir, cluster->pgconfig);
-
- if ((output = popen(cmd, "r")) == NULL ||
- fgets(cmd_output, sizeof(cmd_output), output) == NULL)
- 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();
-}
-
-
-/*
- * get_sock_dir
- *
- * Identify the socket directory to use for this cluster. If we're doing
- * a live check (old cluster only), we need to find out where the postmaster
- * is listening. Otherwise, we're going to put the socket into the current
- * directory.
- */
-void
-get_sock_dir(ClusterInfo *cluster, bool live_check)
-{
-#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_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_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_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_strdup(line);
- /* strip off newline */
- if (strchr(cluster->sockdir, '\n') != NULL)
- *strchr(cluster->sockdir, '\n') = '\0';
- }
- }
- 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
-}
diff --git a/contrib/pg_upgrade/page.c b/contrib/pg_upgrade/page.c
deleted file mode 100644
index 1cfc10f8a2a..00000000000
--- a/contrib/pg_upgrade/page.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * page.c
- *
- * per-page conversion operations
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/page.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include "storage/bufpage.h"
-
-
-#ifdef PAGE_CONVERSION
-
-
-static void getPageVersion(
- uint16 *version, const char *pathName);
-static pageCnvCtx *loadConverterPlugin(
- uint16 newPageVersion, uint16 oldPageVersion);
-
-
-/*
- * setupPageConverter()
- *
- * This function determines the PageLayoutVersion of the old cluster and
- * the PageLayoutVersion of the new cluster. If the versions differ, this
- * function loads a converter plugin and returns a pointer to a pageCnvCtx
- * object (in *result) that knows how to convert pages from the old format
- * to the new format. If the versions are identical, this function just
- * returns a NULL pageCnvCtx pointer to indicate that page-by-page conversion
- * is not required.
- */
-pageCnvCtx *
-setupPageConverter(void)
-{
- uint16 oldPageVersion;
- uint16 newPageVersion;
- pageCnvCtx *converter;
- const char *msg;
- char dstName[MAXPGPATH];
- char srcName[MAXPGPATH];
-
- snprintf(dstName, sizeof(dstName), "%s/global/%u", new_cluster.pgdata,
- new_cluster.pg_database_oid);
- snprintf(srcName, sizeof(srcName), "%s/global/%u", old_cluster.pgdata,
- old_cluster.pg_database_oid);
-
- getPageVersion(&oldPageVersion, srcName);
- getPageVersion(&newPageVersion, dstName);
-
- /*
- * If the old cluster and new cluster use the same page layouts, then we
- * don't need a page converter.
- */
- if (newPageVersion != oldPageVersion)
- {
- /*
- * The clusters use differing page layouts, see if we can find a
- * plugin that knows how to convert from the old page layout to the
- * new page layout.
- */
-
- if ((converter = loadConverterPlugin(newPageVersion, oldPageVersion)) == NULL)
- pg_fatal("could not find plugin to convert from old page layout to new page layout\n");
-
- return converter;
- }
- else
- return NULL;
-}
-
-
-/*
- * getPageVersion()
- *
- * Retrieves the PageLayoutVersion for the given relation.
- *
- * Returns NULL on success (and stores the PageLayoutVersion at *version),
- * if an error occurs, this function returns an error message (in the form
- * of a null-terminated string).
- */
-static void
-getPageVersion(uint16 *version, const char *pathName)
-{
- int relfd;
- PageHeaderData page;
- ssize_t bytesRead;
-
- if ((relfd = open(pathName, O_RDONLY, 0)) < 0)
- pg_fatal("could not open relation %s\n", pathName);
-
- if ((bytesRead = read(relfd, &page, sizeof(page))) != sizeof(page))
- pg_fatal("could not read page header of %s\n", pathName);
-
- *version = PageGetPageLayoutVersion(&page);
-
- close(relfd);
-
- return;
-}
-
-
-/*
- * loadConverterPlugin()
- *
- * This function loads a page-converter plugin library and grabs a
- * pointer to each of the (interesting) functions provided by that
- * plugin. The name of the plugin library is derived from the given
- * newPageVersion and oldPageVersion. If a plugin is found, this
- * function returns a pointer to a pageCnvCtx object (which will contain
- * a collection of plugin function pointers). If the required plugin
- * is not found, this function returns NULL.
- */
-static pageCnvCtx *
-loadConverterPlugin(uint16 newPageVersion, uint16 oldPageVersion)
-{
- char pluginName[MAXPGPATH];
- void *plugin;
-
- /*
- * Try to find a plugin that can convert pages of oldPageVersion into
- * pages of newPageVersion. For example, if we oldPageVersion = 3 and
- * newPageVersion is 4, we search for a plugin named:
- * plugins/convertLayout_3_to_4.dll
- */
-
- /*
- * FIXME: we are searching for plugins relative to the current directory,
- * we should really search relative to our own executable instead.
- */
- snprintf(pluginName, sizeof(pluginName), "./plugins/convertLayout_%d_to_%d%s",
- oldPageVersion, newPageVersion, DLSUFFIX);
-
- if ((plugin = pg_dlopen(pluginName)) == NULL)
- return NULL;
- else
- {
- pageCnvCtx *result = (pageCnvCtx *) pg_malloc(sizeof(*result));
-
- result->old.PageVersion = oldPageVersion;
- result->new.PageVersion = newPageVersion;
-
- result->startup = (pluginStartup) pg_dlsym(plugin, "init");
- result->convertFile = (pluginConvertFile) pg_dlsym(plugin, "convertFile");
- result->convertPage = (pluginConvertPage) pg_dlsym(plugin, "convertPage");
- result->shutdown = (pluginShutdown) pg_dlsym(plugin, "fini");
- result->pluginData = NULL;
-
- /*
- * If the plugin has exported an initializer, go ahead and invoke it.
- */
- if (result->startup)
- result->startup(MIGRATOR_API_VERSION, &result->pluginVersion,
- newPageVersion, oldPageVersion, &result->pluginData);
-
- return result;
- }
-}
-
-#endif
diff --git a/contrib/pg_upgrade/parallel.c b/contrib/pg_upgrade/parallel.c
deleted file mode 100644
index 6da996559a4..00000000000
--- a/contrib/pg_upgrade/parallel.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * parallel.c
- *
- * multi-process support
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/parallel.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#ifdef WIN32
-#include <io.h>
-#endif
-
-static int parallel_jobs;
-
-#ifdef WIN32
-/*
- * Array holding all active threads. There can't be any gaps/zeros so
- * it can be passed to WaitForMultipleObjects(). We use two arrays
- * so the thread_handles array can be passed to WaitForMultipleObjects().
- */
-HANDLE *thread_handles;
-
-typedef struct
-{
- char *log_file;
- char *opt_log_file;
- char *cmd;
-} exec_thread_arg;
-
-typedef struct
-{
- DbInfoArr *old_db_arr;
- DbInfoArr *new_db_arr;
- char *old_pgdata;
- char *new_pgdata;
- char *old_tablespace;
-} transfer_thread_arg;
-
-exec_thread_arg **exec_thread_args;
-transfer_thread_arg **transfer_thread_args;
-
-/* track current thread_args struct so reap_child() can be used for all cases */
-void **cur_thread_args;
-
-DWORD win32_exec_prog(exec_thread_arg *args);
-DWORD win32_transfer_all_new_dbs(transfer_thread_arg *args);
-#endif
-
-/*
- * parallel_exec_prog
- *
- * This has the same API as exec_prog, except it does parallel execution,
- * and therefore must throw errors and doesn't return an error status.
- */
-void
-parallel_exec_prog(const char *log_file, const char *opt_log_file,
- const char *fmt,...)
-{
- va_list args;
- char cmd[MAX_STRING];
-
-#ifndef WIN32
- pid_t child;
-#else
- HANDLE child;
- exec_thread_arg *new_arg;
-#endif
-
- va_start(args, fmt);
- vsnprintf(cmd, sizeof(cmd), fmt, args);
- va_end(args);
-
- if (user_opts.jobs <= 1)
- /* throw_error must be true to allow jobs */
- exec_prog(log_file, opt_log_file, true, "%s", cmd);
- else
- {
- /* parallel */
-#ifdef WIN32
- if (thread_handles == NULL)
- thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
-
- if (exec_thread_args == NULL)
- {
- int i;
-
- exec_thread_args = pg_malloc(user_opts.jobs * sizeof(exec_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++)
- exec_thread_args[i] = pg_malloc0(sizeof(exec_thread_arg));
- }
-
- cur_thread_args = (void **) exec_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)
- /* use _exit to skip atexit() functions */
- _exit(!exec_prog(log_file, opt_log_file, true, "%s", cmd));
- else if (child < 0)
- /* fork failed */
- pg_fatal("could not create worker process: %s\n", strerror(errno));
-#else
- /* empty array element are always at the end */
- new_arg = exec_thread_args[parallel_jobs - 1];
-
- /* Can only pass one pointer into the function, so use a struct */
- if (new_arg->log_file)
- pg_free(new_arg->log_file);
- new_arg->log_file = pg_strdup(log_file);
- if (new_arg->opt_log_file)
- pg_free(new_arg->opt_log_file);
- new_arg->opt_log_file = opt_log_file ? pg_strdup(opt_log_file) : NULL;
- if (new_arg->cmd)
- pg_free(new_arg->cmd);
- new_arg->cmd = pg_strdup(cmd);
-
- child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog,
- new_arg, 0, NULL);
- if (child == 0)
- pg_fatal("could not create worker thread: %s\n", strerror(errno));
-
- thread_handles[parallel_jobs - 1] = child;
-#endif
- }
-
- return;
-}
-
-
-#ifdef WIN32
-DWORD
-win32_exec_prog(exec_thread_arg *args)
-{
- int ret;
-
- ret = !exec_prog(args->log_file, args->opt_log_file, true, "%s", args->cmd);
-
- /* terminates thread */
- return ret;
-}
-#endif
-
-
-/*
- * parallel_transfer_all_new_dbs
- *
- * This has the same API as transfer_all_new_dbs, except it does parallel execution
- * by transfering multiple tablespaces in parallel
- */
-void
-parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
- char *old_pgdata, char *new_pgdata,
- char *old_tablespace)
-{
-#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
- if (thread_handles == NULL)
- thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
-
- if (transfer_thread_args == NULL)
- {
- int i;
-
- 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_malloc0(sizeof(transfer_thread_arg));
- }
-
- 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_fatal("could not create worker process: %s\n", strerror(errno));
-#else
- /* empty array element are always at the end */
- 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;
- if (new_arg->old_pgdata)
- pg_free(new_arg->old_pgdata);
- new_arg->old_pgdata = pg_strdup(old_pgdata);
- if (new_arg->new_pgdata)
- pg_free(new_arg->new_pgdata);
- new_arg->new_pgdata = pg_strdup(new_pgdata);
- if (new_arg->old_tablespace)
- pg_free(new_arg->old_tablespace);
- new_arg->old_tablespace = old_tablespace ? pg_strdup(old_tablespace) : NULL;
-
- child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_transfer_all_new_dbs,
- new_arg, 0, NULL);
- if (child == 0)
- pg_fatal("could not create worker thread: %s\n", strerror(errno));
-
- thread_handles[parallel_jobs - 1] = child;
-#endif
- }
-
- return;
-}
-
-
-#ifdef WIN32
-DWORD
-win32_transfer_all_new_dbs(transfer_thread_arg *args)
-{
- transfer_all_new_dbs(args->old_db_arr, args->new_db_arr, args->old_pgdata,
- args->new_pgdata, args->old_tablespace);
-
- /* terminates thread */
- return 0;
-}
-#endif
-
-
-/*
- * collect status from a completed worker child
- */
-bool
-reap_child(bool wait_for_child)
-{
-#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_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_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];
-
- /*
- * Move last active thead arg struct into the now-dead slot, and the
- * now-dead slot to the end for reuse by the next thread. Though the
- * thread struct is in use by another thread, we can safely swap the
- * struct pointers within the array.
- */
- 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;
-}
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
deleted file mode 100644
index 78bd29fb957..00000000000
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * pg_upgrade.c
- *
- * main source file
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/pg_upgrade.c
- */
-
-/*
- * To simplify the upgrade process, we force certain system values to be
- * identical between old and new clusters:
- *
- * We control all assignments of pg_class.oid (and relfilenode) so toast
- * oids are the same between old and new clusters. This is important
- * because toast oids are stored as toast pointers in user tables.
- *
- * While pg_class.oid and pg_class.relfilenode are initially the same
- * in a cluster, they can diverge due to CLUSTER, REINDEX, or VACUUM
- * FULL. In the new cluster, pg_class.oid and pg_class.relfilenode will
- * be the same and will match the old pg_class.oid value. Because of
- * this, old/new pg_class.relfilenode values will not match if CLUSTER,
- * REINDEX, or VACUUM FULL have been performed in the old cluster.
- *
- * We control all assignments of pg_type.oid because these oids are stored
- * in user composite type values.
- *
- * We control all assignments of pg_enum.oid because these oids are stored
- * in user tables as enum values.
- *
- * We control all assignments of pg_authid.oid because these oids are stored
- * in pg_largeobject_metadata.
- */
-
-
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-#include "common/restricted_token.h"
-
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-
-static void prepare_new_cluster(void);
-static void prepare_new_databases(void);
-static void create_new_objects(void);
-static void copy_clog_xlog_xid(void);
-static void set_frozenxids(bool minmxid_only);
-static void setup(char *argv0, bool *live_check);
-static void cleanup(void);
-
-ClusterInfo old_cluster,
- new_cluster;
-OSInfo os_info;
-
-char *output_files[] = {
- SERVER_LOG_FILE,
-#ifdef WIN32
- /* unique file for pg_ctl start */
- SERVER_START_LOG_FILE,
-#endif
- UTILITY_LOG_FILE,
- INTERNAL_LOG_FILE,
- NULL
-};
-
-
-int
-main(int argc, char **argv)
-{
- char *analyze_script_file_name = NULL;
- char *deletion_script_file_name = NULL;
- bool live_check = false;
-
- parseCommandLine(argc, argv);
-
- get_restricted_token(os_info.progname);
-
- adjust_data_dir(&old_cluster);
- adjust_data_dir(&new_cluster);
-
- setup(argv[0], &live_check);
-
- output_check_banner(live_check);
-
- check_cluster_versions();
-
- get_sock_dir(&old_cluster, live_check);
- get_sock_dir(&new_cluster, false);
-
- check_cluster_compatibility(live_check);
-
- check_and_dump_old_cluster(live_check);
-
-
- /* -- NEW -- */
- start_postmaster(&new_cluster, true);
-
- check_new_cluster();
- report_clusters_compatible();
-
- pg_log(PG_REPORT, "\nPerforming Upgrade\n");
- pg_log(PG_REPORT, "------------------\n");
-
- prepare_new_cluster();
-
- stop_postmaster(false);
-
- /*
- * Destructive Changes to New Cluster
- */
-
- copy_clog_xlog_xid();
-
- /* New now using xids of the old system */
-
- /* -- NEW -- */
- start_postmaster(&new_cluster, true);
-
- prepare_new_databases();
-
- create_new_objects();
-
- stop_postmaster(false);
-
- /*
- * Most failures happen in create_new_objects(), which has completed at
- * this point. We do this here because it is just before linking, which
- * will link the old and new cluster data files, preventing the old
- * cluster from being safely started once the new cluster is started.
- */
- if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
- disable_old_cluster();
-
- transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr,
- old_cluster.pgdata, new_cluster.pgdata);
-
- /*
- * Assuming OIDs are only used in system tables, there is no need to
- * restore the OID counter because we have not transferred any OIDs from
- * the old system, but we do it anyway just in case. We do it late here
- * because there is no need to have the schema load use new oids.
- */
- prep_status("Setting next OID for new cluster");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -o %u \"%s\"",
- new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
- new_cluster.pgdata);
- check_ok();
-
- prep_status("Sync data directory to disk");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/initdb\" --sync-only \"%s\"", new_cluster.bindir,
- new_cluster.pgdata);
- check_ok();
-
- create_script_for_cluster_analyze(&analyze_script_file_name);
- create_script_for_old_cluster_deletion(&deletion_script_file_name);
-
- issue_warnings();
-
- pg_log(PG_REPORT, "\nUpgrade Complete\n");
- pg_log(PG_REPORT, "----------------\n");
-
- output_completion_banner(analyze_script_file_name,
- deletion_script_file_name);
-
- pg_free(analyze_script_file_name);
- pg_free(deletion_script_file_name);
-
- cleanup();
-
- return 0;
-}
-
-
-static void
-setup(char *argv0, bool *live_check)
-{
- char exec_path[MAXPGPATH]; /* full path to my executable */
-
- /*
- * make sure the user has a clean environment, otherwise, we may confuse
- * libpq when we connect to one (or both) of the servers.
- */
- check_pghost_envvar();
-
- verify_directories();
-
- /* no postmasters should be running, except for a live check */
- if (pid_lock_file_exists(old_cluster.pgdata))
- {
- /*
- * If we have a postmaster.pid file, try to start the server. If it
- * starts, the pid file was stale, so stop the server. If it doesn't
- * start, assume the server is running. If the pid file is left over
- * from a server crash, this also allows any committed transactions
- * stored in the WAL to be replayed so they are not lost, because WAL
- * files are not transfered from old to new servers.
- */
- if (start_postmaster(&old_cluster, false))
- stop_postmaster(false);
- else
- {
- if (!user_opts.check)
- pg_fatal("There seems to be a postmaster servicing the old cluster.\n"
- "Please shutdown that postmaster and try again.\n");
- else
- *live_check = true;
- }
- }
-
- /* same goes for the new postmaster */
- if (pid_lock_file_exists(new_cluster.pgdata))
- {
- if (start_postmaster(&new_cluster, false))
- stop_postmaster(false);
- else
- pg_fatal("There seems to be a postmaster servicing the new cluster.\n"
- "Please shutdown that postmaster and try again.\n");
- }
-
- /* get path to pg_upgrade executable */
- if (find_my_exec(argv0, exec_path) < 0)
- pg_fatal("Could not get path name to pg_upgrade: %s\n", getErrorText(errno));
-
- /* Trim off program name and keep just path */
- *last_dir_separator(exec_path) = '\0';
- canonicalize_path(exec_path);
- os_info.exec_path = pg_strdup(exec_path);
-}
-
-
-static void
-prepare_new_cluster(void)
-{
- /*
- * It would make more sense to freeze after loading the schema, but that
- * would cause us to lose the frozenids restored by the load. We use
- * --analyze so autovacuum doesn't update statistics later
- */
- prep_status("Analyzing all rows in the new cluster");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/vacuumdb\" %s --all --analyze %s",
- new_cluster.bindir, cluster_conn_opts(&new_cluster),
- log_opts.verbose ? "--verbose" : "");
- check_ok();
-
- /*
- * We do freeze after analyze so pg_statistic is also frozen. template0 is
- * not frozen here, but data rows were frozen by initdb, and we set its
- * datfrozenxid, relfrozenxids, and relminmxid later to match the new xid
- * counter later.
- */
- prep_status("Freezing all rows on the new cluster");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/vacuumdb\" %s --all --freeze %s",
- new_cluster.bindir, cluster_conn_opts(&new_cluster),
- log_opts.verbose ? "--verbose" : "");
- check_ok();
-
- get_pg_database_relfilenode(&new_cluster);
-}
-
-
-static void
-prepare_new_databases(void)
-{
- /*
- * We set autovacuum_freeze_max_age to its maximum value so autovacuum
- * does not launch here and delete clog files, before the frozen xids are
- * set.
- */
-
- set_frozenxids(false);
-
- prep_status("Restoring global objects in the new cluster");
-
- /*
- * We have to create the databases first so we can install support
- * functions in all the other databases. Ideally we could create the
- * support functions in template1 but pg_dumpall creates database using
- * the template0 template.
- */
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
- new_cluster.bindir, cluster_conn_opts(&new_cluster),
- GLOBALS_DUMP_FILE);
- check_ok();
-
- /* we load this to get a current list of databases */
- get_db_and_rel_infos(&new_cluster);
-}
-
-
-static void
-create_new_objects(void)
-{
- int dbnum;
-
- prep_status("Restoring database schemas in the new cluster\n");
-
- 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);
-
- /*
- * pg_dump only produces its output at the end, so there is little
- * parallelism if using the pipe.
- */
- parallel_exec_prog(log_file_name,
- NULL,
- "\"%s/pg_restore\" %s --exit-on-error --verbose --dbname \"%s\" \"%s\"",
- new_cluster.bindir,
- cluster_conn_opts(&new_cluster),
- old_db->db_name,
- sql_file_name);
- }
-
- /* reap all children */
- while (reap_child(true) == true)
- ;
-
- end_progress_output();
- check_ok();
-
- /*
- * We don't have minmxids for databases or relations in pre-9.3
- * clusters, so set those after we have restores the schemas.
- */
- if (GET_MAJOR_VERSION(old_cluster.major_version) < 903)
- set_frozenxids(true);
-
- optionally_create_toast_tables();
-
- /* regenerate now that we have objects in the databases */
- get_db_and_rel_infos(&new_cluster);
-}
-
-/*
- * Delete the given subdirectory contents from the new cluster
- */
-static void
-remove_new_subdir(char *subdir, bool rmtopdir)
-{
- char new_path[MAXPGPATH];
-
- prep_status("Deleting files from new %s", subdir);
-
- snprintf(new_path, sizeof(new_path), "%s/%s", new_cluster.pgdata, subdir);
- if (!rmtree(new_path, rmtopdir))
- pg_fatal("could not delete directory \"%s\"\n", new_path);
-
- check_ok();
-}
-
-/*
- * Copy the files from the old cluster into it
- */
-static void
-copy_subdir_files(char *subdir)
-{
- char old_path[MAXPGPATH];
- char new_path[MAXPGPATH];
-
- remove_new_subdir(subdir, true);
-
- snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, subdir);
- snprintf(new_path, sizeof(new_path), "%s/%s", new_cluster.pgdata, subdir);
-
- prep_status("Copying old %s to new server", subdir);
-
- exec_prog(UTILITY_LOG_FILE, NULL, true,
-#ifndef WIN32
- "cp -Rf \"%s\" \"%s\"",
-#else
- /* flags: everything, no confirm, quiet, overwrite read-only */
- "xcopy /e /y /q /r \"%s\" \"%s\\\"",
-#endif
- old_path, new_path);
-
- check_ok();
-}
-
-static void
-copy_clog_xlog_xid(void)
-{
- /* copy old commit logs to new data dir */
- copy_subdir_files("pg_clog");
-
- /* set the next transaction id and epoch of the new cluster */
- prep_status("Setting next transaction ID and epoch for new cluster");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
- new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
- new_cluster.pgdata);
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -f -e %u \"%s\"",
- new_cluster.bindir, old_cluster.controldata.chkpnt_nxtepoch,
- new_cluster.pgdata);
- /* must reset commit timestamp limits also */
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -f -c %u,%u \"%s\"",
- new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtxid,
- old_cluster.controldata.chkpnt_nxtxid,
- new_cluster.pgdata);
- check_ok();
-
- /*
- * If the old server is before the MULTIXACT_FORMATCHANGE_CAT_VER change
- * (see pg_upgrade.h) and the new server is after, then we don't copy
- * pg_multixact files, but we need to reset pg_control so that the new
- * server doesn't attempt to read multis older than the cutoff value.
- */
- if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER &&
- new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
- {
- copy_subdir_files("pg_multixact/offsets");
- copy_subdir_files("pg_multixact/members");
-
- prep_status("Setting next multixact ID and offset for new cluster");
-
- /*
- * we preserve all files and contents, so we must preserve both "next"
- * counters here and the oldest multi present on system.
- */
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -O %u -m %u,%u \"%s\"",
- new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtmxoff,
- old_cluster.controldata.chkpnt_nxtmulti,
- old_cluster.controldata.chkpnt_oldstMulti,
- new_cluster.pgdata);
- check_ok();
- }
- else if (new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
- {
- /*
- * Remove offsets/0000 file created by initdb that no longer matches
- * the new multi-xid value. "members" starts at zero so no need to
- * remove it.
- */
- remove_new_subdir("pg_multixact/offsets", false);
-
- prep_status("Setting oldest multixact ID on new cluster");
-
- /*
- * We don't preserve files in this case, but it's important that the
- * oldest multi is set to the latest value used by the old system, so
- * that multixact.c returns the empty set for multis that might be
- * present on disk. We set next multi to the value following that; it
- * might end up wrapped around (i.e. 0) if the old cluster had
- * next=MaxMultiXactId, but multixact.c can cope with that just fine.
- */
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -m %u,%u \"%s\"",
- new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtmulti + 1,
- old_cluster.controldata.chkpnt_nxtmulti,
- new_cluster.pgdata);
- check_ok();
- }
-
- /* now reset the wal archives in the new cluster */
- prep_status("Resetting WAL archives");
- exec_prog(UTILITY_LOG_FILE, NULL, true,
- "\"%s/pg_resetxlog\" -l %s \"%s\"", new_cluster.bindir,
- old_cluster.controldata.nextxlogfile,
- new_cluster.pgdata);
- check_ok();
-}
-
-
-/*
- * set_frozenxids()
- *
- * We have frozen all xids, so set datfrozenxid, relfrozenxid, and
- * relminmxid to be the old cluster's xid counter, which we just set
- * in the new cluster. User-table frozenxid and minmxid values will
- * be set by pg_dump --binary-upgrade, but objects not set by the pg_dump
- * must have proper frozen counters.
- */
-static
-void
-set_frozenxids(bool minmxid_only)
-{
- int dbnum;
- PGconn *conn,
- *conn_template1;
- PGresult *dbres;
- int ntups;
- int i_datname;
- int i_datallowconn;
-
- if (!minmxid_only)
- prep_status("Setting frozenxid and minmxid counters in new cluster");
- else
- prep_status("Setting minmxid counter in new cluster");
-
- conn_template1 = connectToServer(&new_cluster, "template1");
-
- if (!minmxid_only)
- /* set pg_database.datfrozenxid */
- PQclear(executeQueryOrDie(conn_template1,
- "UPDATE pg_catalog.pg_database "
- "SET datfrozenxid = '%u'",
- old_cluster.controldata.chkpnt_nxtxid));
-
- /* set pg_database.datminmxid */
- PQclear(executeQueryOrDie(conn_template1,
- "UPDATE pg_catalog.pg_database "
- "SET datminmxid = '%u'",
- old_cluster.controldata.chkpnt_nxtmulti));
-
- /* get database names */
- dbres = executeQueryOrDie(conn_template1,
- "SELECT datname, datallowconn "
- "FROM pg_catalog.pg_database");
-
- i_datname = PQfnumber(dbres, "datname");
- i_datallowconn = PQfnumber(dbres, "datallowconn");
-
- ntups = PQntuples(dbres);
- for (dbnum = 0; dbnum < ntups; dbnum++)
- {
- char *datname = PQgetvalue(dbres, dbnum, i_datname);
- char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
-
- /*
- * We must update databases where datallowconn = false, e.g.
- * template0, because autovacuum increments their datfrozenxids,
- * relfrozenxids, and relminmxid even if autovacuum is turned off,
- * and even though all the data rows are already frozen To enable
- * this, we temporarily change datallowconn.
- */
- if (strcmp(datallowconn, "f") == 0)
- PQclear(executeQueryOrDie(conn_template1,
- "ALTER DATABASE %s ALLOW_CONNECTIONS = true",
- quote_identifier(datname)));
-
- conn = connectToServer(&new_cluster, datname);
-
- if (!minmxid_only)
- /* set pg_class.relfrozenxid */
- PQclear(executeQueryOrDie(conn,
- "UPDATE pg_catalog.pg_class "
- "SET relfrozenxid = '%u' "
- /* only heap, materialized view, and TOAST are vacuumed */
- "WHERE relkind IN ('r', 'm', 't')",
- old_cluster.controldata.chkpnt_nxtxid));
-
- /* set pg_class.relminmxid */
- PQclear(executeQueryOrDie(conn,
- "UPDATE pg_catalog.pg_class "
- "SET relminmxid = '%u' "
- /* only heap, materialized view, and TOAST are vacuumed */
- "WHERE relkind IN ('r', 'm', 't')",
- old_cluster.controldata.chkpnt_nxtmulti));
- PQfinish(conn);
-
- /* Reset datallowconn flag */
- if (strcmp(datallowconn, "f") == 0)
- PQclear(executeQueryOrDie(conn_template1,
- "ALTER DATABASE %s ALLOW_CONNECTIONS = false",
- quote_identifier(datname)));
- }
-
- PQclear(dbres);
-
- PQfinish(conn_template1);
-
- check_ok();
-}
-
-
-static void
-cleanup(void)
-{
- fclose(log_opts.internal);
-
- /* Remove dump and log files? */
- if (!log_opts.retain)
- {
- int dbnum;
- char **filename;
-
- for (filename = output_files; *filename != NULL; filename++)
- unlink(*filename);
-
- /* remove dump files */
- unlink(GLOBALS_DUMP_FILE);
-
- if (old_cluster.dbarr.dbs)
- 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];
-
- snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
- unlink(sql_file_name);
-
- snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
- unlink(log_file_name);
- }
- }
-}
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
deleted file mode 100644
index ace3465f989..00000000000
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * pg_upgrade.h
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/pg_upgrade.h
- */
-
-#include <unistd.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include "libpq-fe.h"
-
-/* Use port in the private/dynamic port number range */
-#define DEF_PGUPORT 50432
-
-/* Allocate for null byte */
-#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)
-
-/* contains both global db information and CREATE DATABASE commands */
-#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"
-
-extern char *output_files[];
-
-/*
- * WIN32 files do not accept writes from multiple processes
- *
- * On Win32, we can't send both pg_upgrade output and command output to the
- * same file because we get the error: "The process cannot access the file
- * because it is being used by another process." so send the pg_ctl
- * command-line output to a new file, rather than into the server log file.
- * Ideally we could use UTILITY_LOG_FILE for this, but some Windows platforms
- * keep the pg_ctl output file open by the running postmaster, even after
- * pg_ctl exits.
- *
- * We could use the Windows pgwin32_open() flags to allow shared file
- * writes but is unclear how all other tools would use those flags, so
- * we just avoid it and log a little differently on Windows; we adjust
- * the error message appropriately.
- */
-#ifndef WIN32
-#define SERVER_START_LOG_FILE SERVER_LOG_FILE
-#define SERVER_STOP_LOG_FILE SERVER_LOG_FILE
-#else
-#define SERVER_START_LOG_FILE "pg_upgrade_server_start.log"
-/*
- * "pg_ctl start" keeps SERVER_START_LOG_FILE and SERVER_LOG_FILE open
- * while the server is running, so we use UTILITY_LOG_FILE for "pg_ctl
- * stop".
- */
-#define SERVER_STOP_LOG_FILE UTILITY_LOG_FILE
-#endif
-
-
-#ifndef WIN32
-#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_PREFIX "./"
-#define SCRIPT_EXT "sh"
-#define ECHO_QUOTE "'"
-#define ECHO_BLANK ""
-#else
-#define pg_copy_file CopyFile
-#define pg_mv_file pgrename
-#define pg_link_file win32_pghardlink
-#define PATH_SEPARATOR '\\'
-#define RM_CMD "DEL /q"
-#define RMDIR_CMD "RMDIR /s/q"
-#define SCRIPT_PREFIX ""
-#define SCRIPT_EXT "bat"
-#define EXE_EXT ".exe"
-#define ECHO_QUOTE ""
-#define ECHO_BLANK "."
-#endif
-
-#define CLUSTER_NAME(cluster) ((cluster) == &old_cluster ? "old" : \
- (cluster) == &new_cluster ? "new" : "none")
-
-#define atooid(x) ((Oid) strtoul((x), NULL, 10))
-
-/* OID system catalog preservation added during PG 9.0 development */
-#define TABLE_SPACE_SUBDIRS_CAT_VER 201001111
-/* postmaster/postgres -b (binary_upgrade) flag added during PG 9.1 development */
-#define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251
-/*
- * Visibility map changed with this 9.2 commit,
- * 8f9fe6edce358f7904e0db119416b4d1080a83aa; pick later catalog version.
- */
-#define VISIBILITY_MAP_CRASHSAFE_CAT_VER 201107031
-
-/*
- * pg_multixact format changed in 9.3 commit 0ac5ad5134f2769ccbaefec73844f85,
- * ("Improve concurrency of foreign key locking") which also updated catalog
- * version to this value. pg_upgrade behavior depends on whether old and new
- * server versions are both newer than this, or only the new one is.
- */
-#define MULTIXACT_FORMATCHANGE_CAT_VER 201301231
-
-/*
- * large object chunk size added to pg_controldata,
- * commit 5f93c37805e7485488480916b4585e098d3cc883
- */
-#define LARGE_OBJECT_SIZE_PG_CONTROL_VER 942
-
-/*
- * change in JSONB format during 9.4 beta
- */
-#define JSONB_FORMAT_CHANGE_CAT_VER 201409291
-
-/*
- * Each relation is represented by a relinfo structure.
- */
-typedef struct
-{
- /* Can't use NAMEDATALEN; not guaranteed to fit on client */
- char *nspname; /* namespace name */
- char *relname; /* relation name */
- Oid reloid; /* relation oid */
- Oid relfilenode; /* relation relfile node */
- /* relation tablespace path, or "" for the cluster default */
- char *tablespace;
- bool nsp_alloc;
- bool tblsp_alloc;
-} RelInfo;
-
-typedef struct
-{
- RelInfo *rels;
- int nrels;
-} RelInfoArr;
-
-/*
- * The following structure represents a relation mapping.
- */
-typedef struct
-{
- const char *old_tablespace;
- const char *new_tablespace;
- const char *old_tablespace_suffix;
- const char *new_tablespace_suffix;
- Oid old_db_oid;
- Oid new_db_oid;
-
- /*
- * old/new relfilenodes might differ for pg_largeobject(_metadata) indexes
- * due to VACUUM FULL or REINDEX. Other relfilenodes are preserved.
- */
- Oid old_relfilenode;
- Oid new_relfilenode;
- /* the rest are used only for logging and error reporting */
- char *nspname; /* namespaces */
- char *relname;
-} FileNameMap;
-
-/*
- * Structure to store database information
- */
-typedef struct
-{
- Oid db_oid; /* oid of the database */
- char *db_name; /* database name */
- char db_tablespace[MAXPGPATH]; /* database default tablespace
- * path */
- char *db_collate;
- char *db_ctype;
- int db_encoding;
- RelInfoArr rel_arr; /* array of all user relinfos */
-} DbInfo;
-
-typedef struct
-{
- DbInfo *dbs; /* array of db infos */
- int ndbs; /* number of db infos */
-} DbInfoArr;
-
-/*
- * The following structure is used to hold pg_control information.
- * Rather than using the backend's control structure we use our own
- * structure to avoid pg_control version issues between releases.
- */
-typedef struct
-{
- uint32 ctrl_ver;
- uint32 cat_ver;
- char nextxlogfile[25];
- uint32 chkpnt_tli;
- uint32 chkpnt_nxtxid;
- uint32 chkpnt_nxtepoch;
- uint32 chkpnt_nxtoid;
- uint32 chkpnt_nxtmulti;
- uint32 chkpnt_nxtmxoff;
- uint32 chkpnt_oldstMulti;
- uint32 align;
- uint32 blocksz;
- uint32 largesz;
- uint32 walsz;
- uint32 walseg;
- uint32 ident;
- uint32 index;
- uint32 toast;
- uint32 large_object;
- bool date_is_int;
- bool float8_pass_by_value;
- bool data_checksum_version;
-} ControlData;
-
-/*
- * Enumeration to denote link modes
- */
-typedef enum
-{
- TRANSFER_MODE_COPY,
- TRANSFER_MODE_LINK
-} transferMode;
-
-/*
- * Enumeration to denote pg_log modes
- */
-typedef enum
-{
- PG_VERBOSE,
- PG_STATUS,
- PG_REPORT,
- PG_WARNING,
- PG_FATAL
-} eLogType;
-
-
-typedef long pgpid_t;
-
-
-/*
- * cluster
- *
- * information about each cluster
- */
-typedef struct
-{
- ControlData controldata; /* pg_control information */
- DbInfoArr dbarr; /* dbinfos array */
- char *pgdata; /* pathname for cluster's $PGDATA directory */
- char *pgconfig; /* pathname for cluster's config file
- * directory */
- char *bindir; /* pathname for cluster's executable directory */
- char *pgopts; /* options to pass to the server, like pg_ctl
- * -o */
- char *sockdir; /* directory for Unix Domain socket, if any */
- unsigned short port; /* port number where postmaster is waiting */
- uint32 major_version; /* PG_VERSION of cluster */
- char major_version_str[64]; /* string PG_VERSION of cluster */
- uint32 bin_version; /* version returned from pg_ctl */
- Oid pg_database_oid; /* OID of pg_database relation */
- const char *tablespace_suffix; /* directory specification */
-} ClusterInfo;
-
-
-/*
- * LogOpts
-*/
-typedef struct
-{
- FILE *internal; /* internal log FILE */
- bool verbose; /* TRUE -> be verbose in messages */
- bool retain; /* retain log files on success */
-} LogOpts;
-
-
-/*
- * UserOpts
-*/
-typedef struct
-{
- bool check; /* TRUE -> ask user for permission to make
- * changes */
- transferMode transfer_mode; /* copy files or link them? */
- int jobs;
-} UserOpts;
-
-
-/*
- * OSInfo
- */
-typedef struct
-{
- const char *progname; /* complete pathname for this program */
- char *exec_path; /* full path to my executable */
- char *user; /* username for clusters */
- bool user_specified; /* user specified on command-line */
- char **old_tablespaces; /* tablespaces */
- int num_old_tablespaces;
- char **libraries; /* loadable libraries */
- int num_libraries;
- ClusterInfo *running_cluster;
-} OSInfo;
-
-
-/*
- * Global variables
- */
-extern LogOpts log_opts;
-extern UserOpts user_opts;
-extern ClusterInfo old_cluster,
- new_cluster;
-extern OSInfo os_info;
-
-
-/* check.c */
-
-void output_check_banner(bool live_check);
-void check_and_dump_old_cluster(bool live_check);
-void check_new_cluster(void);
-void report_clusters_compatible(void);
-void issue_warnings(void);
-void output_completion_banner(char *analyze_script_file_name,
- char *deletion_script_file_name);
-void check_cluster_versions(void);
-void check_cluster_compatibility(bool live_check);
-void create_script_for_old_cluster_deletion(char **deletion_script_file_name);
-void create_script_for_cluster_analyze(char **analyze_script_file_name);
-
-
-/* controldata.c */
-
-void get_control_data(ClusterInfo *cluster, bool live_check);
-void check_control_data(ControlData *oldctrl, ControlData *newctrl);
-void disable_old_cluster(void);
-
-
-/* dump.c */
-
-void generate_old_dump(void);
-void optionally_create_toast_tables(void);
-
-
-/* exec.c */
-
-#define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
-
-bool exec_prog(const char *log_file, const char *opt_log_file,
- bool throw_error, const char *fmt,...) pg_attribute_printf(4, 5);
-void verify_directories(void);
-bool pid_lock_file_exists(const char *datadir);
-
-
-/* file.c */
-
-#ifdef PAGE_CONVERSION
-typedef const char *(*pluginStartup) (uint16 migratorVersion,
- uint16 *pluginVersion, uint16 newPageVersion,
- uint16 oldPageVersion, void **pluginData);
-typedef const char *(*pluginConvertFile) (void *pluginData,
- const char *dstName, const char *srcName);
-typedef const char *(*pluginConvertPage) (void *pluginData,
- const char *dstPage, const char *srcPage);
-typedef const char *(*pluginShutdown) (void *pluginData);
-
-typedef struct
-{
- uint16 oldPageVersion; /* Page layout version of the old cluster */
- uint16 newPageVersion; /* Page layout version of the new cluster */
- uint16 pluginVersion; /* API version of converter plugin */
- void *pluginData; /* Plugin data (set by plugin) */
- pluginStartup startup; /* Pointer to plugin's startup function */
- pluginConvertFile convertFile; /* Pointer to plugin's file converter
- * function */
- pluginConvertPage convertPage; /* Pointer to plugin's page converter
- * function */
- pluginShutdown shutdown; /* Pointer to plugin's shutdown function */
-} pageCnvCtx;
-
-const pageCnvCtx *setupPageConverter(void);
-#else
-/* dummy */
-typedef void *pageCnvCtx;
-#endif
-
-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);
-
-/* function.c */
-
-void get_loadable_libraries(void);
-void check_loadable_libraries(void);
-
-/* info.c */
-
-FileNameMap *gen_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);
-
-/* option.c */
-
-void parseCommandLine(int argc, char *argv[]);
-void adjust_data_dir(ClusterInfo *cluster);
-void get_sock_dir(ClusterInfo *cluster, bool live_check);
-
-/* relfilenode.c */
-
-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);
-
-/* tablespace.c */
-
-void init_tablespaces(void);
-
-
-/* server.c */
-
-PGconn *connectToServer(ClusterInfo *cluster, const char *db_name);
-PGresult *executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3);
-
-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);
-
-
-/* util.c */
-
-char *quote_identifier(const char *s);
-int get_user_info(char **user_name_p);
-void check_ok(void);
-void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3);
-void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3);
-void pg_fatal(const char *fmt,...) pg_attribute_printf(1, 2) pg_attribute_noreturn();
-void end_progress_output(void);
-void prep_status(const char *fmt,...) pg_attribute_printf(1, 2);
-void check_ok(void);
-const char *getErrorText(int errNum);
-unsigned int str2uint(const char *str);
-void pg_putenv(const char *var, const char *val);
-
-
-/* version.c */
-
-void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
- bool check_mode);
-void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
-
-/* parallel.c */
-void parallel_exec_prog(const char *log_file, const char *opt_log_file,
- const char *fmt,...) pg_attribute_printf(3, 4);
-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);
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
deleted file mode 100644
index 423802bd239..00000000000
--- a/contrib/pg_upgrade/relfilenode.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * relfilenode.c
- *
- * relfilenode functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/relfilenode.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include "catalog/pg_class.h"
-#include "access/transam.h"
-
-
-static void transfer_single_new_db(pageCnvCtx *pageConverter,
- FileNameMap *maps, int size, char *old_tablespace);
-static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
- const char *suffix);
-
-
-/*
- * transfer_all_new_tablespaces()
- *
- * Responsible for upgrading all database. invokes routines to generate mappings and then
- * physically link the databases.
- */
-void
-transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
- char *old_pgdata, char *new_pgdata)
-{
- 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;
-}
-
-
-/*
- * transfer_all_new_dbs()
- *
- * Responsible for upgrading all database. invokes routines to generate mappings and then
- * physically link the databases.
- */
-void
-transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
- char *old_pgdata, char *new_pgdata, char *old_tablespace)
-{
- 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_fatal("old database \"%s\" not found in the new cluster\n",
- old_db->db_name);
-
- 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);
- }
- /* We allocate something even for n_maps == 0 */
- pg_free(mappings);
- }
-
- return;
-}
-
-
-/*
- * get_pg_database_relfilenode()
- *
- * Retrieves the relfilenode for a few system-catalog tables. We need these
- * relfilenodes later in the upgrade process.
- */
-void
-get_pg_database_relfilenode(ClusterInfo *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);
-}
-
-
-/*
- * transfer_single_new_db()
- *
- * create links for mappings stored in "maps" array.
- */
-static void
-transfer_single_new_db(pageCnvCtx *pageConverter,
- FileNameMap *maps, int size, char *old_tablespace)
-{
- int mapnum;
- bool vm_crashsafe_match = true;
-
- /*
- * Do the old and new cluster disagree on the crash-safetiness of the vm
- * files? If so, do not copy them.
- */
- if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER &&
- new_cluster.controldata.cat_ver >= VISIBILITY_MAP_CRASHSAFE_CAT_VER)
- vm_crashsafe_match = false;
-
- for (mapnum = 0; mapnum < size; mapnum++)
- {
- if (old_tablespace == NULL ||
- strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0)
- {
- /* transfer primary file */
- transfer_relfile(pageConverter, &maps[mapnum], "");
-
- /* fsm/vm files added in PG 8.4 */
- if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
- {
- /*
- * Copy/link any fsm and vm files, if they exist
- */
- transfer_relfile(pageConverter, &maps[mapnum], "_fsm");
- if (vm_crashsafe_match)
- transfer_relfile(pageConverter, &maps[mapnum], "_vm");
- }
- }
- }
-}
-
-
-/*
- * transfer_relfile()
- *
- * Copy or link file from old cluster to new one.
- */
-static void
-transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
- const char *type_suffix)
-{
- const char *msg;
- char old_file[MAXPGPATH];
- char new_file[MAXPGPATH];
- int fd;
- int segno;
- char extent_suffix[65];
-
- /*
- * Now copy/link any related segments as well. Remember, PG breaks large
- * files into 1GB segments, the first segment has no extension, subsequent
- * segments are named relfilenode.1, relfilenode.2, relfilenode.3. copied.
- */
- for (segno = 0;; segno++)
- {
- if (segno == 0)
- extent_suffix[0] = '\0';
- else
- snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno);
-
- snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s",
- map->old_tablespace,
- map->old_tablespace_suffix,
- map->old_db_oid,
- map->old_relfilenode,
- type_suffix,
- extent_suffix);
- snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s",
- map->new_tablespace,
- map->new_tablespace_suffix,
- map->new_db_oid,
- map->new_relfilenode,
- type_suffix,
- extent_suffix);
-
- /* Is it an extent, fsm, or vm file? */
- if (type_suffix[0] != '\0' || segno != 0)
- {
- /* Did file open fail? */
- if ((fd = open(old_file, O_RDONLY, 0)) == -1)
- {
- /* File does not exist? That's OK, just return */
- if (errno == ENOENT)
- return;
- else
- pg_fatal("error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
- map->nspname, map->relname, old_file, new_file,
- getErrorText(errno));
- }
- close(fd);
- }
-
- unlink(new_file);
-
- /* Copying files might take some time, so give feedback. */
- pg_log(PG_STATUS, "%s", old_file);
-
- if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
- pg_fatal("This upgrade requires page-by-page conversion, "
- "you must use copy mode instead of link mode.\n");
-
- if (user_opts.transfer_mode == TRANSFER_MODE_COPY)
- {
- pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file);
-
- if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
- pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
- map->nspname, map->relname, old_file, new_file, msg);
- }
- else
- {
- pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file);
-
- if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
- pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
- map->nspname, map->relname, old_file, new_file, msg);
- }
- }
-
- return;
-}
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
deleted file mode 100644
index c5f66f09632..00000000000
--- a/contrib/pg_upgrade/server.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * server.c
- *
- * database server functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/server.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-
-static PGconn *get_db_conn(ClusterInfo *cluster, const char *db_name);
-
-
-/*
- * connectToServer()
- *
- * Connects to the desired database on the designated server.
- * If the connection attempt fails, this function logs an error
- * message and calls exit() to kill the program.
- */
-PGconn *
-connectToServer(ClusterInfo *cluster, const char *db_name)
-{
- PGconn *conn = get_db_conn(cluster, db_name);
-
- if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
- {
- pg_log(PG_REPORT, "connection to database failed: %s\n",
- PQerrorMessage(conn));
-
- if (conn)
- PQfinish(conn);
-
- printf("Failure, exiting\n");
- exit(1);
- }
-
- return conn;
-}
-
-
-/*
- * get_db_conn()
- *
- * get database connection, using named database + standard params for cluster
- */
-static PGconn *
-get_db_conn(ClusterInfo *cluster, const char *db_name)
-{
- char conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
-
- if (cluster->sockdir)
- snprintf(conn_opts, sizeof(conn_opts),
- "dbname = '%s' user = '%s' host = '%s' port = %d",
- db_name, os_info.user, cluster->sockdir, cluster->port);
- else
- snprintf(conn_opts, sizeof(conn_opts),
- "dbname = '%s' user = '%s' port = %d",
- db_name, os_info.user, cluster->port);
-
- return PQconnectdb(conn_opts);
-}
-
-
-/*
- * cluster_conn_opts()
- *
- * Return standard command-line options for connecting to this cluster when
- * using psql, pg_dump, etc. Ideally this would match what get_db_conn()
- * sets, but the utilities we need aren't very consistent about the treatment
- * of database name options, so we leave that out.
- *
- * Note result is in static storage, so use it right away.
- */
-char *
-cluster_conn_opts(ClusterInfo *cluster)
-{
- 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;
-}
-
-
-/*
- * executeQueryOrDie()
- *
- * Formats a query string from the given arguments and executes the
- * resulting query. If the query fails, this function logs an error
- * message and calls exit() to kill the program.
- */
-PGresult *
-executeQueryOrDie(PGconn *conn, const char *fmt,...)
-{
- static char query[QUERY_ALLOC];
- va_list args;
- PGresult *result;
- ExecStatusType status;
-
- va_start(args, fmt);
- vsnprintf(query, sizeof(query), fmt, args);
- va_end(args);
-
- pg_log(PG_VERBOSE, "executing: %s\n", query);
- result = PQexec(conn, query);
- status = PQresultStatus(result);
-
- if ((status != PGRES_TUPLES_OK) && (status != PGRES_COMMAND_OK))
- {
- pg_log(PG_REPORT, "SQL command failed\n%s\n%s\n", query,
- PQerrorMessage(conn));
- PQclear(result);
- PQfinish(conn);
- printf("Failure, exiting\n");
- exit(1);
- }
- else
- return result;
-}
-
-
-/*
- * get_major_server_version()
- *
- * gets the version (in unsigned int form) for the given datadir. Assumes
- * that datadir is an absolute path to a valid pgdata directory. The version
- * is retrieved by reading the PG_VERSION file.
- */
-uint32
-get_major_server_version(ClusterInfo *cluster)
-{
- 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_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_fatal("could not get version from %s\n", cluster->pgdata);
-
- fclose(version_fd);
-
- return (100 * integer_version + fractional_version) * 100;
-}
-
-
-static void
-stop_postmaster_atexit(void)
-{
- stop_postmaster(true);
-}
-
-
-bool
-start_postmaster(ClusterInfo *cluster, bool throw_error)
-{
- 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
-
- /*
- * Since PG 9.1, we have used -b to disable autovacuum. For earlier
- * releases, setting autovacuum=off disables cleanup vacuum and analyze,
- * but freeze vacuums can still happen, so we set autovacuum_freeze_max_age
- * to its maximum. (autovacuum_multixact_freeze_max_age was introduced
- * after 9.1, so there is no need to set that.) We assume all datfrozenxid
- * and relfrozenxid 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);
-
- /* Did it fail and we are just testing if the server could be started? */
- if (!pg_ctl_return && !throw_error)
- return false;
-
- /*
- * We set this here to make sure atexit() shuts down the server, but only
- * if we started the server successfully. We do it before checking for
- * connectivity in case the server started but there is a connectivity
- * failure. If pg_ctl did not return success, we will exit below.
- *
- * Pre-9.1 servers do not have PQping(), so we could be leaving the server
- * running if authentication was misconfigured, so someday we might went
- * to be more aggressive about doing server shutdowns even if pg_ctl
- * fails, but now (2013-08-14) it seems prudent to be cautious. We don't
- * want to shutdown a server that might have been accidentally started
- * during the upgrade.
- */
- if (pg_ctl_return)
- os_info.running_cluster = cluster;
-
- /*
- * pg_ctl -w might have failed because the server couldn't be started, or
- * there might have been a connection problem in _checking_ if the server
- * has started. Therefore, even if pg_ctl failed, we continue and test
- * for connectivity in case we get a connection reason for the failure.
- */
- 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_fatal("could not connect to %s postmaster started with the command:\n"
- "%s\n",
- CLUSTER_NAME(cluster), cmd);
- }
- PQfinish(conn);
-
- /*
- * If pg_ctl failed, and the connection didn't fail, and throw_error is
- * enabled, fail now. This could happen if the server was already
- * running.
- */
- if (!pg_ctl_return)
- pg_fatal("pg_ctl failed to start the %s server, or connection failed\n",
- CLUSTER_NAME(cluster));
-
- return true;
-}
-
-
-void
-stop_postmaster(bool fast)
-{
- 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;
-}
-
-
-/*
- * check_pghost_envvar()
- *
- * Tests that PGHOST does not point to a non-local server
- */
-void
-check_pghost_envvar(void)
-{
- PQconninfoOption *option;
- PQconninfoOption *start;
-
- /* Get valid libpq env vars from the PQconndefaults function */
-
- start = PQconndefaults();
-
- if (!start)
- pg_fatal("out of memory\n");
-
- 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_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);
-}
diff --git a/contrib/pg_upgrade/tablespace.c b/contrib/pg_upgrade/tablespace.c
deleted file mode 100644
index eecdf4b2983..00000000000
--- a/contrib/pg_upgrade/tablespace.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * tablespace.c
- *
- * tablespace functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/tablespace.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-#include <sys/types.h>
-
-static void get_tablespace_paths(void);
-static void set_tablespace_directory_suffix(ClusterInfo *cluster);
-
-
-void
-init_tablespaces(void)
-{
- get_tablespace_paths();
-
- set_tablespace_directory_suffix(&old_cluster);
- set_tablespace_directory_suffix(&new_cluster);
-
- if (os_info.num_old_tablespaces > 0 &&
- strcmp(old_cluster.tablespace_suffix, new_cluster.tablespace_suffix) == 0)
- pg_fatal("Cannot upgrade to/from the same system catalog version when\n"
- "using tablespaces.\n");
-}
-
-
-/*
- * get_tablespace_paths()
- *
- * Scans pg_tablespace and returns a malloc'ed array of all tablespace
- * paths. Its the caller's responsibility to free the array.
- */
-static void
-get_tablespace_paths(void)
-{
- PGconn *conn = connectToServer(&old_cluster, "template1");
- PGresult *res;
- int tblnum;
- int i_spclocation;
- char query[QUERY_ALLOC];
-
- snprintf(query, sizeof(query),
- "SELECT %s "
- "FROM pg_catalog.pg_tablespace "
- "WHERE spcname != 'pg_default' AND "
- " spcname != 'pg_global'",
- /* 9.2 removed the spclocation column */
- (GET_MAJOR_VERSION(old_cluster.major_version) <= 901) ?
- "spclocation" : "pg_catalog.pg_tablespace_location(oid) AS spclocation");
-
- res = executeQueryOrDie(conn, "%s", query);
-
- if ((os_info.num_old_tablespaces = PQntuples(res)) != 0)
- os_info.old_tablespaces = (char **) pg_malloc(
- os_info.num_old_tablespaces * sizeof(char *));
- else
- os_info.old_tablespaces = NULL;
-
- i_spclocation = PQfnumber(res, "spclocation");
-
- for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
- {
- struct stat statBuf;
-
- os_info.old_tablespaces[tblnum] = pg_strdup(
- PQgetvalue(res, tblnum, i_spclocation));
-
- /*
- * Check that the tablespace path exists and is a directory.
- * Effectively, this is checking only for tables/indexes in
- * non-existent tablespace directories. Databases located in
- * non-existent tablespaces already throw a backend error.
- * Non-existent tablespace directories can occur when a data directory
- * that contains user tablespaces is moved as part of pg_upgrade
- * preparation and the symbolic links are not updated.
- */
- if (stat(os_info.old_tablespaces[tblnum], &statBuf) != 0)
- {
- if (errno == ENOENT)
- report_status(PG_FATAL,
- "tablespace directory \"%s\" does not exist\n",
- os_info.old_tablespaces[tblnum]);
- else
- report_status(PG_FATAL,
- "cannot stat() tablespace directory \"%s\": %s\n",
- os_info.old_tablespaces[tblnum], getErrorText(errno));
- }
- if (!S_ISDIR(statBuf.st_mode))
- report_status(PG_FATAL,
- "tablespace path \"%s\" is not a directory\n",
- os_info.old_tablespaces[tblnum]);
- }
-
- PQclear(res);
-
- PQfinish(conn);
-
- return;
-}
-
-
-static void
-set_tablespace_directory_suffix(ClusterInfo *cluster)
-{
- if (GET_MAJOR_VERSION(cluster->major_version) <= 804)
- cluster->tablespace_suffix = pg_strdup("");
- else
- {
- /* This cluster has a version-specific subdirectory */
-
- /* The leading slash is needed to start a new directory. */
- cluster->tablespace_suffix = psprintf("/PG_%s_%d",
- cluster->major_version_str,
- cluster->controldata.cat_ver);
- }
-}
diff --git a/contrib/pg_upgrade/test.sh b/contrib/pg_upgrade/test.sh
deleted file mode 100644
index 2e9f97688c6..00000000000
--- a/contrib/pg_upgrade/test.sh
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/bin/sh
-
-# contrib/pg_upgrade/test.sh
-#
-# Test driver for pg_upgrade. Initializes a new database cluster,
-# runs the regression tests (to put in some data), runs pg_dumpall,
-# runs pg_upgrade, runs pg_dumpall again, compares the dumps.
-#
-# Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-
-set -e
-
-: ${MAKE=make}
-
-# Guard against parallel make issues (see comments in pg_regress.c)
-unset MAKEFLAGS
-unset MAKELEVEL
-
-# Run a given "initdb" binary and overlay the regression testing
-# authentication configuration.
-standard_initdb() {
- "$1" -N
- ../../src/test/regress/pg_regress --config-auth "$PGDATA"
-}
-
-# Establish how the server will listen for connections
-testhost=`uname -s`
-
-case $testhost in
- MINGW*)
- LISTEN_ADDRESSES="localhost"
- PGHOST=localhost
- ;;
- *)
- LISTEN_ADDRESSES=""
- # Select a socket directory. The algorithm is from the "configure"
- # script; the outcome mimics pg_regress.c:make_temp_sockdir().
- PGHOST=$PG_REGRESS_SOCK_DIR
- if [ "x$PGHOST" = x ]; then
- {
- dir=`(umask 077 &&
- mktemp -d /tmp/pg_upgrade_check-XXXXXX) 2>/dev/null` &&
- [ -d "$dir" ]
- } ||
- {
- dir=/tmp/pg_upgrade_check-$$-$RANDOM
- (umask 077 && mkdir "$dir")
- } ||
- {
- echo "could not create socket temporary directory in \"/tmp\""
- exit 1
- }
-
- PGHOST=$dir
- trap 'rm -rf "$PGHOST"' 0
- trap 'exit 3' 1 2 13 15
- fi
- ;;
-esac
-
-POSTMASTER_OPTS="-F -c listen_addresses=$LISTEN_ADDRESSES -k \"$PGHOST\""
-export PGHOST
-
-temp_root=$PWD/tmp_check
-
-if [ "$1" = '--install' ]; then
- temp_install=$temp_root/install
- bindir=$temp_install/$bindir
- libdir=$temp_install/$libdir
-
- "$MAKE" -s -C ../.. install DESTDIR="$temp_install"
- "$MAKE" -s -C . install DESTDIR="$temp_install"
-
- # platform-specific magic to find the shared libraries; see pg_regress.c
- LD_LIBRARY_PATH=$libdir:$LD_LIBRARY_PATH
- export LD_LIBRARY_PATH
- DYLD_LIBRARY_PATH=$libdir:$DYLD_LIBRARY_PATH
- export DYLD_LIBRARY_PATH
- LIBPATH=$libdir:$LIBPATH
- export LIBPATH
- PATH=$libdir:$PATH
-
- # We need to make it use psql from our temporary installation,
- # because otherwise the installcheck run below would try to
- # use psql from the proper installation directory, which might
- # be outdated or missing. But don't override anything else that's
- # already in EXTRA_REGRESS_OPTS.
- EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --psqldir='$bindir'"
- export EXTRA_REGRESS_OPTS
-fi
-
-: ${oldbindir=$bindir}
-
-: ${oldsrc=../..}
-oldsrc=`cd "$oldsrc" && pwd`
-newsrc=`cd ../.. && pwd`
-
-PATH=$bindir:$PATH
-export PATH
-
-BASE_PGDATA=$temp_root/data
-PGDATA="$BASE_PGDATA.old"
-export PGDATA
-rm -rf "$BASE_PGDATA" "$PGDATA"
-
-logdir=$PWD/log
-rm -rf "$logdir"
-mkdir "$logdir"
-
-# Clear out any environment vars that might cause libpq to connect to
-# the wrong postmaster (cf pg_regress.c)
-#
-# Some shells, such as NetBSD's, return non-zero from unset if the variable
-# is already unset. Since we are operating under 'set -e', this causes the
-# script to fail. To guard against this, set them all to an empty string first.
-PGDATABASE=""; unset PGDATABASE
-PGUSER=""; unset PGUSER
-PGSERVICE=""; unset PGSERVICE
-PGSSLMODE=""; unset PGSSLMODE
-PGREQUIRESSL=""; unset PGREQUIRESSL
-PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT
-PGHOSTADDR=""; unset PGHOSTADDR
-
-# Select a non-conflicting port number, similarly to pg_regress.c
-PG_VERSION_NUM=`grep '#define PG_VERSION_NUM' "$newsrc"/src/include/pg_config.h | awk '{print $3}'`
-PGPORT=`expr $PG_VERSION_NUM % 16384 + 49152`
-export PGPORT
-
-i=0
-while psql -X postgres </dev/null 2>/dev/null
-do
- i=`expr $i + 1`
- if [ $i -eq 16 ]
- then
- echo port $PGPORT apparently in use
- exit 1
- fi
- PGPORT=`expr $PGPORT + 1`
- export PGPORT
-done
-
-# buildfarm may try to override port via EXTRA_REGRESS_OPTS ...
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --port=$PGPORT"
-export EXTRA_REGRESS_OPTS
-
-# enable echo so the user can see what is being executed
-set -x
-
-standard_initdb "$oldbindir"/initdb
-"$oldbindir"/pg_ctl start -l "$logdir/postmaster1.log" -o "$POSTMASTER_OPTS" -w
-if "$MAKE" -C "$oldsrc" installcheck; then
- pg_dumpall -f "$temp_root"/dump1.sql || pg_dumpall1_status=$?
- if [ "$newsrc" != "$oldsrc" ]; then
- oldpgversion=`psql -A -t -d regression -c "SHOW server_version_num"`
- fix_sql=""
- case $oldpgversion in
- 804??)
- fix_sql="UPDATE pg_proc SET probin = replace(probin::text, '$oldsrc', '$newsrc')::bytea WHERE probin LIKE '$oldsrc%'; DROP FUNCTION public.myfunc(integer);"
- ;;
- 900??)
- fix_sql="SET bytea_output TO escape; UPDATE pg_proc SET probin = replace(probin::text, '$oldsrc', '$newsrc')::bytea WHERE probin LIKE '$oldsrc%';"
- ;;
- 901??)
- fix_sql="UPDATE pg_proc SET probin = replace(probin, '$oldsrc', '$newsrc') WHERE probin LIKE '$oldsrc%';"
- ;;
- esac
- psql -d regression -c "$fix_sql;" || psql_fix_sql_status=$?
-
- mv "$temp_root"/dump1.sql "$temp_root"/dump1.sql.orig
- sed "s;$oldsrc;$newsrc;g" "$temp_root"/dump1.sql.orig >"$temp_root"/dump1.sql
- fi
-else
- make_installcheck_status=$?
-fi
-"$oldbindir"/pg_ctl -m fast stop
-if [ -n "$make_installcheck_status" ]; then
- exit 1
-fi
-if [ -n "$psql_fix_sql_status" ]; then
- exit 1
-fi
-if [ -n "$pg_dumpall1_status" ]; then
- echo "pg_dumpall of pre-upgrade database cluster failed"
- exit 1
-fi
-
-PGDATA=$BASE_PGDATA
-
-standard_initdb 'initdb'
-
-pg_upgrade $PG_UPGRADE_OPTS -d "${PGDATA}.old" -D "${PGDATA}" -b "$oldbindir" -B "$bindir" -p "$PGPORT" -P "$PGPORT"
-
-pg_ctl start -l "$logdir/postmaster2.log" -o "$POSTMASTER_OPTS" -w
-
-case $testhost in
- MINGW*) cmd /c analyze_new_cluster.bat ;;
- *) sh ./analyze_new_cluster.sh ;;
-esac
-
-pg_dumpall -f "$temp_root"/dump2.sql || pg_dumpall2_status=$?
-pg_ctl -m fast stop
-
-# no need to echo commands anymore
-set +x
-echo
-
-if [ -n "$pg_dumpall2_status" ]; then
- echo "pg_dumpall of post-upgrade database cluster failed"
- exit 1
-fi
-
-case $testhost in
- MINGW*) cmd /c delete_old_cluster.bat ;;
- *) sh ./delete_old_cluster.sh ;;
-esac
-
-if diff -q "$temp_root"/dump1.sql "$temp_root"/dump2.sql; then
- echo PASSED
- exit 0
-else
- echo "dumps were not identical"
- exit 1
-fi
diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c
deleted file mode 100644
index 6184ceef933..00000000000
--- a/contrib/pg_upgrade/util.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * util.c
- *
- * utility functions
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/util.c
- */
-
-#include "postgres_fe.h"
-
-#include "common/username.h"
-#include "pg_upgrade.h"
-
-#include <signal.h>
-
-
-LogOpts log_opts;
-
-static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2, 0);
-
-
-/*
- * report_status()
- *
- * Displays the result of an operation (ok, failed, error message,...)
- */
-void
-report_status(eLogType type, const char *fmt,...)
-{
- va_list args;
- char message[MAX_STRING];
-
- va_start(args, fmt);
- vsnprintf(message, sizeof(message), fmt, args);
- va_end(args);
-
- pg_log(type, "%s\n", message);
-}
-
-
-/* force blank output for progress display */
-void
-end_progress_output(void)
-{
- /*
- * In case nothing printed; pass a space so gcc doesn't complain about
- * empty format string.
- */
- prep_status(" ");
-}
-
-
-/*
- * prep_status
- *
- * Displays a message that describes an operation we are about to begin.
- * We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
- * "failed" indicators line up nicely.
- *
- * A typical sequence would look like this:
- * prep_status("about to flarb the next %d files", fileCount );
- *
- * if(( message = flarbFiles(fileCount)) == NULL)
- * report_status(PG_REPORT, "ok" );
- * else
- * pg_log(PG_FATAL, "failed - %s\n", message );
- */
-void
-prep_status(const char *fmt,...)
-{
- va_list args;
- char message[MAX_STRING];
-
- va_start(args, fmt);
- vsnprintf(message, sizeof(message), fmt, args);
- va_end(args);
-
- if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
- pg_log(PG_REPORT, "%s", message);
- else
- /* trim strings that don't end in a newline */
- pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
-}
-
-
-static void
-pg_log_v(eLogType type, const char *fmt, va_list ap)
-{
- char message[QUERY_ALLOC];
-
- vsnprintf(message, sizeof(message), fmt, ap);
-
- /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
- /* fopen() on log_opts.internal might have failed, so check it */
- if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
- log_opts.internal != NULL)
- {
- if (type == PG_STATUS)
- /* status messages need two leading spaces and a newline */
- fprintf(log_opts.internal, " %s\n", message);
- else
- fprintf(log_opts.internal, "%s", message);
- fflush(log_opts.internal);
- }
-
- switch (type)
- {
- case PG_VERBOSE:
- if (log_opts.verbose)
- printf("%s", _(message));
- break;
-
- case PG_STATUS:
- /* for output to a display, do leading truncation and append \r */
- if (isatty(fileno(stdout)))
- /* -2 because we use a 2-space indent */
- printf(" %s%-*.*s\r",
- /* prefix with "..." if we do leading truncation */
- strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
- MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
- /* optional leading truncation */
- strlen(message) <= MESSAGE_WIDTH - 2 ? message :
- message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
- else
- printf(" %s\n", _(message));
- break;
-
- case PG_REPORT:
- case PG_WARNING:
- printf("%s", _(message));
- break;
-
- case PG_FATAL:
- printf("\n%s", _(message));
- printf("Failure, exiting\n");
- exit(1);
- break;
-
- default:
- break;
- }
- fflush(stdout);
-}
-
-
-void
-pg_log(eLogType type, const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- pg_log_v(type, fmt, args);
- va_end(args);
-}
-
-
-void
-pg_fatal(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- pg_log_v(PG_FATAL, fmt, args);
- va_end(args);
- printf("Failure, exiting\n");
- exit(1);
-}
-
-
-void
-check_ok(void)
-{
- /* all seems well */
- report_status(PG_REPORT, "ok");
- fflush(stdout);
-}
-
-
-/*
- * quote_identifier()
- * Properly double-quote a SQL identifier.
- *
- * The result should be pg_free'd, but most callers don't bother because
- * memory leakage is not a big deal in this program.
- */
-char *
-quote_identifier(const char *s)
-{
- 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;
-}
-
-
-/*
- * get_user_info()
- */
-int
-get_user_info(char **user_name_p)
-{
- int user_id;
- const char *user_name;
- char *errstr;
-
-#ifndef WIN32
- user_id = geteuid();
-#else
- user_id = 1;
-#endif
-
- user_name = get_user_name(&errstr);
- if (!user_name)
- pg_fatal("%s\n", errstr);
-
- /* make a copy */
- *user_name_p = pg_strdup(user_name);
-
- return user_id;
-}
-
-
-/*
- * getErrorText()
- *
- * Returns the text of the error message for the given error number
- *
- * This feature is factored into a separate function because it is
- * system-dependent.
- */
-const char *
-getErrorText(int errNum)
-{
-#ifdef WIN32
- _dosmaperr(GetLastError());
-#endif
- return pg_strdup(strerror(errNum));
-}
-
-
-/*
- * str2uint()
- *
- * convert string to oid
- */
-unsigned int
-str2uint(const char *str)
-{
- return strtoul(str, NULL, 10);
-}
-
-
-/*
- * pg_putenv()
- *
- * This is like putenv(), but takes two arguments.
- * It also does unsetenv() if val is NULL.
- */
-void
-pg_putenv(const char *var, const char *val)
-{
- if (val)
- {
-#ifndef WIN32
- char *envstr;
-
- envstr = psprintf("%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
- }
-}
diff --git a/contrib/pg_upgrade/version.c b/contrib/pg_upgrade/version.c
deleted file mode 100644
index 4ae9511d045..00000000000
--- a/contrib/pg_upgrade/version.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * version.c
- *
- * Postgres-version-specific routines
- *
- * Copyright (c) 2010-2015, PostgreSQL Global Development Group
- * contrib/pg_upgrade/version.c
- */
-
-#include "postgres_fe.h"
-
-#include "pg_upgrade.h"
-
-
-
-/*
- * new_9_0_populate_pg_largeobject_metadata()
- * new >= 9.0, old <= 8.4
- * 9.0 has a new pg_largeobject permission table
- */
-void
-new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster, bool check_mode)
-{
- 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_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();
-}
-
-
-/*
- * old_9_3_check_for_line_data_type_usage()
- * 9.3 -> 9.4
- * Fully implement the 'line' data type in 9.4, which previously returned
- * "not enabled" by default and was only functionally enabled with a
- * compile-time switch; 9.4 "line" has different binary and text
- * representation formats; checks tables and indexes.
- */
-void
-old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
-{
- int dbnum;
- FILE *script = NULL;
- bool found = false;
- char output_path[MAXPGPATH];
-
- prep_status("Checking for invalid \"line\" user columns");
-
- snprintf(output_path, sizeof(output_path), "tables_using_line.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);
-
- 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 "
- " NOT a.attisdropped AND "
- " a.atttypid = 'pg_catalog.line'::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_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_fatal("Your installation contains the \"line\" data type in user tables. This\n"
- "data type changed its internal and input/output format between your old\n"
- "and new clusters so this cluster cannot currently be upgraded. You can\n"
- "remove 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();
-}