patchenum2

text/plain

Filename: patchenum2
Type: text/plain
Part: 0
Message: Re: WIP: extensible enums
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index d9b54b8..9b3c64c 100644
--- a/contrib/pg_upgrade/function.c
+++ b/contrib/pg_upgrade/function.c
@@ -58,25 +58,25 @@ install_support_functions(migratorContext *ctx)
 								  "LANGUAGE C STRICT;"));
 		PQclear(executeQueryOrDie(ctx, conn,
 								  "CREATE OR REPLACE FUNCTION "
-				"		binary_upgrade.set_next_heap_relfilenode(OID) "
+					 "		binary_upgrade.set_next_pg_enum_oid(OID) "
 								  "RETURNS VOID "
 								  "AS '$libdir/pg_upgrade_support' "
 								  "LANGUAGE C STRICT;"));
 		PQclear(executeQueryOrDie(ctx, conn,
 								  "CREATE OR REPLACE FUNCTION "
-			   "		binary_upgrade.set_next_toast_relfilenode(OID) "
+				"		binary_upgrade.set_next_heap_relfilenode(OID) "
 								  "RETURNS VOID "
 								  "AS '$libdir/pg_upgrade_support' "
 								  "LANGUAGE C STRICT;"));
 		PQclear(executeQueryOrDie(ctx, conn,
 								  "CREATE OR REPLACE FUNCTION "
-			   "		binary_upgrade.set_next_index_relfilenode(OID) "
+			   "		binary_upgrade.set_next_toast_relfilenode(OID) "
 								  "RETURNS VOID "
 								  "AS '$libdir/pg_upgrade_support' "
 								  "LANGUAGE C STRICT;"));
 		PQclear(executeQueryOrDie(ctx, conn,
 								  "CREATE OR REPLACE FUNCTION "
-			 "		binary_upgrade.add_pg_enum_label(OID, OID, NAME) "
+			   "		binary_upgrade.set_next_index_relfilenode(OID) "
 								  "RETURNS VOID "
 								  "AS '$libdir/pg_upgrade_support' "
 								  "LANGUAGE C STRICT;"));
diff --git a/contrib/pg_upgrade_support/pg_upgrade_support.c b/contrib/pg_upgrade_support/pg_upgrade_support.c
index 50f9efd..7af7d4d 100644
--- a/contrib/pg_upgrade_support/pg_upgrade_support.c
+++ b/contrib/pg_upgrade_support/pg_upgrade_support.c
@@ -27,6 +27,7 @@ PG_MODULE_MAGIC;
 extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid;
 extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_array_oid;
 extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_toast_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid;
 extern PGDLLIMPORT Oid binary_upgrade_next_heap_relfilenode;
 extern PGDLLIMPORT Oid binary_upgrade_next_toast_relfilenode;
 extern PGDLLIMPORT Oid binary_upgrade_next_index_relfilenode;
@@ -34,18 +35,18 @@ extern PGDLLIMPORT Oid binary_upgrade_next_index_relfilenode;
 Datum set_next_pg_type_oid(PG_FUNCTION_ARGS);
 Datum set_next_pg_type_array_oid(PG_FUNCTION_ARGS);
 Datum set_next_pg_type_toast_oid(PG_FUNCTION_ARGS);
+Datum set_next_pg_enum_oid(PG_FUNCTION_ARGS);
 Datum set_next_heap_relfilenode(PG_FUNCTION_ARGS);
 Datum set_next_toast_relfilenode(PG_FUNCTION_ARGS);
 Datum set_next_index_relfilenode(PG_FUNCTION_ARGS);
-Datum add_pg_enum_label(PG_FUNCTION_ARGS);
 
 PG_FUNCTION_INFO_V1(set_next_pg_type_oid);
 PG_FUNCTION_INFO_V1(set_next_pg_type_array_oid);
 PG_FUNCTION_INFO_V1(set_next_pg_type_toast_oid);
+PG_FUNCTION_INFO_V1(set_next_pg_enum_oid);
 PG_FUNCTION_INFO_V1(set_next_heap_relfilenode);
 PG_FUNCTION_INFO_V1(set_next_toast_relfilenode);
 PG_FUNCTION_INFO_V1(set_next_index_relfilenode);
-PG_FUNCTION_INFO_V1(add_pg_enum_label);
 
 Datum
 set_next_pg_type_oid(PG_FUNCTION_ARGS)
@@ -78,6 +79,16 @@ set_next_pg_type_toast_oid(PG_FUNCTION_ARGS)
 }
 
 Datum
+set_next_pg_enum_oid(PG_FUNCTION_ARGS)
+{
+	Oid			enumoid = PG_GETARG_OID(0);
+
+	binary_upgrade_next_pg_enum_oid = enumoid;
+
+	PG_RETURN_VOID();
+}
+
+Datum
 set_next_heap_relfilenode(PG_FUNCTION_ARGS)
 {
 	Oid			relfilenode = PG_GETARG_OID(0);
@@ -106,17 +117,3 @@ set_next_index_relfilenode(PG_FUNCTION_ARGS)
 
 	PG_RETURN_VOID();
 }
-
-Datum
-add_pg_enum_label(PG_FUNCTION_ARGS)
-{
-	Oid			enumoid = PG_GETARG_OID(0);
-	Oid			typoid = PG_GETARG_OID(1);
-	Name        label = PG_GETARG_NAME(2);
-	
-	EnumValuesCreate(typoid, list_make1(makeString(NameStr(*label))),
-					 enumoid);
-
-	PG_RETURN_VOID();
-}
-
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index a1d951a..3ef4e2d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -854,7 +854,9 @@ AddNewRelationType(const char *typeName,
 				   'x',			/* fully TOASTable */
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
-				   false);		/* Type NOT NULL */
+				   false,		/* Type NOT NULL */
+				   -1,          /* no enum labels */
+				   false);      /* type is not an enum, so not sorted */
 }
 
 /* --------------------------------
@@ -1086,7 +1088,9 @@ heap_create_with_catalog(const char *relname,
 				   'x',			/* fully TOASTable */
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
-				   false);		/* Type NOT NULL */
+				   false,		/* Type NOT NULL */
+				   -1,          /* no enum labels */
+				   false);      /* type is not an enum, so not sorted */
 
 		pfree(relarrayname);
 	}
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index 578f8c5..d104d77 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -18,12 +18,202 @@
 #include "catalog/catalog.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_enum.h"
+#include "catalog/pg_type.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
 static int	oid_cmp(const void *p1, const void *p2);
+static int	sort_order_cmp(const void *p1, const void *p2);
+
+Oid      binary_upgrade_next_pg_enum_oid = InvalidOid;
+
+/*
+ * AddEnumLabel
+ *     Add a new label to the enum set. By default it goes at
+ *     the end, but the user can choose to place it before or
+ *     after any existing set member.
+ *
+ * Returns true iff the labels are sorted by oid after the addition.
+ */
+
+bool
+AddEnumLabel(Oid enumTypeOid, 
+			 char *newVal, 
+			 char *neighbour, 
+			 bool newValIsAfter,
+			 int  nelems,
+			 bool elems_are_sorted)
+{
+	Oid        newOid;
+	Relation   pg_enum;
+	TupleDesc	tupDesc;
+	Datum		values[Natts_pg_enum];
+	bool		nulls[Natts_pg_enum];
+	NameData	enumlabel;
+	HeapTuple   enum_tup;
+	bool        result = elems_are_sorted;
+	int         newelemorder;
+
+	/* check length of new label is ok */
+	if (strlen(newVal) > (NAMEDATALEN - 1))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_NAME),
+				 errmsg("invalid enum label \"%s\"", newVal),
+				 errdetail("Labels must be %d characters or less.",
+						   NAMEDATALEN - 1)));
+
+	/* get a new OID for the label */
+	pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
+
+	if (OidIsValid(binary_upgrade_next_pg_enum_oid))
+	{
+		if (neighbour != NULL)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("BEFORE/AFTER incompatible with binary upgrade.")));
+
+		newOid = binary_upgrade_next_pg_enum_oid;
+		binary_upgrade_next_pg_enum_oid = InvalidOid;
+	}
+	else
+	{
+		/* non upgrade case */
+		newOid = GetNewOid(pg_enum);
+	}
+
+	if (neighbour == NULL)
+	{
+		/* 
+		 * Put the new label at the end of the list.
+		 * No change to existing tuples is required.
+		 */
+		newelemorder = nelems + 1;
+		/* are the elements still sorted? */
+		if (elems_are_sorted)
+		{	
+			CatCList   *list;
+			int			i;
+			bool        still_sorted = true;
+
+			list = SearchSysCacheList1(ENUMTYPOIDNAME, 
+									   ObjectIdGetDatum(enumTypeOid));
+			for (i = 0; i < nelems; i++)
+			{
+				HeapTuple tup = &(list->members[i]->tuple);
+				Form_pg_enum en = (Form_pg_enum) GETSTRUCT(tup);
+
+				if (en->enumsortorder == nelems)
+				{
+					if (HeapTupleGetOid(tup) > newOid)
+						still_sorted = false;
+					break;
+				}
+			}
+			ReleaseCatCacheList(list);
+			if (! still_sorted)
+				result = false;
+		}
+	}
+	else 
+	{
+		/* BEFORE or AFTER specified */
+		CatCList   *list;
+		int			i;
+		HeapTuple    *existing;
+		HeapTuple     nbr = NULL;
+		Form_pg_enum nbr_en;
+
+		/* get a list of the existing elements and sort them by enumsortorder */
+		list = SearchSysCacheList1(ENUMTYPOIDNAME, 
+								   ObjectIdGetDatum(enumTypeOid));
+		existing = palloc(nelems * sizeof(HeapTuple));
+
+		for (i = 0; i < nelems; i++)
+			existing[i] = &(list->members[i]->tuple);
+
+		qsort(existing, nelems, sizeof(HeapTuple), sort_order_cmp);
+		
+		/* locate the neighbour element */
+		for (i = 0; i < nelems; i++)
+		{
+			Form_pg_enum exists_en;
+			exists_en = (Form_pg_enum) GETSTRUCT(existing[i]);
+			if (strcmp(NameStr(exists_en->enumlabel),neighbour) == 0)
+				nbr = existing[i];
+
+		}
+
+		if (nbr == NULL)
+		{
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("\"%s\" is not an existing label.", neighbour)));
+		}
+
+		nbr_en = (Form_pg_enum) GETSTRUCT(nbr);
+
+		/* 
+		 * If BEFORE was specified, the new label goes in the neighbour's
+		 * position. Otherwise, it goes in the position after that.
+		 */
+		newelemorder = nbr_en->enumsortorder;
+		if (newValIsAfter)
+			newelemorder++;
+
+		/* 
+		 * Add 1 to the sortorder of all the labels after where the
+		 * new label goes. Do it from the end back so we don't get
+		 * uniqueness violations.
+		 */
+		for (i = nelems - 1; i>= 0; i--)
+		{
+			HeapTuple newtup;
+			Form_pg_enum exst_en = (Form_pg_enum) GETSTRUCT(existing[i]);
+			if (exst_en->enumsortorder < newelemorder)
+				break;
+			
+			newtup = heap_copytuple(existing[i]);
+			exst_en = (Form_pg_enum) GETSTRUCT(newtup);
+			exst_en->enumsortorder ++;
+
+			simple_heap_update(pg_enum, &newtup->t_self, newtup);
+
+			CatalogUpdateIndexes(pg_enum, newtup);
+
+		}
+
+		ReleaseCatCacheList(list);
+
+		/* are the labels sorted by OID? */
+		if (result && newelemorder > 1)
+			result = newOid > HeapTupleGetOid(existing[newelemorder-2]);
+		if (result && newelemorder < nelems + 1)
+			result = newOid < HeapTupleGetOid(existing[newelemorder-1]);
+ 
+	}
+
+	/* set up the new entry */
+	tupDesc = pg_enum->rd_att;
+	memset(nulls, false, sizeof(nulls));
+	values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
+	namestrcpy(&enumlabel, newVal);
+	values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
+	values[Anum_pg_enum_enumsortorder -1] =	Int32GetDatum(newelemorder);
+	enum_tup = heap_form_tuple(tupDesc, values, nulls);
+	HeapTupleSetOid(enum_tup, newOid);
+	simple_heap_insert(pg_enum, enum_tup);
+	CatalogUpdateIndexes(pg_enum, enum_tup);
+	heap_freetuple(enum_tup);
+
+	heap_close(pg_enum, RowExclusiveLock);
+
+	return result;
+
+}
 
 
 /*
@@ -33,8 +223,7 @@ static int	oid_cmp(const void *p1, const void *p2);
  * vals is a list of Value strings.
  */
 void
