diff options
Diffstat (limited to 'src/backend/catalog/pg_enum.c')
-rw-r--r-- | src/backend/catalog/pg_enum.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c new file mode 100644 index 00000000000..696c1f06d44 --- /dev/null +++ b/src/backend/catalog/pg_enum.c @@ -0,0 +1,146 @@ +/*------------------------------------------------------------------------- + * + * pg_enum.c + * routines to support manipulation of the pg_enum relation + * + * Copyright (c) 2006-2007, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/catalog/pg_enum.c,v 1.1 2007/04/02 03:49:37 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/genam.h" +#include "access/heapam.h" +#include "catalog/catalog.h" +#include "catalog/indexing.h" +#include "catalog/pg_enum.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" + +static int oid_cmp(const void *p1, const void *p2); + + +/* + * EnumValuesCreate + * Create an entry in pg_enum for each of the supplied enum values. + * + * vals is a list of Value strings. + */ +void +EnumValuesCreate(Oid enumTypeOid, List *vals) +{ + Relation pg_enum; + TupleDesc tupDesc; + NameData enumlabel; + Oid *oids; + int i, n; + Datum values[Natts_pg_enum]; + char nulls[Natts_pg_enum]; + ListCell *lc; + HeapTuple tup; + + n = 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); + tupDesc = pg_enum->rd_att; + + /* + * Allocate oids. While this method does not absolutely guarantee + * that we generate no duplicate oids (since we haven't entered each + * oid into the table before allocating the next), trouble could only + * occur if the oid counter wraps all the way around before we finish. + * Which seems unlikely. + */ + oids = (Oid *) palloc(n * sizeof(Oid)); + for(i = 0; i < n; i++) + { + oids[i] = GetNewOid(pg_enum); + } + + /* sort them, just in case counter wrapped from high to low */ + qsort(oids, n, sizeof(Oid), oid_cmp); + + /* and make the entries */ + memset(nulls, ' ', sizeof(nulls)); + + i = 0; + foreach(lc, vals) + { + char *lab = strVal(lfirst(lc)); + + values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid); + namestrcpy(&enumlabel, lab); + values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel); + + tup = heap_formtuple(tupDesc, values, nulls); + HeapTupleSetOid(tup, oids[i]); + + simple_heap_insert(pg_enum, tup); + CatalogUpdateIndexes(pg_enum, tup); + heap_freetuple(tup); + + i++; + } + + /* clean up */ + pfree(oids); + heap_close(pg_enum, RowExclusiveLock); +} + + +/* + * EnumValuesDelete + * Remove all the pg_enum entries for the specified enum type. + */ +void +EnumValuesDelete(Oid enumTypeOid) +{ + Relation pg_enum; + ScanKeyData key[1]; + SysScanDesc scan; + HeapTuple tup; + + pg_enum = heap_open(EnumRelationId, RowExclusiveLock); + + ScanKeyInit(&key[0], + Anum_pg_enum_enumtypid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(enumTypeOid)); + + scan = systable_beginscan(pg_enum, EnumTypIdLabelIndexId, true, + SnapshotNow, 1, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + simple_heap_delete(pg_enum, &tup->t_self); + } + + systable_endscan(scan); + + heap_close(pg_enum, RowExclusiveLock); +} + + +/* qsort comparison function */ +static int +oid_cmp(const void *p1, const void *p2) +{ + Oid v1 = *((const Oid *) p1); + Oid v2 = *((const Oid *) p2); + + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + return 0; +} |