diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index 9a3d533c146aea26b7b76c60a5d03d065067e379..689ecd4830d99e8e08281dc76cc129d0a9c8f119 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_enum.c,v 1.11 2009/12/24 22:17:58 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_enum.c,v 1.12 2009/12/27 14:50:41 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,7 +33,8 @@ static int	oid_cmp(const void *p1, const void *p2);
  * vals is a list of Value strings.
  */
 void
-EnumValuesCreate(Oid enumTypeOid, List *vals)
+EnumValuesCreate(Oid enumTypeOid, List *vals,
+				 Oid binary_upgrade_next_pg_enum_oid)
 {
 	Relation	pg_enum;
 	TupleDesc	tupDesc;
@@ -58,25 +59,39 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	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.
+	 *	Allocate oids
 	 */
 	oids = (Oid *) palloc(num_elems * sizeof(Oid));
-	for (elemno = 0; elemno < num_elems; elemno++)
+	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
 	{
 		/*
-		 *	The pg_enum.oid is stored in user tables.  This oid must be
-		 *	preserved by binary upgrades.
+		 * 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[elemno] = GetNewOid(pg_enum);
+		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);
 	}
 
-	/* 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));
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 11990c0e106f7603fd8e9da22d4534f5b0aec6f6..a815752ecbbbecdbadee2aa8c15d737b0d7ec44c 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.141 2009/12/24 22:09:23 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.142 2009/12/27 14:50:43 momjian Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -1161,7 +1161,7 @@ DefineEnum(CreateEnumStmt *stmt)
 				   false);		/* Type NOT NULL */
 
 	/* Enter the enum's values into pg_enum */
-	EnumValuesCreate(enumTypeOid, stmt->vals);
+	EnumValuesCreate(enumTypeOid, stmt->vals, InvalidOid);
 
 	/*
 	 * Create the array type that goes with it.
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 037c7045e50940384da13fcac47c13de159e38b6..16a912e19adf1152bc0486eea4a2d46c6050d414 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.562 2009/12/26 16:55:21 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.563 2009/12/27 14:50:44 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -6528,12 +6528,14 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 	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 enumlabel FROM pg_catalog.pg_enum "
+	appendPQExpBuffer(query, "SELECT oid, enumlabel "
+					  "FROM pg_catalog.pg_enum "
 					  "WHERE enumtypid = '%u'"
 					  "ORDER BY oid",
 					  tyinfo->dobj.catId.oid);
@@ -6556,18 +6558,44 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 	if (binary_upgrade)
 		binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
 
-	appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (\n",
+	appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
 					  fmtId(tyinfo->dobj.name));
-	for (i = 0; i < num; i++)
+
+	if (!binary_upgrade)
 	{
-		label = PQgetvalue(res, i, 0);
-		if (i > 0)
-			appendPQExpBuffer(q, ",\n");
-		appendPQExpBuffer(q, "    ");
-		appendStringLiteralAH(q, label, fout);
+		/* 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,
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index dde12c28673b1ffc124c3ae70b504b6a29f5735d..6ac2c6713d8bc6abf52fee17b8fca923f4853a62 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.560 2009/12/19 04:08:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.561 2009/12/27 14:50:46 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200912181
+#define CATALOG_VERSION_NO	200912271
 
 #endif
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index c26e891f2fb6d6cba6970926bdeedf296a4e479e..cea056ae4c29bb9316d190564391923399bd792e 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 2006-2009, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_enum.h,v 1.5 2009/01/01 17:23:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_enum.h,v 1.6 2009/12/27 14:50:46 momjian Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -60,7 +60,8 @@ typedef FormData_pg_enum *Form_pg_enum;
 /*
  * prototypes for functions in pg_enum.c
  */
-extern void EnumValuesCreate(Oid enumTypeOid, List *vals);
+extern void EnumValuesCreate(Oid enumTypeOid, List *vals,
+			Oid binary_upgrade_next_pg_enum_oid);
 extern void EnumValuesDelete(Oid enumTypeOid);
 
 #endif   /* PG_ENUM_H */