*** a/contrib/pg_upgrade/function.c
--- b/contrib/pg_upgrade/function.c
***************
*** 61,85 **** install_support_functions(migratorContext *ctx)
  								  "LANGUAGE C STRICT;"));
  		PQclear(executeQueryOrDie(ctx, conn,
  								  "CREATE OR REPLACE FUNCTION "
! 				"		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_toast_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) "
  								  "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) "
  								  "RETURNS VOID "
  								  "AS '$libdir/pg_upgrade_support' "
  								  "LANGUAGE C STRICT;"));
--- 61,85 ----
  								  "LANGUAGE C STRICT;"));
  		PQclear(executeQueryOrDie(ctx, conn,
  								  "CREATE OR REPLACE FUNCTION "
! 					 "		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_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_toast_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) "
  								  "RETURNS VOID "
  								  "AS '$libdir/pg_upgrade_support' "
  								  "LANGUAGE C STRICT;"));
*** a/contrib/pg_upgrade_support/pg_upgrade_support.c
--- b/contrib/pg_upgrade_support/pg_upgrade_support.c
***************
*** 30,35 **** PG_MODULE_MAGIC;
--- 30,36 ----
  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;
***************
*** 37,54 **** 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_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_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)
--- 38,55 ----
  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);
  
  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);
  
  Datum
  set_next_pg_type_oid(PG_FUNCTION_ARGS)
***************
*** 81,86 **** set_next_pg_type_toast_oid(PG_FUNCTION_ARGS)
--- 82,97 ----
  }
  
  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);
***************
*** 110,124 **** 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();
- }
--- 121,123 ----
*** a/doc/src/sgml/ref/alter_type.sgml
--- b/doc/src/sgml/ref/alter_type.sgml
***************
*** 23,33 **** PostgreSQL documentation
  
   <refsynopsisdiv>
  <synopsis>
! ALTER TYPE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</replaceable> [, ... ]
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable> 
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> TO <replaceable class="PARAMETER">new_attribute_name</replaceable>
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
  
  <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
  
--- 23,34 ----
  
   <refsynopsisdiv>
  <synopsis>
! ALTER TYPE  <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</replaceable> [, ... ]
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable> 
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> TO <replaceable class="PARAMETER">new_attribute_name</replaceable>
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
  ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
+ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD <replaceable class="PARAMETER">new_enum_value</replaceable> [ BEFORE | AFTER <replaceable class="PARAMETER">existing_enum_value</replaceable>  
  
  <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
  
***************
*** 103,108 **** ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replace
--- 104,131 ----
       </para>
      </listitem>
     </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>ADD [ BEFORE | AFTER ]</literal></term>
+     <listitem>
+      <para>
+       This form adds a new value to an enum type. If the new value's place
+ 	  in the sort order is not set using <literal>BEFORE</literal> or 
+ 	  <literal>AFTER</literal>, then the new item is placed at the end of
+ 	  the list of values.
+      </para>
+ 	 <note>
+ 	  <para>
+ 	   Adding a new enum value will in some cases lower the comparison and 
+ 	   sorting performance of the enum type. This will only usually occur if  
+ 	   <literal>BEFORE</literal> or <literal>AFTER</literal> are used to set 
+ 	   the new value's sort order position somewhere other than at the end 
+ 	   of the list. Optimal performance will be restored if the database is 
+ 	   dumped and reloaded.
+ 	  </para>
+ 	 </note>
+     </listitem>
+    </varlistentry>
    </variablelist>
    </para>
  
***************
*** 196,201 **** ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replace
--- 219,254 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry>
+       <term><replaceable class="PARAMETER">data_type</replaceable></term>
+       <listitem>
+        <para>
+         The data type of the attribute to add, or the new type of the
+         attribute to alter.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><replaceable class="PARAMETER">new_enum_value</replaceable></term>
+       <listitem>
+        <para>
+         The new value to be added to the num type's list of values. Like all
+ 		enum literals it needs to be quoted.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><replaceable class="PARAMETER">exisiting_enum_value</replaceable></term>
+       <listitem>
+        <para>
+         The neighbour of the new value to be added to the num type's list of values. Like all
+ 		enum literals it needs to be quoted.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
      </variablelist>
     </para>
    </refsect1>
***************
*** 232,237 **** ALTER TYPE email SET SCHEMA customers;
--- 285,297 ----
  ALTER TYPE compfoo ADD ATTRIBUTE f3 int;
  </programlisting>
    </para>
+ 
+   <para>
+    To add a new value to an enum type in a particular sort position:
+ <programlisting>
+ ALTER TYPE colors ADD 'orange' AFTER 'red';
+ </programlisting>
+   </para>
   </refsect1>
  
   <refsect1>
*** a/src/backend/catalog/heap.c
--- b/src/backend/catalog/heap.c
***************
*** 855,861 **** AddNewRelationType(const char *typeName,
  				   'x',			/* fully TOASTable */
  				   -1,			/* typmod */
  				   0,			/* array dimensions for typBaseType */
! 				   false);		/* Type NOT NULL */
  }
  
  /* --------------------------------
--- 855,863 ----
  				   'x',			/* fully TOASTable */
  				   -1,			/* typmod */
  				   0,			/* array dimensions for typBaseType */
