pg_upgrade: remove support for 8.3 old clusters
This trims down the code, and is in preparation for hardening pg_upgrade against auto-oid assignment.
This commit is contained in:
parent
b0488e5c4f
commit
2209b3923a
@ -6,7 +6,7 @@ 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 version_old_8_3.o $(WIN32RES)
|
||||
tablespace.o util.o version.o $(WIN32RES)
|
||||
|
||||
PG_CPPFLAGS = -DFRONTEND -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir)
|
||||
PG_LIBS = $(libpq_pgport)
|
||||
|
@ -73,7 +73,7 @@ output_check_banner(bool live_check)
|
||||
|
||||
|
||||
void
|
||||
check_and_dump_old_cluster(bool live_check, char **sequence_script_file_name)
|
||||
check_and_dump_old_cluster(bool live_check)
|
||||
{
|
||||
/* -- OLD -- */
|
||||
|
||||
@ -100,29 +100,6 @@ check_and_dump_old_cluster(bool live_check, char **sequence_script_file_name)
|
||||
check_for_reg_data_type_usage(&old_cluster);
|
||||
check_for_isn_and_int8_passing_mismatch(&old_cluster);
|
||||
|
||||
/* old = PG 8.3 checks? */
|
||||
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
|
||||
{
|
||||
old_8_3_check_for_name_data_type_usage(&old_cluster);
|
||||
old_8_3_check_for_tsquery_usage(&old_cluster);
|
||||
old_8_3_check_ltree_usage(&old_cluster);
|
||||
if (user_opts.check)
|
||||
{
|
||||
old_8_3_rebuild_tsvector_tables(&old_cluster, true);
|
||||
old_8_3_invalidate_hash_gin_indexes(&old_cluster, true);
|
||||
old_8_3_invalidate_bpchar_pattern_ops_indexes(&old_cluster, true);
|
||||
}
|
||||
else
|
||||
|
||||
/*
|
||||
* While we have the old server running, create the script to
|
||||
* properly restore its sequence values but we report this at the
|
||||
* end.
|
||||
*/
|
||||
*sequence_script_file_name =
|
||||
old_8_3_create_sequence_script(&old_cluster);
|
||||
}
|
||||
|
||||
/* Pre-PG 9.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);
|
||||
@ -183,31 +160,8 @@ report_clusters_compatible(void)
|
||||
|
||||
|
||||
void
|
||||
issue_warnings(char *sequence_script_file_name)
|
||||
issue_warnings(void)
|
||||
{
|
||||
/* old = PG 8.3 warnings? */
|
||||
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
|
||||
{
|
||||
start_postmaster(&new_cluster, true);
|
||||
|
||||
/* restore proper sequence values using file created from old server */
|
||||
if (sequence_script_file_name)
|
||||
{
|
||||
prep_status("Adjusting sequences");
|
||||
exec_prog(UTILITY_LOG_FILE, NULL, true,
|
||||
"\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
|
||||
new_cluster.bindir, cluster_conn_opts(&new_cluster),
|
||||
sequence_script_file_name);
|
||||
unlink(sequence_script_file_name);
|
||||
check_ok();
|
||||
}
|
||||
|
||||
old_8_3_rebuild_tsvector_tables(&new_cluster, false);
|
||||
old_8_3_invalidate_hash_gin_indexes(&new_cluster, false);
|
||||
old_8_3_invalidate_bpchar_pattern_ops_indexes(&new_cluster, false);
|
||||
stop_postmaster(false);
|
||||
}
|
||||
|
||||
/* Create dummy large object permissions for old < PG 9.0? */
|
||||
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
|
||||
{
|
||||
@ -262,8 +216,8 @@ check_cluster_versions(void)
|
||||
* upgrades
|
||||
*/
|
||||
|
||||
if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
|
||||
pg_fatal("This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
|
||||
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))
|
||||
|
@ -125,13 +125,6 @@ get_control_data(ClusterInfo *cluster, bool live_check)
|
||||
cluster->controldata.lc_collate = NULL;
|
||||
cluster->controldata.lc_ctype = NULL;
|
||||
|
||||
/* Only in <= 8.3 */
|
||||
if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
|
||||
{
|
||||
cluster->controldata.float8_pass_by_value = false;
|
||||
got_float8_pass_by_value = true;
|
||||
}
|
||||
|
||||
/* Only in <= 9.2 */
|
||||
if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
|
||||
{
|
||||
@ -144,23 +137,6 @@ get_control_data(ClusterInfo *cluster, bool live_check)
|
||||
{
|
||||
pg_log(PG_VERBOSE, "%s", bufin);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
* Due to an installer bug, LANG=C doesn't work for PG 8.3.3, but does
|
||||
* work 8.2.6 and 8.3.7, so check for non-ASCII output and suggest a
|
||||
* minor upgrade.
|
||||
*/
|
||||
if (GET_MAJOR_VERSION(cluster->major_version) <= 803)
|
||||
{
|
||||
for (p = bufin; *p; p++)
|
||||
if (!isascii((unsigned char) *p))
|
||||
pg_fatal("The 8.3 cluster's pg_controldata is incapable of outputting ASCII, even\n"
|
||||
"with LANG=C. You must upgrade this cluster to a newer version of PostgreSQL\n"
|
||||
"8.3 to fix this bug. PostgreSQL 8.3.7 and later are known to work properly.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((p = strstr(bufin, "pg_control version number:")) != NULL)
|
||||
{
|
||||
p = strchr(p, ':');
|
||||
@ -550,7 +526,6 @@ get_control_data(ClusterInfo *cluster, bool live_check)
|
||||
if (!got_date_is_int)
|
||||
pg_log(PG_REPORT, " dates/times are integers?\n");
|
||||
|
||||
/* value added in Postgres 8.4 */
|
||||
if (!got_float8_pass_by_value)
|
||||
pg_log(PG_REPORT, " float8 argument passing method\n");
|
||||
|
||||
@ -598,17 +573,7 @@ check_control_data(ControlData *oldctrl,
|
||||
pg_fatal("old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n");
|
||||
|
||||
if (oldctrl->date_is_int != newctrl->date_is_int)
|
||||
{
|
||||
pg_log(PG_WARNING,
|
||||
"\nOld and new pg_controldata date/time storage types do not match.\n");
|
||||
|
||||
/*
|
||||
* This is a common 8.3 -> 8.4 upgrade problem, so we are more verbose
|
||||
*/
|
||||
pg_fatal("You will need to rebuild the new server with configure option\n"
|
||||
"--disable-integer-datetimes or get server binaries built with those\n"
|
||||
"options.\n");
|
||||
}
|
||||
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
|
||||
|
@ -325,7 +325,7 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
|
||||
" 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 "
|
||||
"WHERE relkind IN ('r', 'm', 'i', 'S') AND "
|
||||
|
||||
/*
|
||||
* pg_dump only dumps valid indexes; testing indisready is necessary in
|
||||
@ -342,9 +342,6 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
|
||||
" c.oid >= %u) "
|
||||
" OR (n.nspname = 'pg_catalog' AND "
|
||||
" relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) ));",
|
||||
/* see the comment at the top of old_8_3_create_sequence_script() */
|
||||
(GET_MAJOR_VERSION(old_cluster.major_version) <= 803) ?
|
||||
"" : ", 'S'",
|
||||
FirstNormalObjectId,
|
||||
/* does pg_largeobject_metadata need to be migrated? */
|
||||
(GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
|
||||
|
@ -69,7 +69,6 @@ char *output_files[] = {
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *sequence_script_file_name = NULL;
|
||||
char *analyze_script_file_name = NULL;
|
||||
char *deletion_script_file_name = NULL;
|
||||
bool live_check = false;
|
||||
@ -90,7 +89,7 @@ main(int argc, char **argv)
|
||||
|
||||
check_cluster_compatibility(live_check);
|
||||
|
||||
check_and_dump_old_cluster(live_check, &sequence_script_file_name);
|
||||
check_and_dump_old_cluster(live_check);
|
||||
|
||||
|
||||
/* -- NEW -- */
|
||||
@ -157,7 +156,7 @@ main(int argc, char **argv)
|
||||
create_script_for_cluster_analyze(&analyze_script_file_name);
|
||||
create_script_for_old_cluster_deletion(&deletion_script_file_name);
|
||||
|
||||
issue_warnings(sequence_script_file_name);
|
||||
issue_warnings();
|
||||
|
||||
pg_log(PG_REPORT, "\nUpgrade Complete\n");
|
||||
pg_log(PG_REPORT, "----------------\n");
|
||||
@ -167,7 +166,6 @@ main(int argc, char **argv)
|
||||
|
||||
pg_free(analyze_script_file_name);
|
||||
pg_free(deletion_script_file_name);
|
||||
pg_free(sequence_script_file_name);
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -313,11 +313,10 @@ extern OSInfo os_info;
|
||||
/* check.c */
|
||||
|
||||
void output_check_banner(bool live_check);
|
||||
void check_and_dump_old_cluster(bool live_check,
|
||||
char **sequence_script_file_name);
|
||||
void check_and_dump_old_cluster(bool live_check);
|
||||
void check_new_cluster(void);
|
||||
void report_clusters_compatible(void);
|
||||
void issue_warnings(char *sequence_script_file_name);
|
||||
void issue_warnings(void);
|
||||
void output_completion_banner(char *analyze_script_file_name,
|
||||
char *deletion_script_file_name);
|
||||
void check_cluster_versions(void);
|
||||
@ -471,17 +470,6 @@ 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);
|
||||
|
||||
/* version_old_8_3.c */
|
||||
|
||||
void old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster);
|
||||
void old_8_3_check_for_tsquery_usage(ClusterInfo *cluster);
|
||||
void old_8_3_check_ltree_usage(ClusterInfo *cluster);
|
||||
void old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode);
|
||||
void old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode);
|
||||
void old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
|
||||
bool check_mode);
|
||||
char *old_8_3_create_sequence_script(ClusterInfo *cluster);
|
||||
|
||||
/* parallel.c */
|
||||
void
|
||||
parallel_exec_prog(const char *log_file, const char *opt_log_file,
|
||||
|
@ -1,769 +0,0 @@
|
||||
/*
|
||||
* version.c
|
||||
*
|
||||
* Postgres-version-specific routines
|
||||
*
|
||||
* Copyright (c) 2010-2014, PostgreSQL Global Development Group
|
||||
* contrib/pg_upgrade/version_old_8_3.c
|
||||
*/
|
||||
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include "pg_upgrade.h"
|
||||
|
||||
#include "access/transam.h"
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_check_for_name_data_type_usage()
|
||||
* 8.3 -> 8.4
|
||||
* Alignment for the 'name' data type changed to 'char' in 8.4;
|
||||
* checks tables and indexes.
|
||||
*/
|
||||
void
|
||||
old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for invalid \"name\" user columns");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "tables_using_name.txt");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname,
|
||||
i_attname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/*
|
||||
* With a smaller alignment in 8.4, 'name' cannot be used in a
|
||||
* non-pg_catalog table, except as the first column. (We could tighten
|
||||
* that condition with enough analysis, but it seems not worth the
|
||||
* trouble.)
|
||||
*/
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname, a.attname "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n, "
|
||||
" pg_catalog.pg_attribute a "
|
||||
"WHERE c.oid = a.attrelid AND "
|
||||
" a.attnum > 1 AND "
|
||||
" NOT a.attisdropped AND "
|
||||
" a.atttypid = 'pg_catalog.name'::pg_catalog.regtype AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
/* exclude possible orphaned temp tables */
|
||||
" n.nspname !~ '^pg_temp_' AND "
|
||||
" n.nspname !~ '^pg_toast_temp_' AND "
|
||||
" n.nspname NOT IN ('pg_catalog', 'information_schema')");
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
i_attname = PQfnumber(res, "attname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_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 \"name\" data type in user tables. This\n"
|
||||
"data type changed its internal alignment between your old and new\n"
|
||||
"clusters so this cluster cannot currently be upgraded. You can remove\n"
|
||||
"the problem tables and restart the upgrade. A list of the problem\n"
|
||||
"columns is in the file:\n"
|
||||
" %s\n\n", output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_check_for_tsquery_usage()
|
||||
* 8.3 -> 8.4
|
||||
* A new 'prefix' field was added to the 'tsquery' data type in 8.4
|
||||
* so upgrading of such fields is impossible.
|
||||
*/
|
||||
void
|
||||
old_8_3_check_for_tsquery_usage(ClusterInfo *cluster)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for tsquery user columns");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "tables_using_tsquery.txt");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname,
|
||||
i_attname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* Find any user-defined tsquery columns */
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname, a.attname "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n, "
|
||||
" pg_catalog.pg_attribute a "
|
||||
/* materialized views didn't exist in 8.3, so no need to check 'm' */
|
||||
"WHERE c.relkind = 'r' AND "
|
||||
" c.oid = a.attrelid AND "
|
||||
" NOT a.attisdropped AND "
|
||||
" a.atttypid = 'pg_catalog.tsquery'::pg_catalog.regtype AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
/* exclude possible orphaned temp tables */
|
||||
" n.nspname !~ '^pg_temp_' AND "
|
||||
" n.nspname !~ '^pg_toast_temp_' AND "
|
||||
" n.nspname NOT IN ('pg_catalog', 'information_schema')");
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
i_attname = PQfnumber(res, "attname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_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 \"tsquery\" data type. This data type\n"
|
||||
"added a new internal field between your old and new clusters so this\n"
|
||||
"cluster cannot currently be upgraded. You can remove the problem\n"
|
||||
"columns and restart the upgrade. A list of the problem columns is in the\n"
|
||||
"file:\n"
|
||||
" %s\n\n", output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_check_ltree_usage()
|
||||
* 8.3 -> 8.4
|
||||
* The internal ltree structure was changed in 8.4 so upgrading is impossible.
|
||||
*/
|
||||
void
|
||||
old_8_3_check_ltree_usage(ClusterInfo *cluster)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for contrib/ltree");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "contrib_ltree.txt");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_proname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* Find any functions coming from contrib/ltree */
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, p.proname "
|
||||
"FROM pg_catalog.pg_proc p, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE p.pronamespace = n.oid AND "
|
||||
" p.probin = '$libdir/ltree'");
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_proname = PQfnumber(res, "proname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_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 the \"ltree\" data type. This data type\n"
|
||||
"changed its internal storage format between your old and new clusters so this\n"
|
||||
"cluster cannot currently be upgraded. You can manually upgrade databases\n"
|
||||
"that use \"contrib/ltree\" facilities and remove \"contrib/ltree\" from the old\n"
|
||||
"cluster and restart the upgrade. A list of the problem functions is in the\n"
|
||||
"file:\n"
|
||||
" %s\n\n", output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_rebuild_tsvector_tables()
|
||||
* 8.3 -> 8.4
|
||||
* 8.3 sorts lexemes by its length and if lengths are the same then it uses
|
||||
* alphabetic order; 8.4 sorts lexemes in lexicographical order, e.g.
|
||||
*
|
||||
* => SELECT 'c bb aaa'::tsvector;
|
||||
* tsvector
|
||||
* ----------------
|
||||
* 'aaa' 'bb' 'c' -- 8.4
|
||||
* 'c' 'bb' 'aaa' -- 8.3
|
||||
*/
|
||||
void
|
||||
old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for tsvector user columns");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "rebuild_tsvector_tables.sql");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
char nspname[NAMEDATALEN] = "",
|
||||
relname[NAMEDATALEN] = "";
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname,
|
||||
i_attname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* Find any user-defined tsvector columns */
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname, a.attname "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n, "
|
||||
" pg_catalog.pg_attribute a "
|
||||
/* materialized views didn't exist in 8.3, so no need to check 'm' */
|
||||
"WHERE c.relkind = 'r' AND "
|
||||
" c.oid = a.attrelid AND "
|
||||
" NOT a.attisdropped AND "
|
||||
/* child attribute changes are processed by the parent */
|
||||
" a.attinhcount = 0 AND "
|
||||
" a.atttypid = 'pg_catalog.tsvector'::pg_catalog.regtype AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
/* exclude possible orphaned temp tables */
|
||||
" n.nspname !~ '^pg_temp_' AND "
|
||||
" n.nspname !~ '^pg_toast_temp_' AND "
|
||||
" n.nspname NOT IN ('pg_catalog', 'information_schema')");
|
||||
|
||||
/*
|
||||
* This macro is used below to avoid reindexing indexes already rebuilt
|
||||
* because of tsvector columns.
|
||||
*/
|
||||
#define SKIP_TSVECTOR_TABLES \
|
||||
"i.indrelid NOT IN ( " \
|
||||
"SELECT DISTINCT c.oid " \
|
||||
"FROM pg_catalog.pg_class c, " \
|
||||
" pg_catalog.pg_namespace n, " \
|
||||
" pg_catalog.pg_attribute a " \
|
||||
/* materialized views didn't exist in 8.3, so no need to check 'm' */ \
|
||||
"WHERE c.relkind = 'r' AND " \
|
||||
" c.oid = a.attrelid AND " \
|
||||
" NOT a.attisdropped AND " \
|
||||
/* child attribute changes are processed by the parent */ \
|
||||
" a.attinhcount = 0 AND " \
|
||||
" a.atttypid = 'pg_catalog.tsvector'::pg_catalog.regtype AND " \
|
||||
" c.relnamespace = n.oid AND " \
|
||||
" n.nspname !~ '^pg_' AND " \
|
||||
" n.nspname != 'information_schema') "
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
i_attname = PQfnumber(res, "attname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (!check_mode)
|
||||
{
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_fatal("could not open file \"%s\": %s\n", output_path, getErrorText(errno));
|
||||
if (!db_used)
|
||||
{
|
||||
fprintf(script, "\\connect %s\n\n",
|
||||
quote_identifier(active_db->db_name));
|
||||
db_used = true;
|
||||
}
|
||||
|
||||
/* Rebuild all tsvector collumns with one ALTER TABLE command */
|
||||
if (strcmp(PQgetvalue(res, rowno, i_nspname), nspname) != 0 ||
|
||||
strcmp(PQgetvalue(res, rowno, i_relname), relname) != 0)
|
||||
{
|
||||
if (strlen(nspname) != 0 || strlen(relname) != 0)
|
||||
fprintf(script, ";\n\n");
|
||||
fprintf(script, "ALTER TABLE %s.%s\n",
|
||||
quote_identifier(PQgetvalue(res, rowno, i_nspname)),
|
||||
quote_identifier(PQgetvalue(res, rowno, i_relname)));
|
||||
}
|
||||
else
|
||||
fprintf(script, ",\n");
|
||||
strlcpy(nspname, PQgetvalue(res, rowno, i_nspname), sizeof(nspname));
|
||||
strlcpy(relname, PQgetvalue(res, rowno, i_relname), sizeof(relname));
|
||||
|
||||
fprintf(script, "ALTER COLUMN %s "
|
||||
/* This could have been a custom conversion function call. */
|
||||
"TYPE pg_catalog.tsvector USING %s::pg_catalog.text::pg_catalog.tsvector",
|
||||
quote_identifier(PQgetvalue(res, rowno, i_attname)),
|
||||
quote_identifier(PQgetvalue(res, rowno, i_attname)));
|
||||
}
|
||||
}
|
||||
if (strlen(nspname) != 0 || strlen(relname) != 0)
|
||||
fprintf(script, ";\n\n");
|
||||
|
||||
PQclear(res);
|
||||
|
||||
/* XXX Mark tables as not accessible somehow */
|
||||
|
||||
PQfinish(conn);
|
||||
}
|
||||
|
||||
if (script)
|
||||
fclose(script);
|
||||
|
||||
if (found)
|
||||
{
|
||||
report_status(PG_WARNING, "warning");
|
||||
if (check_mode)
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains tsvector columns. The tsvector internal\n"
|
||||
"storage format changed between your old and new clusters so the tables\n"
|
||||
"must be rebuilt. After upgrading, you will be given instructions.\n\n");
|
||||
else
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains tsvector columns. The tsvector internal\n"
|
||||
"storage format changed between your old and new clusters so the tables\n"
|
||||
"must be rebuilt. The file:\n"
|
||||
" %s\n"
|
||||
"when executed by psql by the database superuser will rebuild all tables\n"
|
||||
"with tsvector columns.\n\n",
|
||||
output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_invalidate_hash_gin_indexes()
|
||||
* 8.3 -> 8.4
|
||||
* Hash and GIN index binary format changed from 8.3->8.4
|
||||
*/
|
||||
void
|
||||
old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for hash and GIN indexes");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "reindex_hash_and_gin.sql");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* find hash and gin indexes */
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_index i, "
|
||||
" pg_catalog.pg_am a, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE i.indexrelid = c.oid AND "
|
||||
" c.relam = a.oid AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
" a.amname IN ('hash', 'gin') AND "
|
||||
SKIP_TSVECTOR_TABLES);
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (!check_mode)
|
||||
{
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_fatal("could not open file \"%s\": %s\n", output_path, getErrorText(errno));
|
||||
if (!db_used)
|
||||
{
|
||||
fprintf(script, "\\connect %s\n",
|
||||
quote_identifier(active_db->db_name));
|
||||
db_used = true;
|
||||
}
|
||||
fprintf(script, "REINDEX INDEX %s.%s;\n",
|
||||
quote_identifier(PQgetvalue(res, rowno, i_nspname)),
|
||||
quote_identifier(PQgetvalue(res, rowno, i_relname)));
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
if (!check_mode && found)
|
||||
/* mark hash and gin indexes as invalid */
|
||||
PQclear(executeQueryOrDie(conn,
|
||||
"UPDATE pg_catalog.pg_index i "
|
||||
"SET indisvalid = false "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_am a, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE i.indexrelid = c.oid AND "
|
||||
" c.relam = a.oid AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
" a.amname IN ('hash', 'gin')"));
|
||||
|
||||
PQfinish(conn);
|
||||
}
|
||||
|
||||
if (script)
|
||||
fclose(script);
|
||||
|
||||
if (found)
|
||||
{
|
||||
report_status(PG_WARNING, "warning");
|
||||
if (check_mode)
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains hash and/or GIN indexes. These indexes have\n"
|
||||
"different internal formats between your old and new clusters, so they\n"
|
||||
"must be reindexed with the REINDEX command. After upgrading, you will\n"
|
||||
"be given REINDEX instructions.\n\n");
|
||||
else
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains hash and/or GIN indexes. These indexes have\n"
|
||||
"different internal formats between your old and new clusters, so they\n"
|
||||
"must be reindexed with the REINDEX command. The file:\n"
|
||||
" %s\n"
|
||||
"when executed by psql by the database superuser will recreate all invalid\n"
|
||||
"indexes; until then, none of these indexes will be used.\n\n",
|
||||
output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_invalidate_bpchar_pattern_ops_indexes()
|
||||
* 8.3 -> 8.4
|
||||
* 8.4 bpchar_pattern_ops no longer sorts based on trailing spaces
|
||||
*/
|
||||
void
|
||||
old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
|
||||
bool check_mode)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char output_path[MAXPGPATH];
|
||||
|
||||
prep_status("Checking for bpchar_pattern_ops indexes");
|
||||
|
||||
snprintf(output_path, sizeof(output_path), "reindex_bpchar_ops.sql");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* find bpchar_pattern_ops indexes */
|
||||
|
||||
/*
|
||||
* Do only non-hash, non-gin indexees; we already invalidated them
|
||||
* above; no need to reindex twice
|
||||
*/
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname "
|
||||
"FROM pg_catalog.pg_index i, "
|
||||
" pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE indexrelid = c.oid AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
" ( "
|
||||
" SELECT o.oid "
|
||||
" FROM pg_catalog.pg_opclass o, "
|
||||
" pg_catalog.pg_am a"
|
||||
" WHERE a.amname NOT IN ('hash', 'gin') AND "
|
||||
" a.oid = o.opcmethod AND "
|
||||
" o.opcname = 'bpchar_pattern_ops') "
|
||||
" = ANY (i.indclass) AND "
|
||||
SKIP_TSVECTOR_TABLES);
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
found = true;
|
||||
if (!check_mode)
|
||||
{
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_fatal("could not open file \"%s\": %s\n", output_path, getErrorText(errno));
|
||||
if (!db_used)
|
||||
{
|
||||
fprintf(script, "\\connect %s\n",
|
||||
quote_identifier(active_db->db_name));
|
||||
db_used = true;
|
||||
}
|
||||
fprintf(script, "REINDEX INDEX %s.%s;\n",
|
||||
quote_identifier(PQgetvalue(res, rowno, i_nspname)),
|
||||
quote_identifier(PQgetvalue(res, rowno, i_relname)));
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
if (!check_mode && found)
|
||||
/* mark bpchar_pattern_ops indexes as invalid */
|
||||
PQclear(executeQueryOrDie(conn,
|
||||
"UPDATE pg_catalog.pg_index i "
|
||||
"SET indisvalid = false "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE indexrelid = c.oid AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
" ( "
|
||||
" SELECT o.oid "
|
||||
" FROM pg_catalog.pg_opclass o, "
|
||||
" pg_catalog.pg_am a"
|
||||
" WHERE a.amname NOT IN ('hash', 'gin') AND "
|
||||
" a.oid = o.opcmethod AND "
|
||||
" o.opcname = 'bpchar_pattern_ops') "
|
||||
" = ANY (i.indclass)"));
|
||||
|
||||
PQfinish(conn);
|
||||
}
|
||||
|
||||
if (script)
|
||||
fclose(script);
|
||||
|
||||
if (found)
|
||||
{
|
||||
report_status(PG_WARNING, "warning");
|
||||
if (check_mode)
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains indexes using \"bpchar_pattern_ops\". These\n"
|
||||
"indexes have different internal formats between your old and new clusters\n"
|
||||
"so they must be reindexed with the REINDEX command. After upgrading, you\n"
|
||||
"will be given REINDEX instructions.\n\n");
|
||||
else
|
||||
pg_log(PG_WARNING, "\n"
|
||||
"Your installation contains indexes using \"bpchar_pattern_ops\". These\n"
|
||||
"indexes have different internal formats between your old and new clusters\n"
|
||||
"so they must be reindexed with the REINDEX command. The file:\n"
|
||||
" %s\n"
|
||||
"when executed by psql by the database superuser will recreate all invalid\n"
|
||||
"indexes; until then, none of these indexes will be used.\n\n",
|
||||
output_path);
|
||||
}
|
||||
else
|
||||
check_ok();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* old_8_3_create_sequence_script()
|
||||
* 8.3 -> 8.4
|
||||
* 8.4 added the column "start_value" to all sequences. For this reason,
|
||||
* we don't transfer sequence files but instead use the CREATE SEQUENCE
|
||||
* command from the schema dump, and use setval() to restore the sequence
|
||||
* value and 'is_called' from the old database. This is safe to run
|
||||
* by pg_upgrade because sequence files are not transferred from the old
|
||||
* server, even in link mode.
|
||||
*/
|
||||
char *
|
||||
old_8_3_create_sequence_script(ClusterInfo *cluster)
|
||||
{
|
||||
int dbnum;
|
||||
FILE *script = NULL;
|
||||
bool found = false;
|
||||
char *output_path;
|
||||
|
||||
output_path = pg_strdup("adjust_sequences.sql");
|
||||
|
||||
prep_status("Creating script to adjust sequences");
|
||||
|
||||
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
|
||||
{
|
||||
PGresult *res;
|
||||
bool db_used = false;
|
||||
int ntups;
|
||||
int rowno;
|
||||
int i_nspname,
|
||||
i_relname;
|
||||
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
|
||||
PGconn *conn = connectToServer(cluster, active_db->db_name);
|
||||
|
||||
/* Find any sequences */
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT n.nspname, c.relname "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE c.relkind = 'S' AND "
|
||||
" c.relnamespace = n.oid AND "
|
||||
/* exclude possible orphaned temp tables */
|
||||
" n.nspname !~ '^pg_temp_' AND "
|
||||
" n.nspname !~ '^pg_toast_temp_' AND "
|
||||
" n.nspname NOT IN ('pg_catalog', 'information_schema')");
|
||||
|
||||
ntups = PQntuples(res);
|
||||
i_nspname = PQfnumber(res, "nspname");
|
||||
i_relname = PQfnumber(res, "relname");
|
||||
for (rowno = 0; rowno < ntups; rowno++)
|
||||
{
|
||||
PGresult *seq_res;
|
||||
int i_last_value,
|
||||
i_is_called;
|
||||
const char *nspname = PQgetvalue(res, rowno, i_nspname);
|
||||
const char *relname = PQgetvalue(res, rowno, i_relname);
|
||||
|
||||
found = true;
|
||||
|
||||
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
|
||||
pg_fatal("could not open file \"%s\": %s\n", output_path, getErrorText(errno));
|
||||
if (!db_used)
|
||||
{
|
||||
fprintf(script, "\\connect %s\n\n",
|
||||
quote_identifier(active_db->db_name));
|
||||
db_used = true;
|
||||
}
|
||||
|
||||
/* Find the desired sequence */
|
||||
seq_res = executeQueryOrDie(conn,
|
||||
"SELECT s.last_value, s.is_called "
|
||||
"FROM %s.%s s",
|
||||
quote_identifier(nspname),
|
||||
quote_identifier(relname));
|
||||
|
||||
assert(PQntuples(seq_res) == 1);
|
||||
i_last_value = PQfnumber(seq_res, "last_value");
|
||||
i_is_called = PQfnumber(seq_res, "is_called");
|
||||
|
||||
fprintf(script, "SELECT setval('%s.%s', %s, '%s');\n",
|
||||
quote_identifier(nspname), quote_identifier(relname),
|
||||
PQgetvalue(seq_res, 0, i_last_value), PQgetvalue(seq_res, 0, i_is_called));
|
||||
PQclear(seq_res);
|
||||
}
|
||||
if (db_used)
|
||||
fprintf(script, "\n");
|
||||
|
||||
PQclear(res);
|
||||
|
||||
PQfinish(conn);
|
||||
}
|
||||
|
||||
if (script)
|
||||
fclose(script);
|
||||
|
||||
check_ok();
|
||||
|
||||
if (found)
|
||||
return output_path;
|
||||
else
|
||||
{
|
||||
pg_free(output_path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user