Bruce Momjian wrote:
> Andrew Dunstan wrote:
> > 
> > 
> > Bruce Momjian wrote:
> > > Do we have no composite types in the regression tests, or do we not
> > > store any in the database?  Same the enums.
> > >
> > >   
> > 
> > Looks like the enum regression tests at least drop all their tables :-(
> > 
> > > To allow pg_migrator to work, I would need to reserve the oids in
> > > pg_type, import the dump, and renumber the pg_type entries (and
> > > everything pointing to them) to the proper pg_type.oid.  The big problem
> > > there is that I don't have access at the SQL level to set or change
> > > oids. I am afraid the oid remumbering is something we would have to do
> > > in the backend by walking through the pg_depend entries for the pg_type
> > > row.  Yuck.
> > 
> > Yeah. Maybe we need some special way of setting the oids explicitly. But 
> > preventing a clash might be fairly difficult.
> > 
> > Excluding every database that has a composite/array-of 
> > user-defined-type/enum type would be pretty nasty. After all, these are 
> > features we boast of.
> 
> Well, pg_migrator has gotten pretty far without supporting these
> features, and I think I would have heard about it if someone had these
> and migrated because vacuum analyze found it right away.  I am afraid
> the best we can do is to throw an error when we see these cases and hope
> we can improve things for 8.5.
> 
> As I understand it I have to look for the _use_ of these in user tables,
> not the existance of them in pg_type ---  for example, there is
> certainly an array for every user type, but it might not be used by any
> user tables, and that would be OK.

I have applied the attached patch to pg_migrator to detect enum,
composites, and arrays.  I tested it and the only error I got was with
the breakmigrator table that was supplied by Jeff, and once I removed
that table the migration went fine, meaning there are no cases of these
stored in the regression test database.

I will release a new version of pg_migrator with these new detection
routines.

-- 
  Bruce Momjian  <br...@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
? tools
? log
? src/pg_migrator
Index: src/pg_migrator.c
===================================================================
RCS file: /cvsroot/pg-migrator/pg_migrator/src/pg_migrator.c,v
retrieving revision 1.63
diff -c -r1.63 pg_migrator.c
*** src/pg_migrator.c	3 Aug 2009 01:40:09 -0000	1.63
--- src/pg_migrator.c	6 Aug 2009 03:25:40 -0000
***************
*** 74,79 ****
--- 74,82 ----
  	{
  		v8_3_check_for_name_data_type_usage(&ctx, CLUSTER_OLD);
  		v8_3_check_for_tsquery_usage(&ctx, CLUSTER_OLD);
+ 		v8_3_check_for_composite_types(&ctx, CLUSTER_OLD);
+ 		v8_3_check_for_array_types(&ctx, CLUSTER_OLD);
+ 		v8_3_check_for_enum_types(&ctx, CLUSTER_OLD);
  		if (ctx.check)
  		{
  			v8_3_rebuild_tsvector_tables(&ctx, true, CLUSTER_OLD);
Index: src/pg_migrator.h
===================================================================
RCS file: /cvsroot/pg-migrator/pg_migrator/src/pg_migrator.h,v
retrieving revision 1.67
diff -c -r1.67 pg_migrator.h
*** src/pg_migrator.h	2 Aug 2009 03:59:06 -0000	1.67
--- src/pg_migrator.h	6 Aug 2009 03:25:40 -0000
***************
*** 389,394 ****
--- 389,400 ----
  							Cluster whichCluster);
  void		v8_3_check_for_tsquery_usage(migratorContext *ctx,
  							Cluster whichCluster);
+ void		v8_3_check_for_composite_types(migratorContext *ctx,
+ 							Cluster whichCluster);
+ void		v8_3_check_for_array_types(migratorContext *ctx,
+ 							Cluster whichCluster);
+ void		v8_3_check_for_enum_types(migratorContext *ctx,
+ 							Cluster whichCluster);
  void		v8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx,
  							Cluster whichCluster);
  void		v8_3_rebuild_tsvector_tables(migratorContext *ctx,
Index: src/relfilenode.c
===================================================================
RCS file: /cvsroot/pg-migrator/pg_migrator/src/relfilenode.c,v
retrieving revision 1.29
diff -c -r1.29 relfilenode.c
*** src/relfilenode.c	3 Aug 2009 01:40:09 -0000	1.29
--- src/relfilenode.c	6 Aug 2009 03:25:40 -0000
***************
*** 232,238 ****
  	PGresult   *res;
  	int			i_relfile;
  
! 	prep_status(&ctx, "Getting pg_database and pg_largeobject relfilenodes");
  
  	res = executeQueryOrDie(ctx, conn,
  							"SELECT c.relname, c.relfilenode "
--- 232,238 ----
  	PGresult   *res;
  	int			i_relfile;
  
! 	prep_status(ctx, "Getting pg_database and pg_largeobject relfilenodes");
  
  	res = executeQueryOrDie(ctx, conn,
  							"SELECT c.relname, c.relfilenode "
Index: src/version.c
===================================================================
RCS file: /cvsroot/pg-migrator/pg_migrator/src/version.c,v
retrieving revision 1.26
diff -c -r1.26 version.c
*** src/version.c	21 Jul 2009 17:36:23 -0000	1.26
--- src/version.c	6 Aug 2009 03:25:40 -0000
***************
*** 188,193 ****
--- 188,467 ----
  
  
  /*
+  * v8_3_check_for_composite_types()
+  *
+  *	composite types have pg_type oids in their data values and
+  *  pg_type.oid is not preserved between migrations.  We don't
+  *	have to worry about arrays of composite types because we
+  *	check arrays later
+  */
+ void
+ v8_3_check_for_composite_types(migratorContext *ctx, Cluster whichCluster)
+ {
+ 	ClusterInfo	*active_cluster = (whichCluster == CLUSTER_OLD) ?
+ 					&ctx->old : &ctx->new;
+ 	int			dbnum;
+ 	FILE		*script = NULL;
+ 	bool		found = false;
+ 	char		output_path[MAXPGPATH];
+ 
+ 	prep_status(ctx, "Checking for user columns of composite types");
+ 
+ 	snprintf(output_path, sizeof(output_path), "%s/tables_using_composite_types.txt",
+ 			ctx->home_dir);
+ 	
+ 	for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ 	{
+ 		PGresult   *res;
+  		bool		db_used = false;
+ 		int			ntups;
+ 		int			rowno;
+ 		int			i_nspname, i_relname, i_attname;
+ 		DbInfo	   *active_db = &active_cluster->dbarr.dbs[dbnum];
+ 		PGconn	   *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ 		
+ 		/* Find any user-defined tsquery columns */
+ 		res = executeQueryOrDie(ctx, conn,
+ 								"SELECT n.nspname, c.relname, a.attname "
+ 								"FROM	pg_catalog.pg_class c, "
+ 								"		pg_catalog.pg_namespace n, "
+ 								"		pg_catalog.pg_attribute a, "
+ 								"		pg_catalog.pg_type t "
+ 								"WHERE	c.relkind = 'r' AND "
+ 								"		c.oid = a.attrelid AND "
+ 								"		NOT a.attisdropped AND "
+ 								"		a.atttypid = t.oid AND "
+ 								"		c.relnamespace = n.oid AND "
+ 								"		t.typtype = 'c' AND "
+ 								"		n.nspname != 'pg_catalog' 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 (script == NULL && (script = fopen(output_path, "w")) == NULL)
+ 					pg_log(ctx, PG_FATAL, "Could not create necessary file:  %s\n", output_path);
+ 			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 (found)
+ 	{
+ 		fclose(script);
+ 		pg_log(ctx, PG_REPORT, "fatal\n");
+ 		pg_log(ctx, PG_FATAL,
+ 				"| Your installation uses composite types.\n"
+ 				"| These types are not supported for upgrade because\n"
+ 				"| they contain an internal pg_type.oid that cannot be\n"
+ 				"| migrated.  You can remove the problem columns and\n"
+ 				"| restart the migration.  A list of the problem columns\n"
+ 				"| is in the file:\n"
+ 				"| \t%s\n\n", output_path);
+ 	}
+ 	else
+ 		check_ok(ctx);
+ }
+ 
+ 
+ /*
+  * v8_3_check_for_array_types()
+  *
+  *	array types have pg_type oids in their data values and
+  *  pg_type.oid is not preserved between migrations.  We catch
+  *	arrays of composite types here too.
+  */
+ void
+ v8_3_check_for_array_types(migratorContext *ctx, Cluster whichCluster)
+ {
+ 	ClusterInfo	*active_cluster = (whichCluster == CLUSTER_OLD) ?
+ 					&ctx->old : &ctx->new;
+ 	int			dbnum;
+ 	FILE		*script = NULL;
+ 	bool		found = false;
+ 	char		output_path[MAXPGPATH];
+ 
+ 	prep_status(ctx, "Checking for user columns of array types");
+ 
+ 	snprintf(output_path, sizeof(output_path), "%s/tables_using_array_types.txt",
+ 			ctx->home_dir);
+ 	
+ 	for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ 	{
+ 		PGresult   *res;
+  		bool		db_used = false;
+ 		int			ntups;
+ 		int			rowno;
+ 		int			i_nspname, i_relname, i_attname;
+ 		DbInfo	   *active_db = &active_cluster->dbarr.dbs[dbnum];
+ 		PGconn	   *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ 		
+ 		/* Find any user-defined tsquery columns */
+ 		res = executeQueryOrDie(ctx, conn,
+ 								"SELECT n.nspname, c.relname, a.attname "
+ 								"FROM	pg_catalog.pg_class c, "
+ 								"		pg_catalog.pg_namespace n, "
+ 								"		pg_catalog.pg_attribute a, "
+ 								"		pg_catalog.pg_type t "
+ 								"WHERE	c.relkind = 'r' AND "
+ 								"		c.oid = a.attrelid AND "
+ 								"		NOT a.attisdropped AND "
+ 								"		a.atttypid = t.oid AND "
+ 								"		c.relnamespace = n.oid AND "
+ 								"		t.typtype = 'b' AND "
+ 								"		t.typtype = 'A' AND "
+ 								"		n.nspname != 'pg_catalog' 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 (script == NULL && (script = fopen(output_path, "w")) == NULL)
+ 					pg_log(ctx, PG_FATAL, "Could not create necessary file:  %s\n", output_path);
+ 			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 (found)
+ 	{
+ 		fclose(script);
+ 		pg_log(ctx, PG_REPORT, "fatal\n");
+ 		pg_log(ctx, PG_FATAL,
+ 				"| Your installation uses array types.\n"
+ 				"| These types are not supported for upgrade because\n"
+ 				"| they contain an internal pg_type.oid that cannot be\n"
+ 				"| migrated.  You can remove the problem columns and\n"
+ 				"| restart the migration.  A list of the problem columns\n"
+ 				"| is in the file:\n"
+ 				"| \t%s\n\n", output_path);
+ 	}
+ 	else
+ 		check_ok(ctx);
+ }
+ 
+ 
+ /*
+  * v8_3_check_for_enum_types()
+  *
+  *	enum types have pg_type oids in their data values and
+  *  pg_type.oid is not preserved between migrations.
+  */
+ void
+ v8_3_check_for_enum_types(migratorContext *ctx, Cluster whichCluster)
+ {
+ 	ClusterInfo	*active_cluster = (whichCluster == CLUSTER_OLD) ?
+ 					&ctx->old : &ctx->new;
+ 	int			dbnum;
+ 	FILE		*script = NULL;
+ 	bool		found = false;
+ 	char		output_path[MAXPGPATH];
+ 
+ 	prep_status(ctx, "Checking for user columns of enum types");
+ 
+ 	snprintf(output_path, sizeof(output_path), "%s/tables_using_enum_types.txt",
+ 			ctx->home_dir);
+ 	
+ 	for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ 	{
+ 		PGresult   *res;
+  		bool		db_used = false;
+ 		int			ntups;
+ 		int			rowno;
+ 		int			i_nspname, i_relname, i_attname;
+ 		DbInfo	   *active_db = &active_cluster->dbarr.dbs[dbnum];
+ 		PGconn	   *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ 		
+ 		/* Find any user-defined tsquery columns */
+ 		res = executeQueryOrDie(ctx, conn,
+ 								"SELECT n.nspname, c.relname, a.attname "
+ 								"FROM	pg_catalog.pg_class c, "
+ 								"		pg_catalog.pg_namespace n, "
+ 								"		pg_catalog.pg_attribute a, "
+ 								"		pg_catalog.pg_type t "
+ 								"WHERE	c.relkind = 'r' AND "
+ 								"		c.oid = a.attrelid AND "
+ 								"		NOT a.attisdropped AND "
+ 								"		a.atttypid = t.oid AND "
+ 								"		c.relnamespace = n.oid AND "
+ 								"		t.typtype = 'e' AND "
+ 								"		n.nspname != 'pg_catalog' 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 (script == NULL && (script = fopen(output_path, "w")) == NULL)
+ 					pg_log(ctx, PG_FATAL, "Could not create necessary file:  %s\n", output_path);
+ 			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 (found)
+ 	{
+ 		fclose(script);
+ 		pg_log(ctx, PG_REPORT, "fatal\n");
+ 		pg_log(ctx, PG_FATAL,
+ 				"| Your installation uses enum types.\n"
+ 				"| These types are not supported for upgrade because\n"
+ 				"| they contain an internal pg_type.oid that cannot be\n"
+ 				"| migrated.  You can remove the problem columns and\n"
+ 				"| restart the migration.  A list of the problem columns\n"
+ 				"| is in the file:\n"
+ 				"| \t%s\n\n", output_path);
+ 	}
+ 	else
+ 		check_ok(ctx);
+ }
+ 
+ 
+ /*
   * v8_3_check_for_isn_and_int8_passing_mismatch()
   *
   *	/contrib/isn relies on data type bigint, and the CREATE TYPE
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to