! 				   false,		/* Type NOT NULL */
! 				   -1,          /* no enum labels */
! 				   false);      /* type is not an enum, so not sorted */
  }
  
  /* --------------------------------
***************
*** 1108,1114 **** heap_create_with_catalog(const char *relname,
  				   'x',			/* fully TOASTable */
  				   -1,			/* typmod */
  				   0,			/* array dimensions for typBaseType */
! 				   false);		/* Type NOT NULL */
  
  		pfree(relarrayname);
  	}
--- 1110,1118 ----
  				   'x',			/* fully TOASTable */
  				   -1,			/* typmod */
  				   0,			/* array dimensions for typBaseType */
! 				   false,		/* Type NOT NULL */
! 				   -1,          /* no enum labels */
! 				   false);      /* type is not an enum, so not sorted */
  
  		pfree(relarrayname);
  	}
*** a/src/backend/catalog/pg_enum.c
--- b/src/backend/catalog/pg_enum.c
***************
*** 18,29 ****
--- 18,219 ----
  #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,40 **** 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)
  {
  	Relation	pg_enum;
  	TupleDesc	tupDesc;
--- 223,229 ----
   * vals is a list of Value strings.
   */
  void
! EnumValuesCreate(Oid enumTypeOid, List *vals)
  {
  	Relation	pg_enum;
  	TupleDesc	tupDesc;
***************
*** 50,58 **** EnumValuesCreate(Oid enumTypeOid, List *vals,
  	num_elems = list_length(vals);
  
  	/*
! 	 * XXX 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?
  	 */
  
  	pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
--- 239,247 ----
  	num_elems = list_length(vals);
  
  	/*
! 	 * 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.
! 	 * It is probably not worth trying harder.
  	 */
  
  	pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
***************
*** 62,96 **** 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++)
! 		{
! 			/*
! 			 * The pg_enum.oid is stored in user tables.  This oid must be
! 			 * preserved by binary upgrades.
! 			 */
! 			oids[elemno] = GetNewOid(pg_enum);
! 		}
! 		/* sort them, just in case counter wrapped from high to low */
! 		qsort(oids, num_elems, sizeof(Oid), oid_cmp);
  	}
  
  	/* and make the entries */
  	memset(nulls, false, sizeof(nulls));
--- 251,274 ----
  	 * Allocate oids
  	 */
  	oids = (Oid *) palloc(num_elems * sizeof(Oid));
! 
! 	/*
! 	 * While this method does not absolutely guarantee that we generate no
! 	 * duplicate oids (since we haven't entered each oid into the table
! 	 * before allocating the next), trouble could only occur if the oid
! 	 * counter wraps all the way around before we finish. Which seems
! 	 * unlikely.
! 	 */
! 	for (elemno = 0; elemno < num_elems; elemno++)
  	{
  		/*
! 		 * The pg_enum.oid is stored in user tables.  This oid must be
! 		 * preserved by binary upgrades.
  		 */
! 		oids[elemno] = GetNewOid(pg_enum);
  	}
+ 	/* sort them, just in case counter wrapped from high to low */
+ 	qsort(oids, num_elems, sizeof(Oid), oid_cmp);
  
  	/* and make the entries */
  	memset(nulls, false, sizeof(nulls));
***************
*** 114,119 **** EnumValuesCreate(Oid enumTypeOid, List *vals,
--- 292,298 ----
  		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,170 **** EnumValuesDelete(Oid enumTypeOid)
  }
  
  
! /* qsort comparison function */
  static int
  oid_cmp(const void *p1, const void *p2)
  {
--- 343,349 ----
  }
  
  
! /* qsort comparison for oids */
  static int
  oid_cmp(const void *p1, const void *p2)
  {
***************
*** 177,179 **** oid_cmp(const void *p1, const void *p2)
--- 356,371 ----
  		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;
+ }
+ 
*** a/src/backend/catalog/pg_type.c
--- b/src/backend/catalog/pg_type.c
***************
*** 112,117 **** TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
--- 112,119 ----
  	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,210 **** TypeCreate(Oid newTypeOid,
  		   char storage,
  		   int32 typeMod,
  		   int32 typNDims,		/* Array dimensions for baseType */
! 		   bool typeNotNull)
  {
  	Relation	pg_type_desc;
  	Oid			typeObjectId;
--- 206,214 ----
  		   char storage,
  		   int32 typeMod,
  		   int32 typNDims,		/* Array dimensions for baseType */
! 		   bool typeNotNull,
! 		   int32 typeNLabels,
! 		   bool typeSorted)
  {
  	Relation	pg_type_desc;
  	Oid			typeObjectId;
***************
*** 342,347 **** TypeCreate(Oid newTypeOid,
--- 346,353 ----
  	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
*** a/src/backend/commands/typecmds.c
--- b/src/backend/commands/typecmds.c
***************
*** 85,96 **** 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 char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
  					Oid baseTypeOid,
  					int typMod, Constraint *constr,
  					char *domainName);
- 
- 
  /*
   * DefineType
   *		Registers a new base type.
--- 85,95 ----
  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,569 **** DefineType(List *names, List *parameters)
  				   storage,		/* TOAST strategy */
  				   -1,			/* typMod (Domains only) */
  				   0,			/* Array Dimensions of typbasetype */
! 				   false);		/* Type NOT NULL */
! 
  	/*
  	 * Create the array type that goes with it.
  	 */
--- 561,569 ----
  				   storage,		/* TOAST strategy */
  				   -1,			/* typMod (Domains only) */
  				   0,			/* Array Dimensions of typbasetype */
! 				   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,607 **** DefineType(List *names, List *parameters)
  			   'x',				/* ARRAY is always toastable */
  			   -1,				/* typMod (Domains only) */
  			   0,				/* Array dimensions of typbasetype */
! 			   false);			/* Type NOT NULL */
  
  	pfree(array_type);
  }
