diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index c70f23f..7dc1656 100644
*** a/contrib/pg_upgrade/function.c
--- b/contrib/pg_upgrade/function.c
*************** install_support_functions(migratorContex
*** 61,85 ****
"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;"));
diff --git a/contrib/pg_upgrade_support/pg_upgrade_support.c b/contrib/pg_upgrade_support/pg_upgrade_support.c
index c956be1..24f5e59 100644
*** a/contrib/pg_upgrade_support/pg_upgrade_support.c
--- b/contrib/pg_upgrade_support/pg_upgrade_support.c
*************** PG_MODULE_MAGIC;
*** 30,35 ****
--- 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;
*************** extern PGDLLIMPORT Oid binary_upgrade_ne
*** 37,54 ****
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)
*************** set_next_pg_type_toast_oid(PG_FUNCTION_A
*** 81,86 ****
--- 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);
*************** set_next_index_relfilenode(PG_FUNCTION_A
*** 110,124 ****
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 ----
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index c37b995..0db463e 100644
*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 2626,2634 ****
matching enum types to their associated values and labels. The
internal representation of a given enum value is actually the OID
of its associated row in pg_enum. The
! OIDs for a particular enum type are guaranteed to be ordered in
! the way the type should sort, but there is no guarantee about the
! ordering of OIDs of unrelated enum types.
--- 2626,2633 ----
matching enum types to their associated values and labels. The
internal representation of a given enum value is actually the OID
of its associated row in pg_enum. The
! enum values for a particular enum type are ordered using their
! enumsortorder> values.
***************
*** 2658,2663 ****
--- 2657,2670 ----
The textual label for this enum value
+
+
+ enumsortorder
+ nameinteger
+
+ The position of this enum value within the list of values for the
+ enum type
+
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 02eaedf..78c2dac 100644
*** a/doc/src/sgml/datatype.sgml
--- b/doc/src/sgml/datatype.sgml
*************** SELECT * FROM person WHERE current_mood
*** 2898,2904 ****
The ordering of the values in an enum type is the
! order in which the values were listed when the type was created.
All standard comparison operators and related
aggregate functions are supported for enums. For example:
--- 2898,2906 ----
The ordering of the values in an enum type is the
! order in which the values were listed when the type was created,
! but additional values may be inserted at any position within this
! list using ALTER TYPE>.
All standard comparison operators and related
aggregate functions are supported for enums. For example:
*************** SELECT * FROM person WHERE current_mood
*** 2912,2923 ****
Curly | ok
(2 rows)
SELECT * FROM person WHERE current_mood > 'sad' ORDER BY current_mood;
name | current_mood
-------+--------------
Curly | ok
Moe | happy
! (2 rows)
SELECT name
FROM person
--- 2914,2928 ----
Curly | ok
(2 rows)
+ ALTER TYPE mood ADD 'content' BEFORE 'happy';
+ INSERT INTO person VALUES ('Sue', 'content');
SELECT * FROM person WHERE current_mood > 'sad' ORDER BY current_mood;
name | current_mood
-------+--------------
Curly | ok
+ Sue | content
Moe | happy
! (3 rows)
SELECT name
FROM person
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
index 315922e..b05b000 100644
*** a/doc/src/sgml/ref/alter_type.sgml
--- b/doc/src/sgml/ref/alter_type.sgml
*************** ALTER TYPE name RENAME ATTRIBUTE attribute_name TO new_attribute_name
ALTER TYPE name RENAME TO new_name
ALTER TYPE name SET SCHEMA new_schema
+ ALTER TYPE name ADD new_enum_value [ BEFORE | AFTER existing_enum_value ]
where action is one of:
*************** ALTER TYPE
+
+ new_enum_value
+
+
+ The new value to be added to the enum type's list of values. Like all
+ enum literals it needs to be quoted.
+
+
+
+
+
+ existing_enum_value
+
+
+ The neighbor of the new value to be added to the enum type's list of
+ values. Like all enum literals it needs to be quoted.
+
+
+
+
*************** ALTER TYPE email SET SCHEMA customers;
*** 232,237 ****
--- 275,287 ----
ALTER TYPE compfoo ADD ATTRIBUTE f3 int;
+
+
+ To add a new value to an enum type in a particular sort position:
+
+ ALTER TYPE colors ADD 'orange' AFTER 'red';
+
+
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index dcc53e1..f42aecb 100644
*** a/src/backend/catalog/heap.c
--- b/src/backend/catalog/heap.c
*************** AddNewRelationType(const char *typeName,
*** 855,861 ****
'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 */
}
/* --------------------------------
*************** heap_create_with_catalog(const char *rel
*** 1108,1114 ****
'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);
}
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index d544c1f..65f9c71 100644
*** 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;
+
+ }
/*
*************** static int oid_cmp(const void *p1, const
*** 33,40 ****
* vals is a list of Value strings.
*/
void
! EnumValuesCreate(Oid enumTypeOid, List *vals,
! Oid binary_upgrade_next_pg_enum_oid)
{
Relation pg_enum;
TupleDesc tupDesc;
--- 223,229 ----
* vals is a list of Value strings.
*/
void
! EnumValuesCreate(Oid enumTypeOid, List *vals)
{
Relation pg_enum;
TupleDesc tupDesc;
*************** EnumValuesCreate(Oid enumTypeOid, List *
*** 50,58 ****
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);
*************** EnumValuesCreate(Oid enumTypeOid, List *
*** 62,96 ****
* 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));
*************** EnumValuesCreate(Oid enumTypeOid, List *
*** 114,119 ****
--- 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]);
*************** EnumValuesDelete(Oid enumTypeOid)
*** 164,170 ****
}
! /* 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)
{
*************** oid_cmp(const void *p1, const void *p2)
*** 177,179 ****
--- 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;
+ }
+
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index d7fccdf..56e0dc1 100644
*** a/src/backend/catalog/pg_type.c
--- b/src/backend/catalog/pg_type.c
*************** TypeShellMake(const char *typeName, Oid
*** 112,117 ****
--- 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 */
*************** TypeCreate(Oid newTypeOid,
*** 204,210 ****
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;
*************** TypeCreate(Oid newTypeOid,
*** 342,347 ****
--- 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
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 25503bd..01e19cf 100644
*** a/src/backend/commands/typecmds.c
--- b/src/backend/commands/typecmds.c
*************** static Oid findTypeTypmodoutFunction(Lis
*** 85,96 ****
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.
*************** DefineType(List *names, List *parameters
*** 562,569 ****
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.
*/
*************** DefineType(List *names, List *parameters
*** 601,607 ****
'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);
}
*************** DefineDomain(CreateDomainStmt *stmt)
*** 1044,1050 ****
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
*************** DefineEnum(CreateEnumStmt *stmt)
*** 1094,1099 ****
--- 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,
*************** DefineEnum(CreateEnumStmt *stmt)
*** 1153,1162 ****
'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.
*************** DefineEnum(CreateEnumStmt *stmt)
*** 1192,1202 ****
'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.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2118a33..dcc063a 100644
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
*************** _copyCreateEnumStmt(CreateEnumStmt *from
*** 2873,2878 ****
--- 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)
{
*************** copyObject(void *from)
*** 4033,4038 ****
--- 4046,4054 ----
case T_CreateEnumStmt:
retval = _copyCreateEnumStmt(from);
break;
+ case T_AlterEnumStmt:
+ retval = _copyAlterEnumStmt(from);
+ break;
case T_ViewStmt:
retval = _copyViewStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 6bad724..2439e7f 100644
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
*************** _equalCreateEnumStmt(CreateEnumStmt *a,
*** 1390,1395 ****
--- 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);
*************** equal(void *a, void *b)
*** 2697,2702 ****
--- 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;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 3a74fa5..90d3e4d 100644
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
*************** static RangeVar *makeRangeVarFromAnyName
*** 182,189 ****
}
%type stmt schema_stmt
! AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
--- 182,189 ----
}
%type stmt schema_stmt
! AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
! AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
*************** stmt :
*** 652,657 ****
--- 652,658 ----
| AlterDatabaseSetStmt
| AlterDefaultPrivilegesStmt
| AlterDomainStmt
+ | AlterEnumStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterFunctionStmt
*************** enum_val_list: Sconst
*** 3862,3867 ****
--- 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;
+ }
+ ;
+
+
/*****************************************************************************
*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 75cb354..2c8b7aa 100644
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
*************** check_xact_readonly(Node *parsetree)
*** 190,195 ****
--- 190,196 ----
case T_CreateTrigStmt:
case T_CompositeTypeStmt:
case T_CreateEnumStmt:
+ case T_AlterEnumStmt:
case T_ViewStmt:
case T_DropCastStmt:
case T_DropStmt:
*************** standard_ProcessUtility(Node *parsetree,
*** 860,865 ****
--- 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;
*************** CreateCommandTag(Node *parsetree)
*** 1868,1873 ****
--- 1873,1882 ----
tag = "CREATE TYPE";
break;
+ case T_AlterEnumStmt:
+ tag = "ALTER TYPE";
+ break;
+
case T_ViewStmt:
tag = "CREATE VIEW";
break;
*************** GetCommandLogLevel(Node *parsetree)
*** 2410,2415 ****
--- 2419,2428 ----
lev = LOGSTMT_DDL;
break;
+ case T_AlterEnumStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
case T_ViewStmt:
lev = LOGSTMT_DDL;
break;
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index e5747a4..f9feda5 100644
*** 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 */
*************** enum_send(PG_FUNCTION_ARGS)
*** 155,167 ****
/* 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
*************** enum_le(PG_FUNCTION_ARGS)
*** 170,176 ****
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
*************** enum_ge(PG_FUNCTION_ARGS)
*** 197,203 ****
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
*************** enum_gt(PG_FUNCTION_ARGS)
*** 206,212 ****
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
*************** enum_smaller(PG_FUNCTION_ARGS)
*** 215,221 ****
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
*************** enum_larger(PG_FUNCTION_ARGS)
*** 224,230 ****
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
*************** enum_cmp(PG_FUNCTION_ARGS)
*** 233,242 ****
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);
}
*************** enum_first(PG_FUNCTION_ARGS)
*** 248,253 ****
--- 428,434 ----
{
Oid enumtypoid;
Oid min = InvalidOid;
+ int min_sort = -1; /* value will never in fact be used */
CatCList *list;
int num,
i;
*************** enum_first(PG_FUNCTION_ARGS)
*** 267,276 ****
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);
*************** enum_last(PG_FUNCTION_ARGS)
*** 287,292 ****
--- 472,478 ----
{
Oid enumtypoid;
Oid max = InvalidOid;
+ int max_sort = -1; /* value will never in fact be used */
CatCList *list;
int num,
i;
*************** enum_last(PG_FUNCTION_ARGS)
*** 306,315 ****
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);
*************** enum_range_internal(Oid enumtypoid, Oid
*** 382,427 ****
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;
+ }
+
+
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 6a4557b..d413fe5 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** dumpEnumType(Archive *fout, TypeInfo *ty
*** 6653,6669 ****
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);
*************** dumpEnumType(Archive *fout, TypeInfo *ty
*** 6709,6725 ****
{
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,
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 57d74e1..a077948 100644
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
*************** describeTypes(const char *pattern, bool
*** 473,489 ****
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",
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index b7c9849..c63724a 100644
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
*************** DECLARE_UNIQUE_INDEX(pg_enum_oid_index,
*** 147,152 ****
--- 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));
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index f50cf9d..824a690 100644
*** a/src/include/catalog/pg_class.h
--- b/src/include/catalog/pg_class.h
*************** typedef FormData_pg_class *Form_pg_class
*** 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 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("");
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index 28da42b..06269c6 100644
*** a/src/include/catalog/pg_enum.h
--- b/src/include/catalog/pg_enum.h
*************** CATALOG(pg_enum,3501)
*** 35,40 ****
--- 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;
/* ----------------
*************** typedef FormData_pg_enum *Form_pg_enum;
*** 48,56 ****
* 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
*************** typedef FormData_pg_enum *Form_pg_enum;
*** 60,67 ****
/*
* prototypes for functions in pg_enum.c
*/
! extern void EnumValuesCreate(Oid enumTypeOid, List *vals,
! Oid binary_upgrade_next_pg_enum_oid);
extern void EnumValuesDelete(Oid enumTypeOid);
#endif /* PG_ENUM_H */
--- 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 */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index fc2c306..f79c0e3 100644
*** a/src/include/catalog/pg_type.h
--- b/src/include/catalog/pg_type.h
*************** CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_
*** 194,199 ****
--- 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
*************** typedef FormData_pg_type *Form_pg_type;
*** 224,230 ****
* 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
*************** typedef FormData_pg_type *Form_pg_type;
*** 251,258 ****
#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
/* ----------------
*************** typedef FormData_pg_type *Form_pg_type;
*** 269,355 ****
*/
/* 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 */
*************** DESCR("storage manager");
*** 359,589 ****
/* 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("@ , 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("@ , 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
*************** DATA(insert OID = 2949 ( _txid_snapshot
*** 598,628 ****
* 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
diff --git a/src/include/catalog/pg_type_fn.h b/src/include/catalog/pg_type_fn.h
index cc72350..bc34568 100644
*** a/src/include/catalog/pg_type_fn.h
--- b/src/include/catalog/pg_type_fn.h
*************** extern Oid TypeCreate(Oid newTypeOid,
*** 50,56 ****
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,
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 2bff7e1..9faf3ea 100644
*** a/src/include/commands/typecmds.h
--- b/src/include/commands/typecmds.h
*************** extern void RemoveTypes(DropStmt *drop);
*** 24,29 ****
--- 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);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 0d33a2e..139c8ed 100644
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
*************** typedef enum NodeTag
*** 348,354 ****
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)
*/
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ca225d0..1c3397e 100644
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct CreateEnumStmt
*** 2192,2197 ****
--- 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
* ----------------------
*/
diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out
index 56240c0..f3c86b1 100644
*** a/src/test/regress/expected/enum.out
--- b/src/test/regress/expected/enum.out
*************** ERROR: invalid input value for enum rai
*** 25,30 ****
--- 25,122 ----
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 CAST(enumlabel AS planets);
+ 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)
+
+ \dT+ planets
+ List of data types
+ Schema | Name | Internal name | Size | Elements | Description
+ --------+---------+---------------+------+----------+-------------
+ public | planets | planets | 4 | mercury +|
+ | | | | venus +|
+ | | | | earth +|
+ | | | | mars +|
+ | | | | jupiter +|
+ | | | | saturn +|
+ | | | | uranus +|
+ | | | | neptune |
+ (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);
*************** SELECT COUNT(*) FROM pg_type WHERE typna
*** 403,409 ****
SELECT * FROM pg_enum WHERE NOT EXISTS
(SELECT 1 FROM pg_type WHERE pg_type.oid = enumtypid);
! enumtypid | enumlabel
! -----------+-----------
(0 rows)
--- 495,501 ----
SELECT * FROM pg_enum WHERE NOT EXISTS
(SELECT 1 FROM pg_type WHERE pg_type.oid = enumtypid);
! enumtypid | enumlabel | enumsortorder
! -----------+-----------+---------------
(0 rows)
diff --git a/src/test/regress/sql/enum.sql b/src/test/regress/sql/enum.sql
index 387e8e7..6092706 100644
*** a/src/test/regress/sql/enum.sql
--- b/src/test/regress/sql/enum.sql
*************** SELECT 'red'::rainbow;
*** 16,21 ****
--- 16,71 ----
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 CAST(enumlabel AS planets);
+
+ select 'mars'::planets > 'mercury' as using_sortorder;
+
+ \dT+ planets
+
+ -- 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);