-EnumValuesCreate(Oid enumTypeOid, List *vals,
-				 Oid binary_upgrade_next_pg_enum_oid)
+EnumValuesCreate(Oid enumTypeOid, List *vals)
 {
 	Relation	pg_enum;
 	TupleDesc	tupDesc;
@@ -50,9 +239,9 @@ EnumValuesCreate(Oid enumTypeOid, List *vals,
 	num_elems = list_length(vals);
 
 	/*
-	 * XXX we do not bother to check the list of values for duplicates --- if
+	 * We do not bother to check the list of values for duplicates --- if
 	 * you have any, you'll get a less-than-friendly unique-index violation.
-	 * Is it worth trying harder?
+	 * It is probably not worth trying harder.
 	 */
 
 	pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
@@ -62,35 +251,24 @@ EnumValuesCreate(Oid enumTypeOid, List *vals,
 	 * 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++)
 	{
 		/*
-		 * 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.
+		 * The pg_enum.oid is stored in user tables.  This oid must be
+		 * preserved by binary upgrades.
 		 */
-		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);
+		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));
@@ -114,6 +292,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals,
 		values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
 		namestrcpy(&enumlabel, lab);
 		values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
+		values[Anum_pg_enum_enumsortorder -1] = Int32GetDatum(elemno+1);
 
 		tup = heap_form_tuple(tupDesc, values, nulls);
 		HeapTupleSetOid(tup, oids[elemno]);
@@ -164,7 +343,7 @@ EnumValuesDelete(Oid enumTypeOid)
 }
 
 
-/* qsort comparison function */
+/* qsort comparison for oids */
 static int
 oid_cmp(const void *p1, const void *p2)
 {
@@ -177,3 +356,16 @@ oid_cmp(const void *p1, const void *p2)
 		return 1;
 	return 0;
 }
+
+/* qsort comparison function for tuples by sort order */
+static int
+sort_order_cmp(const void *p1, const void *p2)
+{
+	HeapTuple		v1 = *((const HeapTuple *) p1);
+	HeapTuple		v2 = *((const HeapTuple *) p2);
+	Form_pg_enum en1 = (Form_pg_enum) GETSTRUCT(v1);
+	Form_pg_enum en2 = (Form_pg_enum) GETSTRUCT(v2);
+
+	return en1->enumsortorder - en2->enumsortorder;
+}
+
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index c7efd6d..109ee0e 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -112,6 +112,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 	values[i++] = ObjectIdGetDatum(InvalidOid); /* typbasetype */
 	values[i++] = Int32GetDatum(-1);	/* typtypmod */
 	values[i++] = Int32GetDatum(0);		/* typndims */
+	values[i++] = Int32GetDatum(-1);	/* typnlabels */
+	values[i++] = BoolGetDatum(false);	/* typsorted */
 	nulls[i++] = true;			/* typdefaultbin */
 	nulls[i++] = true;			/* typdefault */
 
@@ -204,7 +206,9 @@ TypeCreate(Oid newTypeOid,
 		   char storage,
 		   int32 typeMod,
 		   int32 typNDims,		/* Array dimensions for baseType */
-		   bool typeNotNull)
+		   bool typeNotNull,
+		   int32 typeNLabels,
+		   bool typeSorted)
 {
 	Relation	pg_type_desc;
 	Oid			typeObjectId;
@@ -342,6 +346,8 @@ TypeCreate(Oid newTypeOid,
 	values[i++] = ObjectIdGetDatum(baseType);	/* typbasetype */
 	values[i++] = Int32GetDatum(typeMod);		/* typtypmod */
 	values[i++] = Int32GetDatum(typNDims);		/* typndims */
+	values[i++] = Int32GetDatum(typeNLabels);	/* typnlabels */
+	values[i++] = BoolGetDatum(typeSorted);	    /* typsorted */
 
 	/*
 	 * initialize the default binary value for this type.  Check for nulls of
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index fc80175..2ed8278 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -85,12 +85,11 @@ static Oid	findTypeTypmodoutFunction(List *procname);
 static Oid	findTypeAnalyzeFunction(List *procname, Oid typeOid);
 static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
 static void checkDomainOwner(HeapTuple tup, TypeName *typename);
+static void checkEnumOwner(HeapTuple tup, TypeName *typename);
 static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
 					Oid baseTypeOid,
 					int typMod, Constraint *constr,
 					char *domainName);
-
-
 /*
  * DefineType
  *		Registers a new base type.
@@ -562,8 +561,9 @@ DefineType(List *names, List *parameters)
 				   storage,		/* TOAST strategy */
 				   -1,			/* typMod (Domains only) */
 				   0,			/* Array Dimensions of typbasetype */
-				   false);		/* Type NOT NULL */
-
+				   false,		/* Type NOT NULL */
+				   -1,          /* no enum labels */
+				   false);        /* type is not an enum, so not sorted */
 	/*
 	 * Create the array type that goes with it.
 	 */
@@ -601,7 +601,9 @@ DefineType(List *names, List *parameters)
 			   'x',				/* ARRAY is always toastable */
 			   -1,				/* typMod (Domains only) */
 			   0,				/* Array dimensions of typbasetype */
-			   false);			/* Type NOT NULL */
+			   false,			/* Type NOT NULL */
+			   -1,              /* no enum labels */
+			   false);          /* type is not an enum, so not sorted */
 
 	pfree(array_type);
 }
@@ -1044,7 +1046,9 @@ DefineDomain(CreateDomainStmt *stmt)
 				   storage,		/* TOAST strategy */
 				   basetypeMod, /* typeMod value */
 				   typNDims,	/* Array dimensions for base type */
-				   typNotNull); /* Type NOT NULL */
+				   typNotNull,  /* Type NOT NULL */
+				   -1,          /* no enum labels */
+				   false);      /* type is not an enum, so not sorted */
 
 	/*
 	 * Process constraints which refer to the domain ID returned by TypeCreate
@@ -1094,6 +1098,9 @@ DefineEnum(CreateEnumStmt *stmt)
 	AclResult	aclresult;
 	Oid			old_type_oid;
 	Oid			enumArrayOid;
+	int         num_labels;
+
+	num_labels = list_length(stmt->vals);
 
 	/* Convert list of names to a name and namespace */
 	enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1153,10 +1160,12 @@ DefineEnum(CreateEnumStmt *stmt)
 				   'p',			/* TOAST strategy always plain */
 				   -1,			/* typMod (Domains only) */
 				   0,			/* Array dimensions of typbasetype */
-				   false);		/* Type NOT NULL */
+				   false,		/* Type NOT NULL */
+				   num_labels,  /* count enum labels */
+				   true);       /* enums always start sorted */
 
 	/* Enter the enum's values into pg_enum */
-	EnumValuesCreate(enumTypeOid, stmt->vals, InvalidOid);
+	EnumValuesCreate(enumTypeOid, stmt->vals);
 
 	/*
 	 * Create the array type that goes with it.
@@ -1192,11 +1201,88 @@ DefineEnum(CreateEnumStmt *stmt)
 			   'x',				/* ARRAY is always toastable */
 			   -1,				/* typMod (Domains only) */
 			   0,				/* Array dimensions of typbasetype */
-			   false);			/* Type NOT NULL */
+			   false,			/* Type NOT NULL */
+			   -1,              /* no enum labels */
+			   false);          /* type is not an enum, so not sorted */
 
 	pfree(enumArrayName);
 }
 