--- 601,609 ----
  			   'x',				/* ARRAY is always toastable */
  			   -1,				/* typMod (Domains only) */
  			   0,				/* Array dimensions of typbasetype */
! 			   false,			/* Type NOT NULL */
! 			   -1,              /* no enum labels */
! 			   false);          /* type is not an enum, so not sorted */
  
  	pfree(array_type);
  }
***************
*** 1044,1050 **** DefineDomain(CreateDomainStmt *stmt)
  				   storage,		/* TOAST strategy */
  				   basetypeMod, /* typeMod value */
  				   typNDims,	/* Array dimensions for base type */
! 				   typNotNull); /* Type NOT NULL */
  
  	/*
  	 * Process constraints which refer to the domain ID returned by TypeCreate
--- 1046,1054 ----
  				   storage,		/* TOAST strategy */
  				   basetypeMod, /* typeMod value */
  				   typNDims,	/* Array dimensions for base type */
! 				   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,1099 **** DefineEnum(CreateEnumStmt *stmt)
--- 1098,1106 ----
  	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,1162 **** DefineEnum(CreateEnumStmt *stmt)
  				   'p',			/* TOAST strategy always plain */
  				   -1,			/* typMod (Domains only) */
  				   0,			/* Array dimensions of typbasetype */
! 				   false);		/* Type NOT NULL */
  
  	/* Enter the enum's values into pg_enum */
