Index: src/backend/catalog/pg_enum.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_enum.c,v
retrieving revision 1.11
diff -c -c -r1.11 pg_enum.c
*** src/backend/catalog/pg_enum.c	24 Dec 2009 22:17:58 -0000	1.11
--- src/backend/catalog/pg_enum.c	26 Dec 2009 18:48:55 -0000
***************
*** 33,39 ****
   * vals is a list of Value strings.
   */
  void
! EnumValuesCreate(Oid enumTypeOid, List *vals)
  {
  	Relation	pg_enum;
  	TupleDesc	tupDesc;
--- 33,40 ----
   * vals is a list of Value strings.
   */
  void
! EnumValuesCreate(Oid enumTypeOid, List *vals,
! 				 Oid binary_upgrade_next_pg_enum_oid)
  {
  	Relation	pg_enum;
  	TupleDesc	tupDesc;
***************
*** 58,82 ****
  	tupDesc = pg_enum->rd_att;
  
  	/*
! 	 * Allocate oids.  While this method does not absolutely guarantee that we
! 	 * generate no duplicate oids (since we haven't entered each oid into the
! 	 * table before allocating the next), trouble could only occur if the oid
! 	 * counter wraps all the way around before we finish. Which seems
! 	 * unlikely.
  	 */
  	oids = (Oid *) palloc(num_elems * sizeof(Oid));
! 	for (elemno = 0; elemno < num_elems; elemno++)
  	{
  		/*
! 		 *	The pg_enum.oid is stored in user tables.  This oid must be
! 		 *	preserved by binary upgrades.
  		 */
! 		oids[elemno] = GetNewOid(pg_enum);
  	}
  
- 	/* sort them, just in case counter wrapped from high to low */
- 	qsort(oids, num_elems, sizeof(Oid), oid_cmp);
- 
  	/* and make the entries */
  	memset(nulls, false, sizeof(nulls));
  
--- 59,97 ----
  	tupDesc = pg_enum->rd_att;
  
  	/*
! 	 *	Allocate oids
  	 */
  	oids = (Oid *) palloc(num_elems * sizeof(Oid));
! 	if (OidIsValid(binary_upgrade_next_pg_enum_oid))
! 	{
! 			if (num_elems != 1)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 						 errmsg("EnumValuesCreate() can only set a single OID")));
! 			oids[0] = binary_upgrade_next_pg_enum_oid;
! 			binary_upgrade_next_pg_enum_oid = InvalidOid;
! 	}	
! 	else
  	{
  		/*
! 		 * While this method does not absolutely guarantee that we generate
! 		 * no duplicate oids (since we haven't entered each oid into the
! 		 * table before allocating the next), trouble could only occur if
! 		 * the oid counter wraps all the way around before we finish. Which
! 		 * seems unlikely.
  		 */
! 		for (elemno = 0; elemno < num_elems; elemno++)
! 		{
! 			/*
! 			 *	The pg_enum.oid is stored in user tables.  This oid must be
! 			 *	preserved by binary upgrades.
! 			 */
! 			oids[elemno] = GetNewOid(pg_enum);
! 		}
! 		/* sort them, just in case counter wrapped from high to low */
! 		qsort(oids, num_elems, sizeof(Oid), oid_cmp);
  	}
  
  	/* and make the entries */
  	memset(nulls, false, sizeof(nulls));
  
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.141
diff -c -c -r1.141 typecmds.c
*** src/backend/commands/typecmds.c	24 Dec 2009 22:09:23 -0000	1.141
--- src/backend/commands/typecmds.c	26 Dec 2009 18:48:56 -0000
***************
*** 1161,1167 ****
  				   false);		/* Type NOT NULL */
  
  	/* Enter the enum's values into pg_enum */
! 	EnumValuesCreate(enumTypeOid, stmt->vals);
  
  	/*
  	 * Create the array type that goes with it.
--- 1161,1167 ----
  				   false);		/* Type NOT NULL */
  
  	/* Enter the enum's values into pg_enum */