+/*
+ * AlterEnum
+ *		Registers a new label for an existing enum.
+ */
+void
+AlterEnum (AlterEnumStmt *stmt)
+{
+	Oid			enum_type_oid;
+	TypeName  *typename;
+	bool       sorted;
+	HeapTuple tup, newtup;
+	Relation  rel;
+	Form_pg_type typTup;
+
+	/* Make a TypeName so we can use standard type lookup machinery */
+	typename = makeTypeNameFromNameList(stmt->typeName);
+	enum_type_oid = typenameTypeId(NULL, typename, NULL);
+
+	/* Look up the row in the type table */
+	rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+	tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(enum_type_oid));
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
+
+	/* Copy the syscache entry so we can scribble on it below */
+	newtup = heap_copytuple(tup);
+	ReleaseSysCache(tup);
+	tup = newtup;
+	typTup = (Form_pg_type) GETSTRUCT(tup);
+
+	/* Check it's an enum and check user has permission to ALTER the enum */
+	checkEnumOwner(tup, typename);
+
+	/* Add the new label */
+	sorted = AddEnumLabel (enum_type_oid, stmt->newVal, 
+						   stmt->newValNeighbour, stmt->newValIsAfter,
+						   typTup->typnlabels, typTup->typsorted);
+
+	/* Update the row in pg_type */
+	typTup->typnlabels += 1;
+	typTup->typsorted = sorted;
+
+	simple_heap_update(rel, &tup->t_self, tup);
+
+	CatalogUpdateIndexes(rel, tup);
+
+	/* Clean up */
+	heap_close(rel, RowExclusiveLock);
+}
+
+
+/*
+ * checkEnumOwner
+ *
+ * Check that the type is actually an enum and that the current user
+ * has permission to do ALTER TYPE on it.  Throw an error if not.
+ */
+static void
+checkEnumOwner(HeapTuple tup, TypeName *typename)
+{
+	Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
+
+	/* Check that this is actually a domain */
+	if (typTup->typtype != TYPTYPE_ENUM)
+		ereport(ERROR,
+				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				 errmsg("\"%s\" is not an enum",
+						TypeNameToString(typename))));
+
+	/* Permission check: must own type */
+	if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
+					   format_type_be(HeapTupleGetOid(tup)));
+}
 
 /*
  * Find suitable I/O functions for a type.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index b3e907a..59cfe96 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2836,6 +2836,19 @@ _copyCreateEnumStmt(CreateEnumStmt *from)
 	return newnode;
 }
 
+static AlterEnumStmt *
+_copyAlterEnumStmt(AlterEnumStmt *from)
+{
+	AlterEnumStmt *newnode = makeNode(AlterEnumStmt);
+
+	COPY_NODE_FIELD(typeName);
+	COPY_STRING_FIELD(newVal);
+	COPY_STRING_FIELD(newValNeighbour);
+	COPY_SCALAR_FIELD(newValIsAfter);
+
+	return newnode;
+}
+
 static ViewStmt *
 _copyViewStmt(ViewStmt *from)
 {
@@ -3989,6 +4002,9 @@ copyObject(void *from)
 		case T_CreateEnumStmt:
 			retval = _copyCreateEnumStmt(from);
 			break;
+		case T_AlterEnumStmt:
+			retval = _copyAlterEnumStmt(from);
+			break;
 		case T_ViewStmt:
 			retval = _copyViewStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 7ec0923..900bf37 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1375,6 +1375,17 @@ _equalCreateEnumStmt(CreateEnumStmt *a, CreateEnumStmt *b)
 }
 
 static bool
+_equalAlterEnumStmt(AlterEnumStmt *a, AlterEnumStmt *b)
+{
+	COMPARE_NODE_FIELD(typeName);
+	COMPARE_STRING_FIELD(newVal);
+	COMPARE_STRING_FIELD(newValNeighbour);
+	COMPARE_SCALAR_FIELD(newValIsAfter);
+
+	return true;
+}
+
+static bool
 _equalViewStmt(ViewStmt *a, ViewStmt *b)
 {
 	COMPARE_NODE_FIELD(view);
@@ -2678,6 +2689,9 @@ equal(void *a, void *b)
 		case T_CreateEnumStmt:
 			retval = _equalCreateEnumStmt(a, b);
 			break;
+		case T_AlterEnumStmt:
+			retval = _equalAlterEnumStmt(a, b);
+			break;
 		case T_ViewStmt:
 			retval = _equalViewStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index d5a0f29..9ef84aa 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -181,8 +181,8 @@ static TypeName *TableFuncTypeName(List *columns);
 }
 
 %type <node>	stmt schema_stmt
-		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
-		AlterForeignServerStmt AlterGroupStmt
+        AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
+        AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
 		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
 		AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
 		AlterRoleStmt AlterRoleSetStmt
@@ -648,6 +648,7 @@ stmt :
 			| AlterDatabaseSetStmt
 			| AlterDefaultPrivilegesStmt
 			| AlterDomainStmt
+			| AlterEnumStmt
 			| AlterFdwStmt
 			| AlterForeignServerStmt
 			| AlterFunctionStmt
@@ -3781,6 +3782,46 @@ enum_val_list:	Sconst
 				{ $$ = lappend($1, makeString($3)); }
 		;
 
+/*****************************************************************************
+ *
+ *	ALTER TYPE enumtype ADD ...	
+ *
+ *****************************************************************************/
+
+AlterEnumStmt:
+         ALTER TYPE_P any_name ADD_P Sconst
+			 {
+				 AlterEnumStmt *n = makeNode(AlterEnumStmt);
+				 n->typeName = $3;
+				 n->newVal = $5;
+				 n->newValNeighbour = NULL;
+				 n->newValIsAfter = true;
+
+				 $$ = (Node *) n;
+			 }
+		 | ALTER TYPE_P any_name ADD_P Sconst BEFORE Sconst
+			 {
+				 AlterEnumStmt *n = makeNode(AlterEnumStmt);
+				 n->typeName = $3;
+				 n->newVal = $5;
+				 n->newValNeighbour = $7;
+				 n->newValIsAfter = false;
+
+				 $$ = (Node *) n;
+			 }
+		 | ALTER TYPE_P any_name ADD_P Sconst AFTER Sconst
+			 {
+				 AlterEnumStmt *n = makeNode(AlterEnumStmt);
+				 n->typeName = $3;
+				 n->newVal = $5;
+				 n->newValNeighbour = $7;
+				 n->newValIsAfter = true;
+
+				 $$ = (Node *) n;
+			 }
+		 ;
+
+
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 77ee926..39ea03e 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -189,6 +189,7 @@ check_xact_readonly(Node *parsetree)
 		case T_CreateTrigStmt:
 		case T_CompositeTypeStmt:
 		case T_CreateEnumStmt:
+		case T_AlterEnumStmt:
 		case T_ViewStmt:
 		case T_DropCastStmt:
 		case T_DropStmt:
@@ -846,6 +847,10 @@ standard_ProcessUtility(Node *parsetree,
 			DefineEnum((CreateEnumStmt *) parsetree);
 			break;
 
+		case T_AlterEnumStmt:	/* ALTER TYPE (enum) */
+			AlterEnum((AlterEnumStmt *) parsetree);
+			break;
+
 		case T_ViewStmt:		/* CREATE VIEW */
 			DefineView((ViewStmt *) parsetree, queryString);
 			break;
@@ -1846,6 +1851,10 @@ CreateCommandTag(Node *parsetree)
 			tag = "CREATE TYPE";
 			break;
 
+		case T_AlterEnumStmt:
+			tag = "ALTER TYPE";
+			break;
+
 		case T_ViewStmt:
 			tag = "CREATE VIEW";
 			break;
@@ -2384,6 +2393,10 @@ GetCommandLogLevel(Node *parsetree)
 			lev = LOGSTMT_DDL;
 			break;
 
+		case T_AlterEnumStmt:
+			lev = LOGSTMT_DDL;
+			break;
+
 		case T_ViewStmt:
 			lev = LOGSTMT_DDL;
 			break;
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index 74cc0c2..63eab09 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -14,6 +14,7 @@
 #include "postgres.h"
 
 #include "catalog/pg_enum.h"
+#include "catalog/pg_type.h"
 #include "fmgr.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -22,9 +23,26 @@
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 
+typedef struct 
+{
+	Oid      enum_oid;
+	int32   sort_order;
+} enum_sort;
+
+typedef struct 
+{
+	Oid       enumtypoid;
+	bool      oids_are_sorted;
+	int       sort_list_length;
+	int       label_count;
+	enum_sort sort_order_list[1];
+} enum_sort_cache;
+	
+
 
 static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
-static int	enum_elem_cmp(const void *left, const void *right);
+static int	enum_sort_cmp(const void *left, const void *right);
+static int	enum_oid_cmp(const void *left, const void *right);
 
 
 /* Basic I/O support */
@@ -155,13 +173,142 @@ enum_send(PG_FUNCTION_ARGS)
 
 /* Comparison functions and related */
 
+static inline int 
+enum_ccmp(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
+{
+
+	enum_sort_cache * mycache;
+	enum_sort *es1, *es2, srch;
+	int sort1, sort2;
+	bool added = false;
+	HeapTuple	enum_tup, type_tup;
+	Form_pg_enum en;
+	Oid typeoid;
+	Form_pg_type typ;
+
+	if (arg1 == arg2)
+		return 0;
+
+	mycache = (enum_sort_cache *) fcinfo->flinfo->fn_extra;
+	if (mycache == NULL )
+	{
+		enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
+		en = (Form_pg_enum) GETSTRUCT(enum_tup);
+		typeoid = en->enumtypid;
+		type_tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeoid));
+		typ = (Form_pg_type)  GETSTRUCT(type_tup);
+		if (typ->typtype != 'e')
+			elog(ERROR,"wrong type for oid %u",typeoid);
+        fcinfo->flinfo->fn_extra = 
+		  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+							 sizeof(enum_sort_cache) + 
+							 (typ->typnlabels * sizeof(enum_sort)));
+        mycache = (enum_sort_cache *) fcinfo->flinfo->fn_extra;
+		mycache->enumtypoid = typeoid;
+		mycache->sort_list_length = 1;
+		mycache->label_count = typ->typnlabels;
+		mycache->oids_are_sorted = typ->typsorted;
+		mycache->sort_order_list[0].enum_oid = arg1;
+		mycache->sort_order_list[0].sort_order = en->enumsortorder;
+		ReleaseSysCache(type_tup);
+		ReleaseSysCache(enum_tup);
+	}
+
+	if (mycache->oids_are_sorted)
+		return arg1 - arg2;
+
+	srch.enum_oid = arg1;
+	es1 = bsearch(&srch,
+				  mycache->sort_order_list,
+				  mycache->sort_list_length,
+				  sizeof(enum_sort),
+				  enum_oid_cmp);
+	srch.enum_oid = arg2;
+	es2 = bsearch(&srch,
+				  mycache->sort_order_list,
+				  mycache->sort_list_length,
+				  sizeof(enum_sort),
+				  enum_oid_cmp);
+
+	if (es1 == NULL)
+	{
+		
+		enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
+		en = (Form_pg_enum) GETSTRUCT(enum_tup);
+		mycache->sort_order_list[mycache->sort_list_length].enum_oid = arg1;
+		sort1 = en->enumsortorder;
+		mycache->sort_order_list[mycache->sort_list_length].sort_order = 
+			sort1; 
+		ReleaseSysCache(enum_tup);
+		mycache->sort_list_length ++;
+		added = true;
+	}
+	else
+	{
+		/* already in cache */
+		sort1 = es1->sort_order;
+	}
+
+	if (es2 == NULL)
+	{
+		
+		enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg2));
+		en = (Form_pg_enum) GETSTRUCT(enum_tup);
+		sort2 = en->enumsortorder;
+		mycache->sort_order_list[mycache->sort_list_length].enum_oid = arg2;
+		mycache->sort_order_list[mycache->sort_list_length].sort_order = 
+			sort2;
+		ReleaseSysCache(enum_tup);
+		mycache->sort_list_length ++;
+		added = true;
+	}
+	else
+	{
+		/* already in cache */
+		sort2 = es2->sort_order;
+	}
+
+	if (added)
+	{
+		/* 
+		 * If we have more than a handful, just fetch them all, so we limit
+		 * the number of sort operations required.
+		 */
+		if (mycache->sort_list_length > 10 && 
+			mycache->sort_list_length < mycache->label_count)
+		{
+			CatCList   *nlist;
+			int			num, i;
+
+			nlist = SearchSysCacheList1(ENUMTYPOIDNAME, 
+									   ObjectIdGetDatum(mycache->enumtypoid));
+			num = nlist->n_members;
+			for (i = 0; i < num; i++)
+			{
+				HeapTuple tup = &(nlist->members[i]->tuple);
+				Form_pg_enum en = (Form_pg_enum) GETSTRUCT(tup);
+				
+				mycache->sort_order_list[i].enum_oid = HeapTupleGetOid(tup);
+				mycache->sort_order_list[i].sort_order = en->enumsortorder; 
+			}
+
+			ReleaseCatCacheList(nlist);
+		}
+
+		qsort(mycache->sort_order_list,mycache->sort_list_length,
+			  sizeof(enum_sort),enum_oid_cmp);
+	}
+
+	return sort1 - sort2;
+}
+
 Datum
 enum_lt(PG_FUNCTION_ARGS)
 {
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_BOOL(a < b);
+	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) < 0);
 }
 
 Datum