! 	EnumValuesCreate(enumTypeOid, stmt->vals, InvalidOid);
  
  	/*
  	 * Create the array type that goes with it.
--- 1160,1171 ----
  				   'p',			/* TOAST strategy always plain */
  				   -1,			/* typMod (Domains only) */
  				   0,			/* Array dimensions of typbasetype */
! 				   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);
  
  	/*
  	 * Create the array type that goes with it.
***************
*** 1192,1202 **** DefineEnum(CreateEnumStmt *stmt)
  			   'x',				/* ARRAY is always toastable */
  			   -1,				/* typMod (Domains only) */
  			   0,				/* Array dimensions of typbasetype */
! 			   false);			/* Type NOT NULL */
  
  	pfree(enumArrayName);
  }
  
  
  /*
   * Find suitable I/O functions for a type.
--- 1201,1288 ----
  			   'x',				/* ARRAY is always toastable */
  			   -1,				/* typMod (Domains only) */
  			   0,				/* Array dimensions of typbasetype */
! 			   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.
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 2873,2878 **** _copyCreateEnumStmt(CreateEnumStmt *from)
--- 2873,2891 ----
  	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)
  {
***************
*** 4033,4038 **** copyObject(void *from)
--- 4046,4054 ----
  		case T_CreateEnumStmt:
  			retval = _copyCreateEnumStmt(from);
  			break;
+ 		case T_AlterEnumStmt:
+ 			retval = _copyAlterEnumStmt(from);
+ 			break;
  		case T_ViewStmt:
  			retval = _copyViewStmt(from);
  			break;
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 1390,1395 **** _equalCreateEnumStmt(CreateEnumStmt *a, CreateEnumStmt *b)
--- 1390,1406 ----
  }
  
  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);
***************
*** 2697,2702 **** equal(void *a, void *b)
--- 2708,2716 ----
  		case T_CreateEnumStmt:
  			retval = _equalCreateEnumStmt(a, b);
  			break;
+ 		case T_AlterEnumStmt:
+ 			retval = _equalAlterEnumStmt(a, b);
+ 			break;
  		case T_ViewStmt:
  			retval = _equalViewStmt(a, b);
  			break;
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 182,189 **** static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
  }
  
  %type <node>	stmt schema_stmt
! 		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! 		AlterForeignServerStmt AlterGroupStmt
  		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
  		AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
--- 182,189 ----
  }
  
  %type <node>	stmt schema_stmt
!         AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
!         AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
  		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
  		AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
***************
*** 652,657 **** stmt :
--- 652,658 ----
  			| AlterDatabaseSetStmt
  			| AlterDefaultPrivilegesStmt
  			| AlterDomainStmt
+ 			| AlterEnumStmt
  			| AlterFdwStmt
  			| AlterForeignServerStmt
  			| AlterFunctionStmt
***************
*** 3862,3867 **** enum_val_list:	Sconst
--- 3863,3908 ----
  				{ $$ = 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;
+ 			 }
+ 		 ;
+ 
+ 
  
  /*****************************************************************************
   *
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 190,195 **** check_xact_readonly(Node *parsetree)
--- 190,196 ----
  		case T_CreateTrigStmt:
  		case T_CompositeTypeStmt:
  		case T_CreateEnumStmt:
+ 		case T_AlterEnumStmt:
  		case T_ViewStmt:
  		case T_DropCastStmt:
  		case T_DropStmt:
***************
*** 860,865 **** standard_ProcessUtility(Node *parsetree,
--- 861,870 ----
  			DefineEnum((CreateEnumStmt *) parsetree);
  			break;
  
+ 		case T_AlterEnumStmt:	/* ALTER TYPE (enum) */
+ 			AlterEnum((AlterEnumStmt *) parsetree);
+ 			break;
+ 
  		case T_ViewStmt:		/* CREATE VIEW */
  			DefineView((ViewStmt *) parsetree, queryString);
  			break;
***************
*** 1868,1873 **** CreateCommandTag(Node *parsetree)
--- 1873,1882 ----
  			tag = "CREATE TYPE";
  			break;
  
+ 		case T_AlterEnumStmt:
+ 			tag = "ALTER TYPE";
+ 			break;
+ 
  		case T_ViewStmt:
  			tag = "CREATE VIEW";
  			break;
