Files
postgresql/src/backend/catalog/pg_enum.c
Tom Lane 902d1cb35f Remove all uses of the deprecated functions heap_formtuple, heap_modifytuple,
and heap_deformtuple in favor of the newer functions heap_form_tuple et al
(which do the same things but use bool control flags instead of arbitrary
char values).  Eliminate the former duplicate coding of these functions,
reducing the deprecated functions to mere wrappers around the newer ones.
We can't get rid of them entirely because add-on modules probably still
contain many instances of the old coding style.

Kris Jurka
2008-11-02 01:45:28 +00:00

161 lines
3.7 KiB
C

/*-------------------------------------------------------------------------
*
* pg_enum.c
* routines to support manipulation of the pg_enum relation
*
* Copyright (c) 2006-2008, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_enum.c,v 1.8 2008/11/02 01:45:27 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"
#include "utils/rel.h"
#include "utils/tqual.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];
bool 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, false, sizeof(nulls));
i = 0;
foreach(lc, vals)
{
char *lab = strVal(lfirst(lc));
/*
* labels are stored in a name field, for easier syscache lookup, so
* check the length to make sure it's within range.
*/
if (strlen(lab) > (NAMEDATALEN - 1))
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid enum label \"%s\"", lab),
errdetail("Labels must be %d characters or less.",
NAMEDATALEN - 1)));
values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
namestrcpy(&enumlabel, lab);
values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
tup = heap_form_tuple(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;
}