@@ -170,7 +317,7 @@ enum_le(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_BOOL(a <= b);
+	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) <= 0);
 }
 
 Datum
@@ -197,7 +344,7 @@ enum_ge(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_BOOL(a >= b);
+	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) >= 0);
 }
 
 Datum
@@ -206,7 +353,7 @@ enum_gt(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_BOOL(a > b);
+	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) > 0);
 }
 
 Datum
@@ -215,7 +362,7 @@ enum_smaller(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_OID(a <= b ? a : b);
+	PG_RETURN_OID(enum_ccmp(a,b,fcinfo) < 0 ? a : b);
 }
 
 Datum
@@ -224,7 +371,7 @@ enum_larger(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	PG_RETURN_OID(a >= b ? a : b);
+	PG_RETURN_OID(enum_ccmp(a,b,fcinfo) > 0 ? a : b);
 }
 
 Datum
@@ -233,10 +380,10 @@ enum_cmp(PG_FUNCTION_ARGS)
 	Oid			a = PG_GETARG_OID(0);
 	Oid			b = PG_GETARG_OID(1);
 
-	if (a > b)
-		PG_RETURN_INT32(1);
-	else if (a == b)
+	if (a == b)
 		PG_RETURN_INT32(0);
+	else if (enum_ccmp(a,b,fcinfo) > 0)
+		PG_RETURN_INT32(1);
 	else
 		PG_RETURN_INT32(-1);
 }
@@ -248,6 +395,7 @@ enum_first(PG_FUNCTION_ARGS)
 {
 	Oid			enumtypoid;
 	Oid			min = InvalidOid;
+	int         min_sort = -1; /* value will never in fact be used */
 	CatCList   *list;
 	int			num,
 				i;
@@ -267,10 +415,14 @@ enum_first(PG_FUNCTION_ARGS)
 	num = list->n_members;
 	for (i = 0; i < num; i++)
 	{
-		Oid			valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data);
-
-		if (!OidIsValid(min) || valoid < min)
-			min = valoid;
+		HeapTuple tup = &(list->members[i]->tuple);
+		Form_pg_enum en = (Form_pg_enum) GETSTRUCT(tup);
+
+		if (!OidIsValid(min) || en->enumsortorder < min_sort)
+		{
+			min = HeapTupleGetOid(tup);
+			min_sort = en->enumsortorder;
+		}
 	}
 
 	ReleaseCatCacheList(list);
@@ -287,6 +439,7 @@ enum_last(PG_FUNCTION_ARGS)
 {
 	Oid			enumtypoid;
 	Oid			max = InvalidOid;
+	int         max_sort = -1; /* value will never in fact be used */
 	CatCList   *list;
 	int			num,
 				i;
@@ -306,10 +459,14 @@ enum_last(PG_FUNCTION_ARGS)
 	num = list->n_members;
 	for (i = 0; i < num; i++)
 	{
-		Oid			valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data);
-
-		if (!OidIsValid(max) || valoid > max)
-			max = valoid;
+		HeapTuple tup = &(list->members[i]->tuple);
+		Form_pg_enum en = (Form_pg_enum) GETSTRUCT(tup);
+
+		if (!OidIsValid(max) || en->enumsortorder > max_sort)
+		{
+			max = HeapTupleGetOid(tup);
+			max_sort = en->enumsortorder;
+		}
 	}
 
 	ReleaseCatCacheList(list);
@@ -382,46 +539,76 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
 				i,
 				j;
 	Datum	   *elems;
+	enum_sort  *sort_items;
+	bool        left_found;
 
 	list = SearchSysCacheList1(ENUMTYPOIDNAME, ObjectIdGetDatum(enumtypoid));
 	total = list->n_members;
 
 	elems = (Datum *) palloc(total * sizeof(Datum));
+	sort_items = (enum_sort *) palloc(total * sizeof(enum_sort));
 
-	j = 0;
 	for (i = 0; i < total; i++)
 	{
-		Oid			val = HeapTupleGetOid(&(list->members[i]->tuple));
+		HeapTuple tup = &(list->members[i]->tuple);
+		Form_pg_enum en = (Form_pg_enum) GETSTRUCT(tup);
+
+		sort_items[i].enum_oid = HeapTupleGetOid(tup);
+		sort_items[i].sort_order = en->enumsortorder;
 
-		if ((!OidIsValid(lower) || lower <= val) &&
-			(!OidIsValid(upper) || val <= upper))
-			elems[j++] = ObjectIdGetDatum(val);
 	}
 
 	/* shouldn't need the cache anymore */
 	ReleaseCatCacheList(list);
 
-	/* sort results into OID order */
-	qsort(elems, j, sizeof(Datum), enum_elem_cmp);
+	/* sort results into sort_order sequence */
+	qsort(sort_items, total, sizeof(enum_sort), enum_sort_cmp);
+
+	j = 0; 
+	left_found = !OidIsValid(lower);
+	for (i=0; i < total; i++)
+	{
+		if (! left_found && lower == sort_items[i].enum_oid)
+			left_found = true;
+
+		if (left_found)
+			elems[j++] = ObjectIdGetDatum(sort_items[i].enum_oid);
+
+		if (OidIsValid(upper) && upper == sort_items[i].enum_oid)
+			break;
+	}
 
 	/* note this hardwires some details about the representation of Oid */
 	result = construct_array(elems, j, enumtypoid, sizeof(Oid), true, 'i');
 
 	pfree(elems);
+	pfree(sort_items);
 
 	return result;
 }
 
-/* qsort comparison function for Datums that are OIDs */
+/* 
+ * qsort comparison using sort order, for range routines 
+ */
 static int
-enum_elem_cmp(const void *left, const void *right)
+enum_sort_cmp(const void *left, const void *right)
 {
-	Oid			l = DatumGetObjectId(*((const Datum *) left));
-	Oid			r = DatumGetObjectId(*((const Datum *) right));
-
-	if (l < r)
-		return -1;
-	if (l > r)
-		return 1;
-	return 0;
+	enum_sort  *l = (enum_sort *) left;
+	enum_sort  *r = (enum_sort *) right;
+
+	return l->sort_order - r->sort_order;
 }
+
+/* 
+ * qsort comparison using OID order for comparison search cache
+ */
+static int 
+enum_oid_cmp(const void *es1, const void *es2)
+{
+	enum_sort *p1, *p2;
+	p1 = (enum_sort *)es1;
+	p2 = (enum_sort *)es2;
+	return p1->enum_oid - p2->enum_oid;
+}
+
+
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 01e1a48..94ae650 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -6605,17 +6605,24 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 	PQExpBuffer query = createPQExpBuffer();
 	PGresult   *res;
 	int			num,
-				i;
+		        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",
+    if  (fout->remoteVersion > 90000)
+		appendPQExpBuffer(query, "SELECT oid, enumlabel "
+						  "FROM pg_catalog.pg_enum "
+						  "WHERE enumtypid = '%u'"
+						  "ORDER BY enumsortorder",
+					  tyinfo->dobj.catId.oid);
+	else
+		appendPQExpBuffer(query, "SELECT oid, enumlabel "
+						  "FROM pg_catalog.pg_enum "
+						  "WHERE enumtypid = '%u'"
+						  "ORDER BY oid",
 					  tyinfo->dobj.catId.oid);
 
 	res = PQexec(g_conn, query->data);
@@ -6661,17 +6668,19 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 		{
 			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");
+							  "SELECT binary_upgrade.set_next_pg_enum_oid('%u'::pg_catalog.oid);\n",
+							  enum_oid);
+			appendPQExpBuffer(q, "ALTER TYPE %s.",
+					  fmtId(tyinfo->dobj.namespace->dobj.name));
+			appendPQExpBuffer(q, "%s ADD ",
+					  fmtId(tyinfo->dobj.name));
+ 			appendStringLiteralAH(q, label, fout);
+			appendPQExpBuffer(q, ";\n\n");
 		}