***************
*** 2410,2415 **** GetCommandLogLevel(Node *parsetree)
--- 2419,2428 ----
  			lev = LOGSTMT_DDL;
  			break;
  
+ 		case T_AlterEnumStmt:
+ 			lev = LOGSTMT_DDL;
+ 			break;
+ 
  		case T_ViewStmt:
  			lev = LOGSTMT_DDL;
  			break;
*** a/src/backend/utils/adt/enum.c
--- b/src/backend/utils/adt/enum.c
***************
*** 14,19 ****
--- 14,20 ----
  #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,30 ****
  #include "libpq/pqformat.h"
  #include "miscadmin.h"
  
  
  static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
! static int	enum_elem_cmp(const void *left, const void *right);
  
  
  /* Basic I/O support */
--- 23,48 ----
  #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_sort_cmp(const void *left, const void *right);
! static int	enum_oid_cmp(const void *left, const void *right);
  
  
  /* Basic I/O support */
***************
*** 155,167 **** enum_send(PG_FUNCTION_ARGS)
  
  /* Comparison functions and related */
  
  Datum
  enum_lt(PG_FUNCTION_ARGS)
  {
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(a < b);
  }
  
  Datum
--- 173,347 ----
  
  /* Comparison functions and related */
  
+ 
+ /* enum_ccmp is the common engine for all the visible comparison functions */
+ 
+ static inline int 
+ enum_ccmp(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
+ {
+ 
+ 	/*
+ 	 * Keep a cache of type information in fcinfo->flinfo->fn_extra.
+ 	 * If the Oids are sorted, that's all the info we need, and
+ 	 * we can just return the difference of arg1 and arg2.
+ 	 * If not, we keep a list of Oid/sortorder pairs in the cache,
+ 	 * and look up the sortorder by Oid, using a binary search,
+ 	 * and return the difference between the sortorders. 
+ 	 *
+ 	 * To keep down the cost of retail comparisons even if
+ 	 * the label set is very large, we start by just putting
+ 	 * Oids we are actually comparing into the cache. If this
+ 	 * grows beyond a handful (10 in fact) it looks like it's a
+ 	 * bulk operation, and so we just fetch the all the labels
+ 	 * and sort them. This keeps down the number of times we
+ 	 * might need to call quicksort.
+ 	 */
+ 
+ 	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;
+ 
+ 	/* 
+ 	 * Fast path return for equal Oids, sorted or not. 
+ 	 * This shouldn't happen, but it's here just in case.
+ 	 */
+ 	if (arg1 == arg2)
+ 		return 0;
+ 
+ 	mycache = (enum_sort_cache *) fcinfo->flinfo->fn_extra;
+ 
+ 	/* Initialize the cache if it's not already there */
+ 	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);
+ 	}
+ 
+ 	/* Fast path return for Oids are sorted case */
+ 	if (mycache->oids_are_sorted)
+ 		return arg1 - arg2;
+ 
+ 	/* Look up the Oids in the cache */
+ 	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);
+ 
+ 	/* Handle cache misses, or get the sort order from the search results */
+ 
+ 	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;
+ 	}
+ 
+ 	/* Sort the cache, and possibly complete it, for the next function call */
+ 	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; 
+ 			}
+ 			mycache->sort_list_length = mycache->label_count;
+ 
+ 			ReleaseCatCacheList(nlist);
+ 		}
+ 
+ 		qsort(mycache->sort_order_list,mycache->sort_list_length,
+ 			  sizeof(enum_sort),enum_oid_cmp);
+ 	}
+ 
+ 	/* and we're done */
+ 	return sort1 - sort2;
+ }
+ 
  Datum
  enum_lt(PG_FUNCTION_ARGS)
  {
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) < 0);
  }
  
  Datum
***************
*** 170,176 **** enum_le(PG_FUNCTION_ARGS)
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(a <= b);
  }
  
  Datum
--- 350,356 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) <= 0);
  }
  
  Datum
***************
*** 197,203 **** enum_ge(PG_FUNCTION_ARGS)
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(a >= b);
  }
  
  Datum
--- 377,383 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) >= 0);
  }
  
  Datum
***************
*** 206,212 **** enum_gt(PG_FUNCTION_ARGS)
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(a > b);
  }
  
  Datum
