mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -6,7 +6,7 @@ PGAPPICON = win32
 | 
				
			|||||||
PROGRAM  = pg_upgrade
 | 
					PROGRAM  = pg_upgrade
 | 
				
			||||||
OBJS = check.o controldata.o dump.o exec.o file.o function.o info.o \
 | 
					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 \
 | 
					       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_CPPFLAGS  = -DFRONTEND -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir)
 | 
				
			||||||
PG_LIBS = $(libpq_pgport)
 | 
					PG_LIBS = $(libpq_pgport)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,7 @@ output_check_banner(bool live_check)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
check_and_dump_old_cluster(bool live_check, char **sequence_script_file_name)
 | 
					check_and_dump_old_cluster(bool live_check)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* -- OLD -- */
 | 
						/* -- 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_reg_data_type_usage(&old_cluster);
 | 
				
			||||||
	check_for_isn_and_int8_passing_mismatch(&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 */
 | 
						/* Pre-PG 9.4 had a different 'line' data type internal format */
 | 
				
			||||||
	if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
 | 
						if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
 | 
				
			||||||
		old_9_3_check_for_line_data_type_usage(&old_cluster);
 | 
							old_9_3_check_for_line_data_type_usage(&old_cluster);
 | 
				
			||||||
@@ -183,31 +160,8 @@ report_clusters_compatible(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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? */
 | 
						/* Create dummy large object permissions for old < PG 9.0? */
 | 
				
			||||||
	if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
 | 
						if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -262,8 +216,8 @@ check_cluster_versions(void)
 | 
				
			|||||||
	 * upgrades
 | 
						 * upgrades
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
 | 
						if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
 | 
				
			||||||
		pg_fatal("This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
 | 
							pg_fatal("This utility can only upgrade from PostgreSQL version 8.4 and later.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Only current PG version is supported as a target */
 | 
						/* Only current PG version is supported as a target */
 | 
				
			||||||
	if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
 | 
						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_collate = NULL;
 | 
				
			||||||
	cluster->controldata.lc_ctype = 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 */
 | 
						/* Only in <= 9.2 */
 | 
				
			||||||
	if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
 | 
						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);
 | 
							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)
 | 
							if ((p = strstr(bufin, "pg_control version number:")) != NULL)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			p = strchr(p, ':');
 | 
								p = strchr(p, ':');
 | 
				
			||||||
@@ -550,7 +526,6 @@ get_control_data(ClusterInfo *cluster, bool live_check)
 | 
				
			|||||||
		if (!got_date_is_int)
 | 
							if (!got_date_is_int)
 | 
				
			||||||
			pg_log(PG_REPORT, "  dates/times are integers?\n");
 | 
								pg_log(PG_REPORT, "  dates/times are integers?\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* value added in Postgres 8.4 */
 | 
					 | 
				
			||||||
		if (!got_float8_pass_by_value)
 | 
							if (!got_float8_pass_by_value)
 | 
				
			||||||
			pg_log(PG_REPORT, "  float8 argument passing method\n");
 | 
								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");
 | 
							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)
 | 
						if (oldctrl->date_is_int != newctrl->date_is_int)
 | 
				
			||||||
	{
 | 
							pg_fatal("old and new pg_controldata date/time storage types do not match\n");
 | 
				
			||||||
		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");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We might eventually allow upgrades from checksum to no-checksum
 | 
						 * 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 "
 | 
								 "	   ON c.relnamespace = n.oid "
 | 
				
			||||||
			 "LEFT OUTER JOIN pg_catalog.pg_index i "
 | 
								 "LEFT OUTER JOIN pg_catalog.pg_index i "
 | 
				
			||||||
			 "	   ON c.oid = i.indexrelid "
 | 
								 "	   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
 | 
						 * 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) "
 | 
								 "	  c.oid >= %u) "
 | 
				
			||||||
			 "  OR (n.nspname = 'pg_catalog' AND "
 | 
								 "  OR (n.nspname = 'pg_catalog' AND "
 | 
				
			||||||
	"    relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) ));",
 | 
						"    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,
 | 
								 FirstNormalObjectId,
 | 
				
			||||||
	/* does pg_largeobject_metadata need to be migrated? */
 | 
						/* does pg_largeobject_metadata need to be migrated? */
 | 
				
			||||||
			 (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
 | 
								 (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,6 @@ char	   *output_files[] = {
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char **argv)
 | 
					main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	   *sequence_script_file_name = NULL;
 | 
					 | 
				
			||||||
	char	   *analyze_script_file_name = NULL;
 | 
						char	   *analyze_script_file_name = NULL;
 | 
				
			||||||
	char	   *deletion_script_file_name = NULL;
 | 
						char	   *deletion_script_file_name = NULL;
 | 
				
			||||||
	bool		live_check = false;
 | 
						bool		live_check = false;
 | 
				
			||||||
@@ -90,7 +89,7 @@ main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	check_cluster_compatibility(live_check);
 | 
						check_cluster_compatibility(live_check);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	check_and_dump_old_cluster(live_check, &sequence_script_file_name);
 | 
						check_and_dump_old_cluster(live_check);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* -- NEW -- */
 | 
						/* -- NEW -- */
 | 
				
			||||||
@@ -157,7 +156,7 @@ main(int argc, char **argv)
 | 
				
			|||||||
	create_script_for_cluster_analyze(&analyze_script_file_name);
 | 
						create_script_for_cluster_analyze(&analyze_script_file_name);
 | 
				
			||||||
	create_script_for_old_cluster_deletion(&deletion_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, "\nUpgrade Complete\n");
 | 
				
			||||||
	pg_log(PG_REPORT, "----------------\n");
 | 
						pg_log(PG_REPORT, "----------------\n");
 | 
				
			||||||
@@ -167,7 +166,6 @@ main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pg_free(analyze_script_file_name);
 | 
						pg_free(analyze_script_file_name);
 | 
				
			||||||
	pg_free(deletion_script_file_name);
 | 
						pg_free(deletion_script_file_name);
 | 
				
			||||||
	pg_free(sequence_script_file_name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cleanup();
 | 
						cleanup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -313,11 +313,10 @@ extern OSInfo os_info;
 | 
				
			|||||||
/* check.c */
 | 
					/* check.c */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void		output_check_banner(bool live_check);
 | 
					void		output_check_banner(bool live_check);
 | 
				
			||||||
void check_and_dump_old_cluster(bool live_check,
 | 
					void check_and_dump_old_cluster(bool live_check);
 | 
				
			||||||
						   char **sequence_script_file_name);
 | 
					 | 
				
			||||||
void		check_new_cluster(void);
 | 
					void		check_new_cluster(void);
 | 
				
			||||||
void		report_clusters_compatible(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,
 | 
					void output_completion_banner(char *analyze_script_file_name,
 | 
				
			||||||
						 char *deletion_script_file_name);
 | 
											 char *deletion_script_file_name);
 | 
				
			||||||
void		check_cluster_versions(void);
 | 
					void		check_cluster_versions(void);
 | 
				
			||||||
@@ -471,17 +470,6 @@ void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
 | 
				
			|||||||
										 bool check_mode);
 | 
															 bool check_mode);
 | 
				
			||||||
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
 | 
					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 */
 | 
					/* parallel.c */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
parallel_exec_prog(const char *log_file, const char *opt_log_file,
 | 
					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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user