-		appendPQExpBuffer(q, "\n");
 	}
 
 	ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index e56e15f..8db3800 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -147,6 +147,8 @@ DECLARE_UNIQUE_INDEX(pg_enum_oid_index, 3502, on pg_enum using btree(oid oid_ops
 #define EnumOidIndexId	3502
 DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, on pg_enum using btree(enumtypid oid_ops, enumlabel name_ops));
 #define EnumTypIdLabelIndexId 3503
+DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3539, on pg_enum using btree(enumtypid oid_ops, enumsortorder int4_ops));
+#define EnumTypIdSortOrderIndexId 3539
 
 /* This following index is not used for a cache and is not unique */
 DECLARE_INDEX(pg_index_indrelid_index, 2678, on pg_index using btree(indrelid oid_ops));
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index de34576..184cfb3 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class;
  */
 
 /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
-DATA(insert OID = 1247 (  pg_type		PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f f r 28 0 t f f f f f 3 _null_ _null_ ));
+DATA(insert OID = 1247 (  pg_type		PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f f r 30 0 t f f f f f 3 _null_ _null_ ));
 DESCR("");
 DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f f r 19 0 f f f f f f 3 _null_ _null_ ));
 DESCR("");
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index 3a1df77..b85f9cf 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -35,6 +35,7 @@ CATALOG(pg_enum,3501)
 {
 	Oid			enumtypid;		/* OID of owning enum type */
 	NameData	enumlabel;		/* text representation of enum value */
+	int4        enumsortorder;  /* sort order for this enum label */
 } FormData_pg_enum;
 
 /* ----------------
@@ -48,9 +49,10 @@ typedef FormData_pg_enum *Form_pg_enum;
  *		compiler constants for pg_enum
  * ----------------
  */
-#define Natts_pg_enum					2
+#define Natts_pg_enum					3
 #define Anum_pg_enum_enumtypid			1
 #define Anum_pg_enum_enumlabel			2
+#define Anum_pg_enum_enumsortorder		3
 
 /* ----------------
  *		pg_enum has no initial contents
@@ -60,8 +62,9 @@ typedef FormData_pg_enum *Form_pg_enum;
 /*
  * prototypes for functions in pg_enum.c
  */
-extern void EnumValuesCreate(Oid enumTypeOid, List *vals,
-				 Oid binary_upgrade_next_pg_enum_oid);
+extern void EnumValuesCreate(Oid enumTypeOid, List *vals);
 extern void EnumValuesDelete(Oid enumTypeOid);
+extern bool AddEnumLabel(Oid enumTypeOid, char *newVal, char *neighbour, 
+						 bool newValIsAfter, int nelems, bool elems_are_sorted);
 
 #endif   /* PG_ENUM_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index b2e14ce..3ea2118 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -194,6 +194,18 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
 	 */
 	int4		typndims;
 
+    /* 
+     * typnlabels, contains a count on the number of labels an enum type has, 
+     * -1 for a non-enum type.
+     */
+    int4          typnlabels;
+
+    /*
+     * typsorted is true if the oids of an enum type reflect the type's sort
+     * order, false otherwise including for a non-enum type.
+     */
+    bool         typsorted;
+
 	/*
 	 * If typdefaultbin is not NULL, it is the nodeToString representation of
 	 * a default expression for the type.  Currently this is only used for
@@ -224,7 +236,7 @@ typedef FormData_pg_type *Form_pg_type;
  *		compiler constants for pg_type
  * ----------------
  */
-#define Natts_pg_type					28
+#define Natts_pg_type					30
 #define Anum_pg_type_typname			1
 #define Anum_pg_type_typnamespace		2
 #define Anum_pg_type_typowner			3
@@ -251,8 +263,10 @@ typedef FormData_pg_type *Form_pg_type;
 #define Anum_pg_type_typbasetype		24
 #define Anum_pg_type_typtypmod			25
 #define Anum_pg_type_typndims			26
-#define Anum_pg_type_typdefaultbin		27
-#define Anum_pg_type_typdefault			28
+#define Anum_pg_type_typnlabels			27
+#define Anum_pg_type_typsorted			28
+#define Anum_pg_type_typdefaultbin		29
+#define Anum_pg_type_typdefault			30
 
 
 /* ----------------
@@ -269,83 +283,83 @@ typedef FormData_pg_type *Form_pg_type;
  */
 
 /* OIDS 1 - 99 */