--- 386,392 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_BOOL(enum_ccmp(a,b,fcinfo) > 0);
  }
  
  Datum
***************
*** 215,221 **** enum_smaller(PG_FUNCTION_ARGS)
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_OID(a <= b ? a : b);
  }
  
  Datum
--- 395,401 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_OID(enum_ccmp(a,b,fcinfo) < 0 ? a : b);
  }
  
  Datum
***************
*** 224,230 **** enum_larger(PG_FUNCTION_ARGS)
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_OID(a >= b ? a : b);
  }
  
  Datum
--- 404,410 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	PG_RETURN_OID(enum_ccmp(a,b,fcinfo) > 0 ? a : b);
  }
  
  Datum
***************
*** 233,242 **** 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)
  		PG_RETURN_INT32(0);
  	else
  		PG_RETURN_INT32(-1);
  }
--- 413,422 ----
  	Oid			a = PG_GETARG_OID(0);
  	Oid			b = PG_GETARG_OID(1);
  
! 	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,253 **** enum_first(PG_FUNCTION_ARGS)
--- 428,434 ----
  {
  	Oid			enumtypoid;
  	Oid			min = InvalidOid;
+ 	int         min_sort = -1; /* value will never in fact be used */
  	CatCList   *list;
  	int			num,
  				i;
***************
*** 267,276 **** 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;
  	}
  
  	ReleaseCatCacheList(list);
--- 448,461 ----
  	num = list->n_members;
  	for (i = 0; i < num; i++)
  	{
! 		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,292 **** enum_last(PG_FUNCTION_ARGS)
--- 472,478 ----
  {
  	Oid			enumtypoid;
  	Oid			max = InvalidOid;
+ 	int         max_sort = -1; /* value will never in fact be used */
  	CatCList   *list;
  	int			num,
  				i;
***************
*** 306,315 **** 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;
  	}
  
  	ReleaseCatCacheList(list);
--- 492,505 ----
  	num = list->n_members;
  	for (i = 0; i < num; i++)
  	{
! 		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,427 **** enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
  				i,
  				j;
  	Datum	   *elems;
  
  	list = SearchSysCacheList1(ENUMTYPOIDNAME, ObjectIdGetDatum(enumtypoid));
  	total = list->n_members;
  
  	elems = (Datum *) palloc(total * sizeof(Datum));
  
- 	j = 0;
  	for (i = 0; i < total; i++)
  	{
! 		Oid			val = HeapTupleGetOid(&(list->members[i]->tuple));
  
- 		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);
  
  	/* note this hardwires some details about the representation of Oid */
  	result = construct_array(elems, j, enumtypoid, sizeof(Oid), true, 'i');
  
  	pfree(elems);
  
  	return result;
  }
  
! /* qsort comparison function for Datums that are OIDs */
  static int
! enum_elem_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;
  }
--- 572,647 ----
  				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));
  
  	for (i = 0; i < total; i++)
  	{
! 		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;
  
  	}
  
  	/* shouldn't need the cache anymore */
  	ReleaseCatCacheList(list);
  
! 	/* 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 using sort order, for range routines 
!  */
  static int
! enum_sort_cmp(const void *left, const void *right)
  {
! 	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;
+ }
+ 
+ 
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 6653,6669 **** dumpEnumType(Archive *fout, TypeInfo *tyinfo)
  	PQExpBuffer query = createPQExpBuffer();
  	PGresult   *res;
  	int			num,
! 				i;
  	Oid			enum_oid;
  	char	   *label;
  
  	/* Set proper schema search path so regproc references list correctly */
  	selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
  
! 	appendPQExpBuffer(query, "SELECT oid, enumlabel "
! 					  "FROM pg_catalog.pg_enum "
! 					  "WHERE enumtypid = '%u'"
! 					  "ORDER BY oid",
  					  tyinfo->dobj.catId.oid);
  
  	res = PQexec(g_conn, query->data);
--- 6653,6676 ----
  	PQExpBuffer query = createPQExpBuffer();
  	PGresult   *res;
  	int			num,
! 		        i;
  	Oid			enum_oid;
  	char	   *label;
  
  	/* Set proper schema search path so regproc references list correctly */
  	selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
  