! 	EnumValuesCreate(enumTypeOid, stmt->vals, InvalidOid);
  
  	/*
  	 * Create the array type that goes with it.
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.562
diff -c -c -r1.562 pg_dump.c
*** src/bin/pg_dump/pg_dump.c	26 Dec 2009 16:55:21 -0000	1.562
--- src/bin/pg_dump/pg_dump.c	26 Dec 2009 18:48:57 -0000
***************
*** 6528,6539 ****
  	PGresult   *res;
  	int			num,
  				i;
  	char	   *label;
  
  	/* Set proper schema search path so regproc references list correctly */
  	selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
  
! 	appendPQExpBuffer(query, "SELECT enumlabel FROM pg_catalog.pg_enum "
  					  "WHERE enumtypid = '%u'"
  					  "ORDER BY oid",
  					  tyinfo->dobj.catId.oid);
--- 6528,6541 ----
  	PGresult   *res;
  	int			num,
  				i;
+ 	Oid			enum_oid;
  	char	   *label;
  
  	/* Set proper schema search path so regproc references list correctly */
  	selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
  
! 	appendPQExpBuffer(query, "SELECT oid, enumlabel "
! 					  "FROM pg_catalog.pg_enum "
  					  "WHERE enumtypid = '%u'"
  					  "ORDER BY oid",
  					  tyinfo->dobj.catId.oid);
***************
*** 6556,6573 ****
  	if (binary_upgrade)
  		binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
  
! 	appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (\n",
  					  fmtId(tyinfo->dobj.name));
! 	for (i = 0; i < num; i++)
  	{
! 		label = PQgetvalue(res, i, 0);
! 		if (i > 0)
! 			appendPQExpBuffer(q, ",\n");
! 		appendPQExpBuffer(q, "    ");
! 		appendStringLiteralAH(q, label, fout);
  	}
  	appendPQExpBuffer(q, "\n);\n");
  
  	ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
  				 tyinfo->dobj.name,
  				 tyinfo->dobj.namespace->dobj.name,
--- 6558,6601 ----
  	if (binary_upgrade)
  		binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
  
! 	appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
  					  fmtId(tyinfo->dobj.name));
! 
! 	if (!binary_upgrade)
  	{
! 		/* Labels with server-assigned oids */
! 		for (i = 0; i < num; i++)
! 		{
! 			label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
! 			if (i > 0)
! 				appendPQExpBuffer(q, ",");
! 			appendPQExpBuffer(q, "\n    ");
! 			appendStringLiteralAH(q, label, fout);
! 		}
  	}
+ 
  	appendPQExpBuffer(q, "\n);\n");
  
+ 	if (binary_upgrade)
+ 	{
+ 		/* Labels with dump-assigned (preserved) oids */
+ 		for (i = 0; i < num; i++)
+ 		{
+ 			enum_oid = atooid(PQgetvalue(res, i, PQfnumber(res, "oid")));
+ 			label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
+ 
+ 			if (i == 0)
+ 				appendPQExpBuffer(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
+ 			appendPQExpBuffer(q,
+ 				"SELECT binary_upgrade.add_pg_enum_label('%u'::pg_catalog.oid, "
+ 				"'%u'::pg_catalog.oid, ",
+ 				enum_oid, tyinfo->dobj.catId.oid);
+ 			appendStringLiteralAH(q, label, fout);
+ 			appendPQExpBuffer(q, ");\n");
+ 		}
+ 		appendPQExpBuffer(q, "\n");
+ 	}
+ 
  	ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
  				 tyinfo->dobj.name,
  				 tyinfo->dobj.namespace->dobj.name,
Index: src/include/catalog/pg_enum.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_enum.h,v
retrieving revision 1.5
diff -c -c -r1.5 pg_enum.h
*** src/include/catalog/pg_enum.h	1 Jan 2009 17:23:57 -0000	1.5
--- src/include/catalog/pg_enum.h	26 Dec 2009 18:49:00 -0000
***************
*** 60,66 ****
  /*
   * prototypes for functions in pg_enum.c
   */
! extern void EnumValuesCreate(Oid enumTypeOid, List *vals);
  extern void EnumValuesDelete(Oid enumTypeOid);
  
  #endif   /* PG_ENUM_H */
--- 60,67 ----
  /*
   * prototypes for functions in pg_enum.c
   */
! extern void EnumValuesCreate(Oid enumTypeOid, List *vals,
! 			Oid binary_upgrade_next_pg_enum_oid);
  extern void EnumValuesDelete(Oid enumTypeOid);
  
  #endif   /* PG_ENUM_H */