-DATA(insert OID = 16 (	bool	   PGNSP PGUID	1 t b B t t \054 0	 0 1000 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 16 (	bool	   PGNSP PGUID	1 t b B t t \054 0	 0 1000 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("boolean, 'true'/'false'");
 #define BOOLOID			16
 
-DATA(insert OID = 17 (	bytea	   PGNSP PGUID -1 f b U f t \054 0	0 1001 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 17 (	bytea	   PGNSP PGUID -1 f b U f t \054 0	0 1001 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("variable-length string, binary values escaped");
 #define BYTEAOID		17
 
-DATA(insert OID = 18 (	char	   PGNSP PGUID	1 t b S f t \054 0	 0 1002 charin charout charrecv charsend - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 18 (	char	   PGNSP PGUID	1 t b S f t \054 0	 0 1002 charin charout charrecv charsend - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("single character");
 #define CHAROID			18
 
-DATA(insert OID = 19 (	name	   PGNSP PGUID NAMEDATALEN f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 19 (	name	   PGNSP PGUID NAMEDATALEN f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("63-character type for storing system identifiers");
 #define NAMEOID			19
 
-DATA(insert OID = 20 (	int8	   PGNSP PGUID	8 FLOAT8PASSBYVAL b N f t \054 0	 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 20 (	int8	   PGNSP PGUID	8 FLOAT8PASSBYVAL b N f t \054 0	 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("~18 digit integer, 8-byte storage");
 #define INT8OID			20
 
-DATA(insert OID = 21 (	int2	   PGNSP PGUID	2 t b N f t \054 0	 0 1005 int2in int2out int2recv int2send - - - s p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 21 (	int2	   PGNSP PGUID	2 t b N f t \054 0	 0 1005 int2in int2out int2recv int2send - - - s p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("-32 thousand to 32 thousand, 2-byte storage");
 #define INT2OID			21
 
-DATA(insert OID = 22 (	int2vector PGNSP PGUID -1 f b A f t \054 0	21 1006 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 22 (	int2vector PGNSP PGUID -1 f b A f t \054 0	21 1006 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("array of int2, used in system tables");
 #define INT2VECTOROID	22
 
-DATA(insert OID = 23 (	int4	   PGNSP PGUID	4 t b N f t \054 0	 0 1007 int4in int4out int4recv int4send - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 23 (	int4	   PGNSP PGUID	4 t b N f t \054 0	 0 1007 int4in int4out int4recv int4send - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("-2 billion to 2 billion integer, 4-byte storage");
 #define INT4OID			23
 
-DATA(insert OID = 24 (	regproc    PGNSP PGUID	4 t b N f t \054 0	 0 1008 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 24 (	regproc    PGNSP PGUID	4 t b N f t \054 0	 0 1008 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered procedure");
 #define REGPROCOID		24
 
-DATA(insert OID = 25 (	text	   PGNSP PGUID -1 f b S t t \054 0	0 1009 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 25 (	text	   PGNSP PGUID -1 f b S t t \054 0	0 1009 textin textout textrecv textsend - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("variable-length string, no limit specified");
 #define TEXTOID			25
 
-DATA(insert OID = 26 (	oid		   PGNSP PGUID	4 t b N t t \054 0	 0 1028 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 26 (	oid		   PGNSP PGUID	4 t b N t t \054 0	 0 1028 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("object identifier(oid), maximum 4 billion");
 #define OIDOID			26
 
-DATA(insert OID = 27 (	tid		   PGNSP PGUID	6 f b U f t \054 0	 0 1010 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 27 (	tid		   PGNSP PGUID	6 f b U f t \054 0	 0 1010 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("(block, offset), physical location of tuple");
 #define TIDOID		27
 
-DATA(insert OID = 28 (	xid		   PGNSP PGUID	4 t b U f t \054 0	 0 1011 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 28 (	xid		   PGNSP PGUID	4 t b U f t \054 0	 0 1011 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("transaction id");
 #define XIDOID 28
 
-DATA(insert OID = 29 (	cid		   PGNSP PGUID	4 t b U f t \054 0	 0 1012 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 29 (	cid		   PGNSP PGUID	4 t b U f t \054 0	 0 1012 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("command identifier type, sequence in transaction id");
 #define CIDOID 29
 
-DATA(insert OID = 30 (	oidvector  PGNSP PGUID -1 f b A f t \054 0	26 1013 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 30 (	oidvector  PGNSP PGUID -1 f b A f t \054 0	26 1013 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("array of oids, used in system tables");
 #define OIDVECTOROID	30
 
 /* hand-built rowtype entries for bootstrapped catalogs */
 /* NB: OIDs assigned here must match the BKI_ROWTYPE_OID declarations */
 
-DATA(insert OID = 71 (	pg_type			PGNSP PGUID -1 f c C f t \054 1247 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 75 (	pg_attribute	PGNSP PGUID -1 f c C f t \054 1249 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 81 (	pg_proc			PGNSP PGUID -1 f c C f t \054 1255 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 83 (	pg_class		PGNSP PGUID -1 f c C f t \054 1259 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 71 (	pg_type			PGNSP PGUID -1 f c C f t \054 1247 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 75 (	pg_attribute	PGNSP PGUID -1 f c C f t \054 1249 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 81 (	pg_proc			PGNSP PGUID -1 f c C f t \054 1255 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 83 (	pg_class		PGNSP PGUID -1 f c C f t \054 1259 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 100 - 199 */
-DATA(insert OID = 142 ( xml		   PGNSP PGUID -1 f b U f t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 142 ( xml		   PGNSP PGUID -1 f b U f t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("XML content");
 #define XMLOID 142
-DATA(insert OID = 143 ( _xml	   PGNSP PGUID -1 f b A f t \054 0 142 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 143 ( _xml	   PGNSP PGUID -1 f b A f t \054 0 142 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 200 - 299 */
 
-DATA(insert OID = 210 (  smgr	   PGNSP PGUID 2 t b U f t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 210 (  smgr	   PGNSP PGUID 2 t b U f t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("storage manager");
 
 /* OIDS 300 - 399 */
@@ -355,231 +369,231 @@ DESCR("storage manager");
 /* OIDS 500 - 599 */
 
 /* OIDS 600 - 699 */
-DATA(insert OID = 600 (  point	   PGNSP PGUID 16 f b G f t \054 0 701 1017 point_in point_out point_recv point_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 600 (  point	   PGNSP PGUID 16 f b G f t \054 0 701 1017 point_in point_out point_recv point_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric point '(x, y)'");
 #define POINTOID		600
-DATA(insert OID = 601 (  lseg	   PGNSP PGUID 32 f b G f t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 601 (  lseg	   PGNSP PGUID 32 f b G f t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric line segment '(pt1,pt2)'");
 #define LSEGOID			601
-DATA(insert OID = 602 (  path	   PGNSP PGUID -1 f b G f t \054 0 0 1019 path_in path_out path_recv path_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 602 (  path	   PGNSP PGUID -1 f b G f t \054 0 0 1019 path_in path_out path_recv path_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric path '(pt1,...)'");
 #define PATHOID			602
-DATA(insert OID = 603 (  box	   PGNSP PGUID 32 f b G f t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 603 (  box	   PGNSP PGUID 32 f b G f t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric box '(lower left,upper right)'");
 #define BOXOID			603
-DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b G f t \054 0	 0 1027 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b G f t \054 0	 0 1027 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric polygon '(pt1,...)'");
 #define POLYGONOID		604
 
-DATA(insert OID = 628 (  line	   PGNSP PGUID 32 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 628 (  line	   PGNSP PGUID 32 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric line (not implemented)");
 #define LINEOID			628
-DATA(insert OID = 629 (  _line	   PGNSP PGUID	-1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 629 (  _line	   PGNSP PGUID	-1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("");
 
 /* OIDS 700 - 799 */
 
-DATA(insert OID = 700 (  float4    PGNSP PGUID	4 FLOAT4PASSBYVAL b N f t \054 0	 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 700 (  float4    PGNSP PGUID	4 FLOAT4PASSBYVAL b N f t \054 0	 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("single-precision floating point number, 4-byte storage");
 #define FLOAT4OID 700
-DATA(insert OID = 701 (  float8    PGNSP PGUID	8 FLOAT8PASSBYVAL b N t t \054 0	 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 701 (  float8    PGNSP PGUID	8 FLOAT8PASSBYVAL b N t t \054 0	 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("double-precision floating point number, 8-byte storage");
 #define FLOAT8OID 701
-DATA(insert OID = 702 (  abstime   PGNSP PGUID	4 t b D f t \054 0	 0 1023 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 702 (  abstime   PGNSP PGUID	4 t b D f t \054 0	 0 1023 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("absolute, limited-range date and time (Unix system time)");
 #define ABSTIMEOID		702
-DATA(insert OID = 703 (  reltime   PGNSP PGUID	4 t b T f t \054 0	 0 1024 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 703 (  reltime   PGNSP PGUID	4 t b T f t \054 0	 0 1024 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("relative, limited-range time interval (Unix delta time)");
 #define RELTIMEOID		703
-DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b T f t \054 0	 0 1025 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b T f t \054 0	 0 1025 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("(abstime,abstime), time interval");
 #define TINTERVALOID	704
-DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b X f t \054 0	 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b X f t \054 0	 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("");
 #define UNKNOWNOID		705
 
-DATA(insert OID = 718 (  circle    PGNSP PGUID	24 f b G f t \054 0 0 719 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 718 (  circle    PGNSP PGUID	24 f b G f t \054 0 0 719 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("geometric circle '(center,radius)'");
 #define CIRCLEOID		718
-DATA(insert OID = 719 (  _circle   PGNSP PGUID	-1 f b A f t \054 0  718 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 790 (  money	   PGNSP PGUID	 8 FLOAT8PASSBYVAL b N f t \054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 719 (  _circle   PGNSP PGUID	-1 f b A f t \054 0  718 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 790 (  money	   PGNSP PGUID	 8 FLOAT8PASSBYVAL b N f t \054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("monetary amounts, $d,ddd.cc");
 #define CASHOID 790
-DATA(insert OID = 791 (  _money    PGNSP PGUID	-1 f b A f t \054 0  790 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 791 (  _money    PGNSP PGUID	-1 f b A f t \054 0  790 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 800 - 899 */
-DATA(insert OID = 829 ( macaddr    PGNSP PGUID	6 f b U f t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 829 ( macaddr    PGNSP PGUID	6 f b U f t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("XX:XX:XX:XX:XX:XX, MAC address");
 #define MACADDROID 829
-DATA(insert OID = 869 ( inet	   PGNSP PGUID	-1 f b I t t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 869 ( inet	   PGNSP PGUID	-1 f b I t t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("IP address/netmask, host address, netmask optional");
 #define INETOID 869
-DATA(insert OID = 650 ( cidr	   PGNSP PGUID	-1 f b I f t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 650 ( cidr	   PGNSP PGUID	-1 f b I f t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("network IP address/netmask, network address");
 #define CIDROID 650
 
 /* OIDS 900 - 999 */
 
 /* OIDS 1000 - 1099 */
-DATA(insert OID = 1000 (  _bool		 PGNSP PGUID -1 f b A f t \054 0	16 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1001 (  _bytea	 PGNSP PGUID -1 f b A f t \054 0	17 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1002 (  _char		 PGNSP PGUID -1 f b A f t \054 0	18 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1003 (  _name		 PGNSP PGUID -1 f b A f t \054 0	19 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1005 (  _int2		 PGNSP PGUID -1 f b A f t \054 0	21 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b A f t \054 0	22 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1007 (  _int4		 PGNSP PGUID -1 f b A f t \054 0	23 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1000 (  _bool		 PGNSP PGUID -1 f b A f t \054 0	16 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1001 (  _bytea	 PGNSP PGUID -1 f b A f t \054 0	17 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1002 (  _char		 PGNSP PGUID -1 f b A f t \054 0	18 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1003 (  _name		 PGNSP PGUID -1 f b A f t \054 0	19 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1005 (  _int2		 PGNSP PGUID -1 f b A f t \054 0	21 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b A f t \054 0	22 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1007 (  _int4		 PGNSP PGUID -1 f b A f t \054 0	23 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 #define INT4ARRAYOID		1007
-DATA(insert OID = 1008 (  _regproc	 PGNSP PGUID -1 f b A f t \054 0	24 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1009 (  _text		 PGNSP PGUID -1 f b A f t \054 0	25 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1008 (  _regproc	 PGNSP PGUID -1 f b A f t \054 0	24 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1009 (  _text		 PGNSP PGUID -1 f b A f t \054 0	25 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 #define TEXTARRAYOID		1009
-DATA(insert OID = 1028 (  _oid		 PGNSP PGUID -1 f b A f t \054 0	26 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1010 (  _tid		 PGNSP PGUID -1 f b A f t \054 0	27 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1011 (  _xid		 PGNSP PGUID -1 f b A f t \054 0	28 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1012 (  _cid		 PGNSP PGUID -1 f b A f t \054 0	29 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b A f t \054 0	30 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1014 (  _bpchar	 PGNSP PGUID -1 f b A f t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1015 (  _varchar	 PGNSP PGUID -1 f b A f t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1016 (  _int8		 PGNSP PGUID -1 f b A f t \054 0	20 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1017 (  _point	 PGNSP PGUID -1 f b A f t \054 0 600 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1018 (  _lseg		 PGNSP PGUID -1 f b A f t \054 0 601 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1019 (  _path		 PGNSP PGUID -1 f b A f t \054 0 602 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1020 (  _box		 PGNSP PGUID -1 f b A f t \073 0 603 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1021 (  _float4	 PGNSP PGUID -1 f b A f t \054 0 700 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1028 (  _oid		 PGNSP PGUID -1 f b A f t \054 0	26 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1010 (  _tid		 PGNSP PGUID -1 f b A f t \054 0	27 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1011 (  _xid		 PGNSP PGUID -1 f b A f t \054 0	28 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1012 (  _cid		 PGNSP PGUID -1 f b A f t \054 0	29 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b A f t \054 0	30 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1014 (  _bpchar	 PGNSP PGUID -1 f b A f t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1015 (  _varchar	 PGNSP PGUID -1 f b A f t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1016 (  _int8		 PGNSP PGUID -1 f b A f t \054 0	20 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1017 (  _point	 PGNSP PGUID -1 f b A f t \054 0 600 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1018 (  _lseg		 PGNSP PGUID -1 f b A f t \054 0 601 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1019 (  _path		 PGNSP PGUID -1 f b A f t \054 0 602 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1020 (  _box		 PGNSP PGUID -1 f b A f t \073 0 603 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1021 (  _float4	 PGNSP PGUID -1 f b A f t \054 0 700 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 #define FLOAT4ARRAYOID 1021
-DATA(insert OID = 1022 (  _float8	 PGNSP PGUID -1 f b A f t \054 0 701 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1023 (  _abstime	 PGNSP PGUID -1 f b A f t \054 0 702 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1024 (  _reltime	 PGNSP PGUID -1 f b A f t \054 0 703 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b A f t \054 0 704 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1027 (  _polygon	 PGNSP PGUID -1 f b A f t \054 0 604 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1033 (  aclitem	 PGNSP PGUID 12 f b U f t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1022 (  _float8	 PGNSP PGUID -1 f b A f t \054 0 701 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1023 (  _abstime	 PGNSP PGUID -1 f b A f t \054 0 702 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1024 (  _reltime	 PGNSP PGUID -1 f b A f t \054 0 703 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b A f t \054 0 704 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1027 (  _polygon	 PGNSP PGUID -1 f b A f t \054 0 604 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1033 (  aclitem	 PGNSP PGUID 12 f b U f t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("access control list");
 #define ACLITEMOID		1033
-DATA(insert OID = 1034 (  _aclitem	 PGNSP PGUID -1 f b A f t \054 0 1033 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1040 (  _macaddr	 PGNSP PGUID -1 f b A f t \054 0  829 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1041 (  _inet		 PGNSP PGUID -1 f b A f t \054 0  869 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 651  (  _cidr		 PGNSP PGUID -1 f b A f t \054 0  650 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1263 (  _cstring	 PGNSP PGUID -1 f b A f t \054 0 2275 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1034 (  _aclitem	 PGNSP PGUID -1 f b A f t \054 0 1033 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1040 (  _macaddr	 PGNSP PGUID -1 f b A f t \054 0  829 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1041 (  _inet		 PGNSP PGUID -1 f b A f t \054 0  869 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 651  (  _cidr		 PGNSP PGUID -1 f b A f t \054 0  650 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1263 (  _cstring	 PGNSP PGUID -1 f b A f t \054 0 2275 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 #define CSTRINGARRAYOID		1263
 
-DATA(insert OID = 1042 ( bpchar		 PGNSP PGUID -1 f b S f t \054 0	0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1042 ( bpchar		 PGNSP PGUID -1 f b S f t \054 0	0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("char(length), blank-padded string, fixed storage length");
 #define BPCHAROID		1042
-DATA(insert OID = 1043 ( varchar	 PGNSP PGUID -1 f b S f t \054 0	0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1043 ( varchar	 PGNSP PGUID -1 f b S f t \054 0	0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("varchar(length), non-blank-padded string, variable storage length");
 #define VARCHAROID		1043
 
-DATA(insert OID = 1082 ( date		 PGNSP PGUID	4 t b D f t \054 0	0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1082 ( date		 PGNSP PGUID	4 t b D f t \054 0	0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("date");
 #define DATEOID			1082
-DATA(insert OID = 1083 ( time		 PGNSP PGUID	8 FLOAT8PASSBYVAL b D f t \054 0	0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1083 ( time		 PGNSP PGUID	8 FLOAT8PASSBYVAL b D f t \054 0	0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("time of day");
 #define TIMEOID			1083
 
 /* OIDS 1100 - 1199 */
-DATA(insert OID = 1114 ( timestamp	 PGNSP PGUID	8 FLOAT8PASSBYVAL b D f t \054 0	0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1114 ( timestamp	 PGNSP PGUID	8 FLOAT8PASSBYVAL b D f t \054 0	0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("date and time");
 #define TIMESTAMPOID	1114
-DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID	-1 f b A f t \054 0 1114 0 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1182 ( _date		 PGNSP PGUID	-1 f b A f t \054 0 1082 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1183 ( _time		 PGNSP PGUID	-1 f b A f t \054 0 1083 0 array_in array_out array_recv array_send timetypmodin timetypmodout - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1184 ( timestamptz PGNSP PGUID	8 FLOAT8PASSBYVAL b D t t \054 0	0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID	-1 f b A f t \054 0 1114 0 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1182 ( _date		 PGNSP PGUID	-1 f b A f t \054 0 1082 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1183 ( _time		 PGNSP PGUID	-1 f b A f t \054 0 1083 0 array_in array_out array_recv array_send timetypmodin timetypmodout - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1184 ( timestamptz PGNSP PGUID	8 FLOAT8PASSBYVAL b D t t \054 0	0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("date and time with time zone");
 #define TIMESTAMPTZOID	1184
-DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b A f t \054 0	1184 0 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1186 ( interval	 PGNSP PGUID 16 f b T t t \054 0	0 1187 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b A f t \054 0	1184 0 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout - d x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1186 ( interval	 PGNSP PGUID 16 f b T t t \054 0	0 1187 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("@ <number> <units>, time interval");
 #define INTERVALOID		1186
-DATA(insert OID = 1187 ( _interval	 PGNSP PGUID	-1 f b A f t \054 0 1186 0 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1187 ( _interval	 PGNSP PGUID	-1 f b A f t \054 0 1186 0 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout - d x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 1200 - 1299 */
-DATA(insert OID = 1231 (  _numeric	 PGNSP PGUID -1 f b A f t \054 0	1700 0 array_in array_out array_recv array_send numerictypmodin numerictypmodout - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1266 ( timetz		 PGNSP PGUID 12 f b D f t \054 0	0 1270 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1231 (  _numeric	 PGNSP PGUID -1 f b A f t \054 0	1700 0 array_in array_out array_recv array_send numerictypmodin numerictypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1266 ( timetz		 PGNSP PGUID 12 f b D f t \054 0	0 1270 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("time of day with time zone");
 #define TIMETZOID		1266
-DATA(insert OID = 1270 ( _timetz	 PGNSP PGUID -1 f b A f t \054 0	1266 0 array_in array_out array_recv array_send timetztypmodin timetztypmodout - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1270 ( _timetz	 PGNSP PGUID -1 f b A f t \054 0	1266 0 array_in array_out array_recv array_send timetztypmodin timetztypmodout - d x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 1500 - 1599 */
-DATA(insert OID = 1560 ( bit		 PGNSP PGUID -1 f b V f t \054 0	0 1561 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1560 ( bit		 PGNSP PGUID -1 f b V f t \054 0	0 1561 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("fixed-length bit string");
 #define BITOID	 1560
-DATA(insert OID = 1561 ( _bit		 PGNSP PGUID -1 f b A f t \054 0	1560 0 array_in array_out array_recv array_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1562 ( varbit		 PGNSP PGUID -1 f b V t t \054 0	0 1563 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1561 ( _bit		 PGNSP PGUID -1 f b A f t \054 0	1560 0 array_in array_out array_recv array_send bittypmodin bittypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 1562 ( varbit		 PGNSP PGUID -1 f b V t t \054 0	0 1563 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("variable-length bit string");
 #define VARBITOID	  1562
-DATA(insert OID = 1563 ( _varbit	 PGNSP PGUID -1 f b A f t \054 0	1562 0 array_in array_out array_recv array_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1563 ( _varbit	 PGNSP PGUID -1 f b A f t \054 0	1562 0 array_in array_out array_recv array_send varbittypmodin varbittypmodout - i x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* OIDS 1600 - 1699 */
 
 /* OIDS 1700 - 1799 */
-DATA(insert OID = 1700 ( numeric	   PGNSP PGUID -1 f b N f t \054 0	0 1231 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1700 ( numeric	   PGNSP PGUID -1 f b N f t \054 0	0 1231 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("numeric(precision, decimal), arbitrary precision number");
 #define NUMERICOID		1700
 
-DATA(insert OID = 1790 ( refcursor	   PGNSP PGUID -1 f b U f t \054 0	0 2201 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1790 ( refcursor	   PGNSP PGUID -1 f b U f t \054 0	0 2201 textin textout textrecv textsend - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("reference to cursor (portal name)");
 #define REFCURSOROID	1790
 
 /* OIDS 2200 - 2299 */
-DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b A f t \054 0 1790 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b A f t \054 0 1790 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 
-DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID	4 t b N f t \054 0	 0 2207 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID	4 t b N f t \054 0	 0 2207 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered procedure (with args)");
 #define REGPROCEDUREOID 2202
 
-DATA(insert OID = 2203 ( regoper	   PGNSP PGUID	4 t b N f t \054 0	 0 2208 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2203 ( regoper	   PGNSP PGUID	4 t b N f t \054 0	 0 2208 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered operator");
 #define REGOPEROID		2203
 
-DATA(insert OID = 2204 ( regoperator   PGNSP PGUID	4 t b N f t \054 0	 0 2209 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2204 ( regoperator   PGNSP PGUID	4 t b N f t \054 0	 0 2209 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered operator (with args)");
 #define REGOPERATOROID	2204
 
-DATA(insert OID = 2205 ( regclass	   PGNSP PGUID	4 t b N f t \054 0	 0 2210 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2205 ( regclass	   PGNSP PGUID	4 t b N f t \054 0	 0 2210 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered class");
 #define REGCLASSOID		2205
 
-DATA(insert OID = 2206 ( regtype	   PGNSP PGUID	4 t b N f t \054 0	 0 2211 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2206 ( regtype	   PGNSP PGUID	4 t b N f t \054 0	 0 2211 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered type");
 #define REGTYPEOID		2206
 
-DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 2208 ( _regoper	   PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 2210 ( _regclass	   PGNSP PGUID -1 f b A f t \054 0 2205 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 2211 ( _regtype	   PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 2208 ( _regoper	   PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 2210 ( _regclass	   PGNSP PGUID -1 f b A f t \054 0 2205 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 2211 ( _regtype	   PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 #define REGTYPEARRAYOID 2211
 
 /* uuid */
-DATA(insert OID = 2950 ( uuid			PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2950 ( uuid			PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("UUID datatype");
-DATA(insert OID = 2951 ( _uuid			PGNSP PGUID -1 f b A f t \054 0 2950 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2951 ( _uuid			PGNSP PGUID -1 f b A f t \054 0 2950 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 
 /* text search */
-DATA(insert OID = 3614 ( tsvector		PGNSP PGUID -1 f b U f t \054 0 0 3643 tsvectorin tsvectorout tsvectorrecv tsvectorsend - - ts_typanalyze i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3614 ( tsvector		PGNSP PGUID -1 f b U f t \054 0 0 3643 tsvectorin tsvectorout tsvectorrecv tsvectorsend - - ts_typanalyze i x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("text representation for text search");
 #define TSVECTOROID		3614
-DATA(insert OID = 3642 ( gtsvector		PGNSP PGUID -1 f b U f t \054 0 0 3644 gtsvectorin gtsvectorout - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3642 ( gtsvector		PGNSP PGUID -1 f b U f t \054 0 0 3644 gtsvectorin gtsvectorout - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("GiST index internal text representation for text search");
 #define GTSVECTOROID	3642
-DATA(insert OID = 3615 ( tsquery		PGNSP PGUID -1 f b U f t \054 0 0 3645 tsqueryin tsqueryout tsqueryrecv tsquerysend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3615 ( tsquery		PGNSP PGUID -1 f b U f t \054 0 0 3645 tsqueryin tsqueryout tsqueryrecv tsquerysend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("query representation for text search");
 #define TSQUERYOID		3615
-DATA(insert OID = 3734 ( regconfig		PGNSP PGUID 4 t b N f t \054 0 0 3735 regconfigin regconfigout regconfigrecv regconfigsend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3734 ( regconfig		PGNSP PGUID 4 t b N f t \054 0 0 3735 regconfigin regconfigout regconfigrecv regconfigsend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered text search configuration");
 #define REGCONFIGOID	3734
-DATA(insert OID = 3769 ( regdictionary	PGNSP PGUID 4 t b N f t \054 0 0 3770 regdictionaryin regdictionaryout regdictionaryrecv regdictionarysend - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3769 ( regdictionary	PGNSP PGUID 4 t b N f t \054 0 0 3770 regdictionaryin regdictionaryout regdictionaryrecv regdictionarysend - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("registered text search dictionary");
 #define REGDICTIONARYOID	3769
 
-DATA(insert OID = 3643 ( _tsvector		PGNSP PGUID -1 f b A f t \054 0 3614 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 3644 ( _gtsvector		PGNSP PGUID -1 f b A f t \054 0 3642 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 3645 ( _tsquery		PGNSP PGUID -1 f b A f t \054 0 3615 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 3735 ( _regconfig		PGNSP PGUID -1 f b A f t \054 0 3734 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 3770 ( _regdictionary PGNSP PGUID -1 f b A f t \054 0 3769 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3643 ( _tsvector		PGNSP PGUID -1 f b A f t \054 0 3614 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 3644 ( _gtsvector		PGNSP PGUID -1 f b A f t \054 0 3642 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 3645 ( _tsquery		PGNSP PGUID -1 f b A f t \054 0 3615 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 3735 ( _regconfig		PGNSP PGUID -1 f b A f t \054 0 3734 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
+DATA(insert OID = 3770 ( _regdictionary PGNSP PGUID -1 f b A f t \054 0 3769 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
 
-DATA(insert OID = 2970 ( txid_snapshot	PGNSP PGUID -1 f b U f t \054 0 0 2949 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2970 ( txid_snapshot	PGNSP PGUID -1 f b U f t \054 0 0 2949 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 DESCR("txid snapshot");
-DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 
 /*
  * pseudo-types
@@ -594,31 +608,31 @@ DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 a
  * but there is now support for it in records and arrays.  Perhaps we should
  * just treat it as a regular base type?
  */
-DATA(insert OID = 2249 ( record			PGNSP PGUID -1 f p P f t \054 0 0 2287 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2249 ( record			PGNSP PGUID -1 f p P f t \054 0 0 2287 record_in record_out record_recv record_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 #define RECORDOID		2249
-DATA(insert OID = 2287 ( _record		PGNSP PGUID -1 f p P f t \054 0 2249 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2287 ( _record		PGNSP PGUID -1 f p P f t \054 0 2249 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 #define RECORDARRAYOID	2287
-DATA(insert OID = 2275 ( cstring		PGNSP PGUID -2 f p P f t \054 0 0 1263 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2275 ( cstring		PGNSP PGUID -2 f p P f t \054 0 0 1263 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 -1 f _null_ _null_ ));
 #define CSTRINGOID		2275
-DATA(insert OID = 2276 ( any			PGNSP PGUID  4 t p P f t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2276 ( any			PGNSP PGUID  4 t p P f t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define ANYOID			2276
-DATA(insert OID = 2277 ( anyarray		PGNSP PGUID -1 f p P f t \054 0 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2277 ( anyarray		PGNSP PGUID -1 f p P f t \054 0 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 -1 f _null_ _null_ ));
 #define ANYARRAYOID		2277
-DATA(insert OID = 2278 ( void			PGNSP PGUID  4 t p P f t \054 0 0 0 void_in void_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2278 ( void			PGNSP PGUID  4 t p P f t \054 0 0 0 void_in void_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define VOIDOID			2278
-DATA(insert OID = 2279 ( trigger		PGNSP PGUID  4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2279 ( trigger		PGNSP PGUID  4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define TRIGGEROID		2279
-DATA(insert OID = 2280 ( language_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2280 ( language_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define LANGUAGE_HANDLEROID		2280
-DATA(insert OID = 2281 ( internal		PGNSP PGUID  SIZEOF_POINTER t p P f t \054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2281 ( internal		PGNSP PGUID  SIZEOF_POINTER t p P f t \054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 -1 f _null_ _null_ ));
 #define INTERNALOID		2281
-DATA(insert OID = 2282 ( opaque			PGNSP PGUID  4 t p P f t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2282 ( opaque			PGNSP PGUID  4 t p P f t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define OPAQUEOID		2282
-DATA(insert OID = 2283 ( anyelement		PGNSP PGUID  4 t p P f t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2283 ( anyelement		PGNSP PGUID  4 t p P f t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define ANYELEMENTOID	2283
-DATA(insert OID = 2776 ( anynonarray	PGNSP PGUID  4 t p P f t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2776 ( anynonarray	PGNSP PGUID  4 t p P f t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define ANYNONARRAYOID	2776
-DATA(insert OID = 3500 ( anyenum		PGNSP PGUID  4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 3500 ( anyenum		PGNSP PGUID  4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 -1 f _null_ _null_ ));
 #define ANYENUMOID		3500
 
 
diff --git a/src/include/catalog/pg_type_fn.h b/src/include/catalog/pg_type_fn.h
index e5b5a96..1769af1 100644
--- a/src/include/catalog/pg_type_fn.h
+++ b/src/include/catalog/pg_type_fn.h
@@ -50,7 +50,9 @@ extern Oid TypeCreate(Oid newTypeOid,
 		   char storage,
 		   int32 typeMod,
 		   int32 typNDims,
-		   bool typeNotNull);
+    	   bool typeNotNull,
+		   int32 typeNLabels,
+		   bool typeSorted);
 
 extern void GenerateTypeDependencies(Oid typeNamespace,
 						 Oid typeObjectId,
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 809143c..fb890b8 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -24,6 +24,7 @@ extern void RemoveTypes(DropStmt *drop);
 extern void RemoveTypeById(Oid typeOid);
 extern void DefineDomain(CreateDomainStmt *stmt);
 extern void DefineEnum(CreateEnumStmt *stmt);
+extern void AlterEnum (AlterEnumStmt *stmt);
 extern Oid	DefineCompositeType(const RangeVar *typevar, List *coldeflist);
 extern Oid	AssignTypeArrayOid(void);
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index ebec0eb..b61938c 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -346,6 +346,7 @@ typedef enum NodeTag
 	T_AlterUserMappingStmt,
 	T_DropUserMappingStmt,
 	T_AlterTableSpaceOptionsStmt,
+	T_AlterEnumStmt,
 
 	/*
 	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ce3da66..d06dfb8 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2171,6 +2171,20 @@ typedef struct CreateEnumStmt
 
 
 /* ----------------------
+ *		Alter Type Statement, enum types
+ * ----------------------
+ */
+typedef struct AlterEnumStmt
+{
+	NodeTag		type;
+	List	   *typeName;		/* qualified name (list of Value strings) */
+	char	   *newVal;			/* new enum value */
+	char	   *newValNeighbour;/* neighbouring enum value */
+	bool	    newValIsAfter;	/* new enum value is after neighbour? */
+} AlterEnumStmt;
+
+
+/* ----------------------
  *		Create View Statement
  * ----------------------
  */
diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out
index 56240c0..ae595af 100644
--- a/src/test/regress/expected/enum.out
+++ b/src/test/regress/expected/enum.out
@@ -25,6 +25,84 @@ ERROR:  invalid input value for enum rainbow: "mauve"
 LINE 1: SELECT 'mauve'::rainbow;
                ^
 --
+-- adding new values
+--
+CREATE TYPE planets AS ENUM ( 'venus', 'earth', 'mars' );
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+ enumlabel | enumsortorder 
+-----------+---------------
+ venus     |             1
+ earth     |             2
+ mars      |             3
+(3 rows)
+
+ALTER TYPE planets ADD 'uranus';
+SELECT typnlabels, typsorted
+FROM pg_type
+WHERE oid = 'planets'::regtype;
+ typnlabels | typsorted 
+------------+-----------
+          4 | t
+(1 row)
+
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+ enumlabel | enumsortorder 
+-----------+---------------
+ venus     |             1
+ earth     |             2
+ mars      |             3
+ uranus    |             4
+(4 rows)
+
+ALTER TYPE planets ADD 'mercury' BEFORE 'venus';
+ALTER TYPE planets ADD 'saturn' BEFORE 'uranus';
+ALTER TYPE planets ADD 'jupiter' AFTER 'mars';
+ALTER TYPE planets ADD 'neptune' AFTER 'uranus';
+SELECT typnlabels, typsorted
+FROM pg_type
+WHERE oid = 'planets'::regtype;
+ typnlabels | typsorted 
+------------+-----------
+          8 | f
+(1 row)
+
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+ enumlabel | enumsortorder 
+-----------+---------------
+ mercury   |             1
+ venus     |             2
+ earth     |             3
+ mars      |             4
+ jupiter   |             5
+ saturn    |             6
+ uranus    |             7
+ neptune   |             8
+(8 rows)
+
+select 'mars'::planets > 'mercury' as using_sortorder;
+ using_sortorder 
+-----------------
+ t
+(1 row)
+
+-- errors for adding labels 
+ALTER TYPE planets ADD 
+	  'plutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutopluto';
+ERROR:  invalid enum label "plutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutopluto"
+DETAIL:  Labels must be 63 characters or less.
+ALTER TYPE planets ADD 'pluto' AFTER 'zeus';
+ERROR:  "zeus" is not an existing label.
+DROP TYPE planets;
+--
 -- Basic table creation, row selection
 --
 CREATE TABLE enumtest (col rainbow);
@@ -403,7 +481,7 @@ SELECT COUNT(*) FROM pg_type WHERE typname = 'rainbow';
 
 SELECT * FROM pg_enum WHERE NOT EXISTS
   (SELECT 1 FROM pg_type WHERE pg_type.oid = enumtypid);
- enumtypid | enumlabel 
------------+-----------
+ enumtypid | enumlabel | enumsortorder 
+-----------+-----------+---------------
 (0 rows)
 
diff --git a/src/test/regress/sql/enum.sql b/src/test/regress/sql/enum.sql
index 387e8e7..0e240b2 100644
--- a/src/test/regress/sql/enum.sql
+++ b/src/test/regress/sql/enum.sql
@@ -16,6 +16,54 @@ SELECT 'red'::rainbow;
 SELECT 'mauve'::rainbow;
 
 --
+-- adding new values
+--
+
+CREATE TYPE planets AS ENUM ( 'venus', 'earth', 'mars' );
+
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+
+ALTER TYPE planets ADD 'uranus';
+
+SELECT typnlabels, typsorted
+FROM pg_type
+WHERE oid = 'planets'::regtype;
+
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+
+ALTER TYPE planets ADD 'mercury' BEFORE 'venus';
+
+ALTER TYPE planets ADD 'saturn' BEFORE 'uranus';
+
+ALTER TYPE planets ADD 'jupiter' AFTER 'mars';
+
+ALTER TYPE planets ADD 'neptune' AFTER 'uranus';
+
+SELECT typnlabels, typsorted
+FROM pg_type
+WHERE oid = 'planets'::regtype;
+
+SELECT enumlabel, enumsortorder 
+FROM pg_enum 
+WHERE enumtypid = 'planets'::regtype
+ORDER by 2;
+
+select 'mars'::planets > 'mercury' as using_sortorder;
+
+-- errors for adding labels 
+ALTER TYPE planets ADD 
+	  'plutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutoplutopluto';
+
+ALTER TYPE planets ADD 'pluto' AFTER 'zeus';
+
+DROP TYPE planets;
+--
 -- Basic table creation, row selection
 --
 CREATE TABLE enumtest (col rainbow);