!     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);
***************
*** 6709,6725 **** 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");
  		}
- 		appendPQExpBuffer(q, "\n");
  	}
  
  	ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
--- 6716,6734 ----
  		{
  			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.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");
  		}
  	}
  
  	ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
***************
*** 473,489 **** describeTypes(const char *pattern, bool verbose, bool showSystem)
  						  gettext_noop("Internal name"),
  						  gettext_noop("Size"));
  	if (verbose && pset.sversion >= 80300)
  		appendPQExpBuffer(&buf,
  						  "  pg_catalog.array_to_string(\n"
  						  "      ARRAY(\n"
  						  "		     SELECT e.enumlabel\n"
  						  "          FROM pg_catalog.pg_enum e\n"
! 						  "          WHERE e.enumtypid = t.oid\n"
! 						  "          ORDER BY e.oid\n"
  						  "      ),\n"
  						  "      E'\\n'\n"
  						  "  ) AS \"%s\",\n",
  						  gettext_noop("Elements"));
  
  	appendPQExpBuffer(&buf,
  				"  pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
--- 473,499 ----
  						  gettext_noop("Internal name"),
  						  gettext_noop("Size"));
  	if (verbose && pset.sversion >= 80300)
+ 	{
  		appendPQExpBuffer(&buf,
  						  "  pg_catalog.array_to_string(\n"
  						  "      ARRAY(\n"
  						  "		     SELECT e.enumlabel\n"
  						  "          FROM pg_catalog.pg_enum e\n"
! 						  "          WHERE e.enumtypid = t.oid\n");
! 
! 		if (pset.sversion >= 90100 )
! 			appendPQExpBuffer(&buf,
! 							  "          ORDER BY e.enumsortorder\n");
! 		else
! 			appendPQExpBuffer(&buf,
! 							  "          ORDER BY e.oid\n");
! 
! 		appendPQExpBuffer(&buf,
  						  "      ),\n"
  						  "      E'\\n'\n"
  						  "  ) AS \"%s\",\n",
  						  gettext_noop("Elements"));
+ 	}
  
  	appendPQExpBuffer(&buf,
  				"  pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
***************
*** 147,152 **** DECLARE_UNIQUE_INDEX(pg_enum_oid_index, 3502, on pg_enum using btree(oid oid_ops
--- 147,154 ----
  #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));
*** a/src/include/catalog/pg_class.h
--- b/src/include/catalog/pg_class.h
***************
*** 132,138 **** 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_ ));
  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("");
--- 132,138 ----
   */
  
  /* 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 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("");
*** a/src/include/catalog/pg_enum.h
--- b/src/include/catalog/pg_enum.h
***************
*** 35,40 **** CATALOG(pg_enum,3501)
--- 35,41 ----
  {
  	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,56 **** typedef FormData_pg_enum *Form_pg_enum;
   *		compiler constants for pg_enum
   * ----------------
   */
! #define Natts_pg_enum					2
  #define Anum_pg_enum_enumtypid			1
  #define Anum_pg_enum_enumlabel			2
  
  /* ----------------
   *		pg_enum has no initial contents
--- 49,58 ----
   *		compiler constants for pg_enum
   * ----------------
   */
! #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,67 **** 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 EnumValuesDelete(Oid enumTypeOid);
  
  #endif   /* PG_ENUM_H */
--- 62,70 ----
  /*
   * prototypes for functions in pg_enum.c
   */
! 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 */
*** a/src/include/catalog/pg_type.h
--- b/src/include/catalog/pg_type.h
***************
*** 194,199 **** CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
--- 194,211 ----
  	 */
  	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,230 **** typedef FormData_pg_type *Form_pg_type;
   *		compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type					28
  #define Anum_pg_type_typname			1
  #define Anum_pg_type_typnamespace		2
  #define Anum_pg_type_typowner			3
--- 236,242 ----
   *		compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type					30
  #define Anum_pg_type_typname			1
  #define Anum_pg_type_typnamespace		2
  #define Anum_pg_type_typowner			3
***************
*** 251,258 **** 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
  
  
  /* ----------------
--- 263,272 ----
  #define Anum_pg_type_typbasetype		24
  #define Anum_pg_type_typtypmod			25
  #define Anum_pg_type_typndims			26
! #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,355 **** 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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  
  /* 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_ ));
  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 = 194 (	pg_node_tree	PGNSP PGUID -1 f b S f t \054 0	0 0 pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send - - - i x f 0 -1 0 _null_ _null_ ));
  DESCR("string representing an internal node tree");
  #define PGNODETREEOID	194
  
  /* 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_ ));
  DESCR("storage manager");
  
  /* OIDS 300 - 399 */
--- 283,369 ----
   */
  
  /* 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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -1 f _null_ _null_ ));
  
! DATA(insert OID = 194 (	pg_node_tree	PGNSP PGUID -1 f b S f t \054 0	0 0 pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send - - - i x f 0 -1 0 -1 f _null_ _null_ ));
  DESCR("string representing an internal node tree");
  #define PGNODETREEOID	194
  
  /* 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 -1 f _null_ _null_ ));
  DESCR("storage manager");
  
  /* OIDS 300 - 399 */
***************
*** 359,589 **** 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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  
  /* 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_ ));
  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_ ));
  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_ ));
  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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  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_ ));
  #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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  
  /* 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_ ));
  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_ ));
  
  /* 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_ ));
  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_ ));
  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_ ));
  
  /* 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_ ));
  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_ ));
  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 = 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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  #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_ ));
  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_ ));
  
  /* 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_ ));
  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_ ));
  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_ ));
  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_ ));
  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_ ));
  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 = 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_ ));
  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_ ));
  
  /*
   * pseudo-types
--- 373,603 ----
  /* 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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -1 f _null_ _null_ ));
  
  /*
   * pseudo-types
***************
*** 598,628 **** 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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #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_ ));
  #define ANYENUMOID		3500
  
  
--- 612,642 ----
   * 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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -1 f _null_ _null_ ));
  #define ANYENUMOID		3500
  
  
*** a/src/include/catalog/pg_type_fn.h
--- b/src/include/catalog/pg_type_fn.h
***************
*** 50,56 **** extern Oid TypeCreate(Oid newTypeOid,
  		   char storage,
  		   int32 typeMod,
  		   int32 typNDims,
! 		   bool typeNotNull);
  
  extern void GenerateTypeDependencies(Oid typeNamespace,
  						 Oid typeObjectId,
--- 50,58 ----
  		   char storage,
  		   int32 typeMod,
  		   int32 typNDims,
!     	   bool typeNotNull,
! 		   int32 typeNLabels,
! 		   bool typeSorted);
  
  extern void GenerateTypeDependencies(Oid typeNamespace,
  						 Oid typeObjectId,
*** a/src/include/commands/typecmds.h
--- b/src/include/commands/typecmds.h
***************
*** 24,29 **** extern void RemoveTypes(DropStmt *drop);
--- 24,30 ----
  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);
  
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
***************
*** 348,354 **** typedef enum NodeTag
  	T_DropUserMappingStmt,
  	T_AlterTableSpaceOptionsStmt,
  	T_SecLabelStmt,
! 
  	/*
  	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
  	 */
--- 348,354 ----
  	T_DropUserMappingStmt,
  	T_AlterTableSpaceOptionsStmt,
  	T_SecLabelStmt,
! 	T_AlterEnumStmt,
  	/*
  	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
  	 */
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2192,2197 **** typedef struct CreateEnumStmt
--- 2192,2211 ----
  
  
  /* ----------------------
+  *		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
   * ----------------------
   */
*** a/src/test/regress/expected/enum.out
--- b/src/test/regress/expected/enum.out
***************
*** 25,30 **** ERROR:  invalid input value for enum rainbow: "mauve"
--- 25,108 ----
  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,409 **** 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 
! -----------+-----------
  (0 rows)
  
--- 481,487 ----
  
  SELECT * FROM pg_enum WHERE NOT EXISTS
    (SELECT 1 FROM pg_type WHERE pg_type.oid = enumtypid);
!  enumtypid | enumlabel | enumsortorder 
! -----------+-----------+---------------
  (0 rows)
  
*** a/src/test/regress/sql/enum.sql
--- b/src/test/regress/sql/enum.sql
***************
*** 16,21 **** SELECT 'red'::rainbow;
--- 16,69 ----
  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);
