PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_enum.h File Reference
#include "catalog/genbki.h"
#include "nodes/pg_list.h"
Include dependency graph for pg_enum.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define EnumRelationId   3501
 
#define Natts_pg_enum   3
 
#define Anum_pg_enum_enumtypid   1
 
#define Anum_pg_enum_enumsortorder   2
 
#define Anum_pg_enum_enumlabel   3
 

Typedefs

typedef FormData_pg_enumForm_pg_enum
 

Functions

 CATALOG (pg_enum, 3501)
 
void EnumValuesCreate (Oid enumTypeOid, List *vals)
 
void EnumValuesDelete (Oid enumTypeOid)
 
void AddEnumLabel (Oid enumTypeOid, const char *newVal, const char *neighbor, bool newValIsAfter, bool skipIfExists)
 
void RenameEnumLabel (Oid enumTypeOid, const char *oldVal, const char *newVal)
 

Variables

 FormData_pg_enum
 

Macro Definition Documentation

#define Anum_pg_enum_enumlabel   3

Definition at line 55 of file pg_enum.h.

Referenced by AddEnumLabel(), and EnumValuesCreate().

#define Anum_pg_enum_enumsortorder   2

Definition at line 54 of file pg_enum.h.

Referenced by AddEnumLabel(), and EnumValuesCreate().

#define Anum_pg_enum_enumtypid   1
#define EnumRelationId   3501
#define Natts_pg_enum   3

Definition at line 52 of file pg_enum.h.

Referenced by AddEnumLabel(), and EnumValuesCreate().

Typedef Documentation

Definition at line 46 of file pg_enum.h.

Function Documentation

void AddEnumLabel ( Oid  enumTypeOid,
const char *  newVal,
const char *  neighbor,
bool  newValIsAfter,
bool  skipIfExists 
)

Definition at line 180 of file pg_enum.c.

References Anum_pg_enum_enumlabel, Anum_pg_enum_enumsortorder, Anum_pg_enum_enumtypid, binary_upgrade_next_pg_enum_oid, CatalogTupleInsert(), CStringGetDatum, EnumRelationId, ENUMTYPOIDNAME, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, ExclusiveLock, Float4GetDatum(), GetNewOid(), GETSTRUCT, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, HeapTupleSetOid, i, InvalidOid, IsBinaryUpgrade, sort-test::list, LockDatabaseObject(), catclist::members, catclist::n_members, NAMEDATALEN, NameGetDatum, NameStr, namestrcpy(), Natts_pg_enum, NOTICE, NULL, ObjectIdGetDatum, OidIsValid, palloc(), pfree(), qsort, RelationGetDescr, ReleaseCatCacheList(), ReleaseSysCache(), RenumberEnumType(), RowExclusiveLock, SearchSysCache2, SearchSysCacheList1, sort_order_cmp(), catctup::tuple, TypeRelationId, and values.

Referenced by AlterEnum().

185 {
186  Relation pg_enum;
187  Oid newOid;
189  bool nulls[Natts_pg_enum];
190  NameData enumlabel;
191  HeapTuple enum_tup;
192  float4 newelemorder;
193  HeapTuple *existing;
194  CatCList *list;
195  int nelems;
196  int i;
197 
198  /* check length of new label is ok */
199  if (strlen(newVal) > (NAMEDATALEN - 1))
200  ereport(ERROR,
201  (errcode(ERRCODE_INVALID_NAME),
202  errmsg("invalid enum label \"%s\"", newVal),
203  errdetail("Labels must be %d characters or less.",
204  NAMEDATALEN - 1)));
205 
206  /*
207  * Acquire a lock on the enum type, which we won't release until commit.
208  * This ensures that two backends aren't concurrently modifying the same
209  * enum type. Without that, we couldn't be sure to get a consistent view
210  * of the enum members via the syscache. Note that this does not block
211  * other backends from inspecting the type; see comments for
212  * RenumberEnumType.
213  */
215 
216  /*
217  * Check if label is already in use. The unique index on pg_enum would
218  * catch this anyway, but we prefer a friendlier error message, and
219  * besides we need a check to support IF NOT EXISTS.
220  */
221  enum_tup = SearchSysCache2(ENUMTYPOIDNAME,
222  ObjectIdGetDatum(enumTypeOid),
223  CStringGetDatum(newVal));
224  if (HeapTupleIsValid(enum_tup))
225  {
226  ReleaseSysCache(enum_tup);
227  if (skipIfExists)
228  {
229  ereport(NOTICE,
231  errmsg("enum label \"%s\" already exists, skipping",
232  newVal)));
233  return;
234  }
235  else
236  ereport(ERROR,
238  errmsg("enum label \"%s\" already exists",
239  newVal)));
240  }
241 
243 
244  /* If we have to renumber the existing members, we restart from here */
245 restart:
246 
247  /* Get the list of existing members of the enum */
249  ObjectIdGetDatum(enumTypeOid));
250  nelems = list->n_members;
251 
252  /* Sort the existing members by enumsortorder */
253  existing = (HeapTuple *) palloc(nelems * sizeof(HeapTuple));
254  for (i = 0; i < nelems; i++)
255  existing[i] = &(list->members[i]->tuple);
256 
257  qsort(existing, nelems, sizeof(HeapTuple), sort_order_cmp);
258 
259  if (neighbor == NULL)
260  {
261  /*
262  * Put the new label at the end of the list. No change to existing
263  * tuples is required.
264  */
265  if (nelems > 0)
266  {
267  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(existing[nelems - 1]);
268 
269  newelemorder = en->enumsortorder + 1;
270  }
271  else
272  newelemorder = 1;
273  }
274  else
275  {
276  /* BEFORE or AFTER was specified */
277  int nbr_index;
278  int other_nbr_index;
279  Form_pg_enum nbr_en;
280  Form_pg_enum other_nbr_en;
281 
282  /* Locate the neighbor element */
283  for (nbr_index = 0; nbr_index < nelems; nbr_index++)
284  {
285  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(existing[nbr_index]);
286 
287  if (strcmp(NameStr(en->enumlabel), neighbor) == 0)
288  break;
289  }
290  if (nbr_index >= nelems)
291  ereport(ERROR,
292  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
293  errmsg("\"%s\" is not an existing enum label",
294  neighbor)));
295  nbr_en = (Form_pg_enum) GETSTRUCT(existing[nbr_index]);
296 
297  /*
298  * Attempt to assign an appropriate enumsortorder value: one less than
299  * the smallest member, one more than the largest member, or halfway
300  * between two existing members.
301  *
302  * In the "halfway" case, because of the finite precision of float4,
303  * we might compute a value that's actually equal to one or the other
304  * of its neighbors. In that case we renumber the existing members
305  * and try again.
306  */
307  if (newValIsAfter)
308  other_nbr_index = nbr_index + 1;
309  else
310  other_nbr_index = nbr_index - 1;
311 
312  if (other_nbr_index < 0)
313  newelemorder = nbr_en->enumsortorder - 1;
314  else if (other_nbr_index >= nelems)
315  newelemorder = nbr_en->enumsortorder + 1;
316  else
317  {
318  /*
319  * The midpoint value computed here has to be rounded to float4
320  * precision, else our equality comparisons against the adjacent
321  * values are meaningless. The most portable way of forcing that
322  * to happen with non-C-standard-compliant compilers is to store
323  * it into a volatile variable.
324  */
325  volatile float4 midpoint;
326 
327  other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]);
328  midpoint = (nbr_en->enumsortorder +
329  other_nbr_en->enumsortorder) / 2;
330 
331  if (midpoint == nbr_en->enumsortorder ||
332  midpoint == other_nbr_en->enumsortorder)
333  {
334  RenumberEnumType(pg_enum, existing, nelems);
335  /* Clean up and start over */
336  pfree(existing);
337  ReleaseCatCacheList(list);
338  goto restart;
339  }
340 
341  newelemorder = midpoint;
342  }
343  }
344 
345  /* Get a new OID for the new label */
346  if (IsBinaryUpgrade)
347  {
349  ereport(ERROR,
350  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
351  errmsg("pg_enum OID value not set when in binary upgrade mode")));
352 
353  /*
354  * Use binary-upgrade override for pg_enum.oid, if supplied. During
355  * binary upgrade, all pg_enum.oid's are set this way so they are
356  * guaranteed to be consistent.
357  */
358  if (neighbor != NULL)
359  ereport(ERROR,
360  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
361  errmsg("ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade")));
362 
365  }
366  else
367  {
368  /*
369  * Normal case: we need to allocate a new Oid for the value.
370  *
371  * We want to give the new element an even-numbered Oid if it's safe,
372  * which is to say it compares correctly to all pre-existing even
373  * numbered Oids in the enum. Otherwise, we must give it an odd Oid.
374  */
375  for (;;)
376  {
377  bool sorts_ok;
378 
379  /* Get a new OID (different from all existing pg_enum tuples) */
380  newOid = GetNewOid(pg_enum);
381 
382  /*
383  * Detect whether it sorts correctly relative to existing
384  * even-numbered labels of the enum. We can ignore existing
385  * labels with odd Oids, since a comparison involving one of those
386  * will not take the fast path anyway.
387  */
388  sorts_ok = true;
389  for (i = 0; i < nelems; i++)
390  {
391  HeapTuple exists_tup = existing[i];
392  Form_pg_enum exists_en = (Form_pg_enum) GETSTRUCT(exists_tup);
393  Oid exists_oid = HeapTupleGetOid(exists_tup);
394 
395  if (exists_oid & 1)
396  continue; /* ignore odd Oids */
397 
398  if (exists_en->enumsortorder < newelemorder)
399  {
400  /* should sort before */
401  if (exists_oid >= newOid)
402  {
403  sorts_ok = false;
404  break;
405  }
406  }
407  else
408  {
409  /* should sort after */
410  if (exists_oid <= newOid)
411  {
412  sorts_ok = false;
413  break;
414  }
415  }
416  }
417 
418  if (sorts_ok)
419  {
420  /* If it's even and sorts OK, we're done. */
421  if ((newOid & 1) == 0)
422  break;
423 
424  /*
425  * If it's odd, and sorts OK, loop back to get another OID and
426  * try again. Probably, the next available even OID will sort
427  * correctly too, so it's worth trying.
428  */
429  }
430  else
431  {
432  /*
433  * If it's odd, and does not sort correctly, we're done.
434  * (Probably, the next available even OID would sort
435  * incorrectly too, so no point in trying again.)
436  */
437  if (newOid & 1)
438  break;
439 
440  /*
441  * If it's even, and does not sort correctly, loop back to get
442  * another OID and try again. (We *must* reject this case.)
443  */
444  }
445  }
446  }
447 
448  /* Done with info about existing members */
449  pfree(existing);
450  ReleaseCatCacheList(list);
451 
452  /* Create the new pg_enum entry */
453  memset(nulls, false, sizeof(nulls));
454  values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
455  values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(newelemorder);
456  namestrcpy(&enumlabel, newVal);
457  values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
458  enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
459  HeapTupleSetOid(enum_tup, newOid);
460  CatalogTupleInsert(pg_enum, enum_tup);
461  heap_freetuple(enum_tup);
462 
463  heap_close(pg_enum, RowExclusiveLock);
464 }
static int sort_order_cmp(const void *p1, const void *p2)
Definition: pg_enum.c:624
#define NameGetDatum(X)
Definition: postgres.h:603
int n_members
Definition: catcache.h:154
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:425
#define ExclusiveLock
Definition: lockdefs.h:44
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_enum_enumlabel
Definition: pg_enum.h:55
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define OidIsValid(objectId)
Definition: c.h:534
bool IsBinaryUpgrade
Definition: globals.c:101
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1665
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:992
#define Natts_pg_enum
Definition: pg_enum.h:52
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define EnumRelationId
Definition: pg_enum.h:32
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:2114
Definition: c.h:489
Oid binary_upgrade_next_pg_enum_oid
Definition: pg_enum.c:36
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define CStringGetDatum(X)
Definition: postgres.h:586
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:830
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:46
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:194
#define ereport(elevel, rest)
Definition: elog.h:122
float float4
Definition: c.h:377
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Oid GetNewOid(Relation relation)
Definition: catalog.c:288
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
static void RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems)
Definition: pg_enum.c:574
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Anum_pg_enum_enumtypid
Definition: pg_enum.h:53
tuple list
Definition: sort-test.py:11
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_enum_enumsortorder
Definition: pg_enum.h:54
int i
#define NameStr(name)
Definition: c.h:495
HeapTupleData tuple
Definition: catcache.h:116
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define qsort(a, b, c, d)
Definition: port.h:440
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:151
CATALOG ( pg_enum  ,
3501   
)

Definition at line 34 of file pg_enum.h.

35 {
36  Oid enumtypid; /* OID of owning enum type */
37  float4 enumsortorder; /* sort position of this enum value */
38  NameData enumlabel; /* text representation of enum value */
unsigned int Oid
Definition: postgres_ext.h:31
Definition: c.h:489
FormData_pg_enum
Definition: pg_enum.h:39
float float4
Definition: c.h:377
void EnumValuesCreate ( Oid  enumTypeOid,
List vals 
)

Definition at line 50 of file pg_enum.c.

References Anum_pg_enum_enumlabel, Anum_pg_enum_enumsortorder, Anum_pg_enum_enumtypid, CatalogTupleInsert(), EnumRelationId, ereport, errcode(), errdetail(), errmsg(), ERROR, Float4GetDatum(), GetNewOid(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleSetOid, lfirst, list_length(), NAMEDATALEN, NameGetDatum, namestrcpy(), Natts_pg_enum, ObjectIdGetDatum, oid_cmp(), palloc(), pfree(), qsort, RelationGetDescr, RowExclusiveLock, strVal, and values.

Referenced by DefineEnum().

51 {
52  Relation pg_enum;
53  NameData enumlabel;
54  Oid *oids;
55  int elemno,
56  num_elems;
58  bool nulls[Natts_pg_enum];
59  ListCell *lc;
60  HeapTuple tup;
61 
62  num_elems = list_length(vals);
63 
64  /*
65  * We do not bother to check the list of values for duplicates --- if you
66  * have any, you'll get a less-than-friendly unique-index violation. It is
67  * probably not worth trying harder.
68  */
69 
71 
72  /*
73  * Allocate OIDs for the enum's members.
74  *
75  * While this method does not absolutely guarantee that we generate no
76  * duplicate OIDs (since we haven't entered each oid into the table before
77  * allocating the next), trouble could only occur if the OID counter wraps
78  * all the way around before we finish. Which seems unlikely.
79  */
80  oids = (Oid *) palloc(num_elems * sizeof(Oid));
81 
82  for (elemno = 0; elemno < num_elems; elemno++)
83  {
84  /*
85  * We assign even-numbered OIDs to all the new enum labels. This
86  * tells the comparison functions the OIDs are in the correct sort
87  * order and can be compared directly.
88  */
89  Oid new_oid;
90 
91  do
92  {
93  new_oid = GetNewOid(pg_enum);
94  } while (new_oid & 1);
95  oids[elemno] = new_oid;
96  }
97 
98  /* sort them, just in case OID counter wrapped from high to low */
99  qsort(oids, num_elems, sizeof(Oid), oid_cmp);
100 
101  /* and make the entries */
102  memset(nulls, false, sizeof(nulls));
103 
104  elemno = 0;
105  foreach(lc, vals)
106  {
107  char *lab = strVal(lfirst(lc));
108 
109  /*
110  * labels are stored in a name field, for easier syscache lookup, so
111  * check the length to make sure it's within range.
112  */
113  if (strlen(lab) > (NAMEDATALEN - 1))
114  ereport(ERROR,
115  (errcode(ERRCODE_INVALID_NAME),
116  errmsg("invalid enum label \"%s\"", lab),
117  errdetail("Labels must be %d characters or less.",
118  NAMEDATALEN - 1)));
119 
120  values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
121  values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1);
122  namestrcpy(&enumlabel, lab);
123  values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
124 
125  tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
126  HeapTupleSetOid(tup, oids[elemno]);
127 
128  CatalogTupleInsert(pg_enum, tup);
129  heap_freetuple(tup);
130 
131  elemno++;
132  }
133 
134  /* clean up */
135  pfree(oids);
136  heap_close(pg_enum, RowExclusiveLock);
137 }
static int oid_cmp(const void *p1, const void *p2)
Definition: pg_enum.c:610
#define NameGetDatum(X)
Definition: postgres.h:603
#define RelationGetDescr(relation)
Definition: rel.h:425
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_enum_enumlabel
Definition: pg_enum.h:55
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:992
#define Natts_pg_enum
Definition: pg_enum.h:52
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define EnumRelationId
Definition: pg_enum.h:32
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:2114
Definition: c.h:489
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
Oid GetNewOid(Relation relation)
Definition: catalog.c:288
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Anum_pg_enum_enumtypid
Definition: pg_enum.h:53
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_enum_enumsortorder
Definition: pg_enum.h:54
#define qsort(a, b, c, d)
Definition: port.h:440
void EnumValuesDelete ( Oid  enumTypeOid)

Definition at line 145 of file pg_enum.c.

References Anum_pg_enum_enumtypid, BTEqualStrategyNumber, CatalogTupleDelete(), EnumRelationId, EnumTypIdLabelIndexId, heap_close, heap_open(), HeapTupleIsValid, NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by RemoveTypeById().

146 {
147  Relation pg_enum;
148  ScanKeyData key[1];
149  SysScanDesc scan;
150  HeapTuple tup;
151 
153 
154  ScanKeyInit(&key[0],
156  BTEqualStrategyNumber, F_OIDEQ,
157  ObjectIdGetDatum(enumTypeOid));
158 
159  scan = systable_beginscan(pg_enum, EnumTypIdLabelIndexId, true,
160  NULL, 1, key);
161 
162  while (HeapTupleIsValid(tup = systable_getnext(scan)))
163  {
164  CatalogTupleDelete(pg_enum, &tup->t_self);
165  }
166 
167  systable_endscan(scan);
168 
169  heap_close(pg_enum, RowExclusiveLock);
170 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define EnumTypIdLabelIndexId
Definition: indexing.h:157
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define EnumRelationId
Definition: pg_enum.h:32
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Anum_pg_enum_enumtypid
Definition: pg_enum.h:53
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RenameEnumLabel ( Oid  enumTypeOid,
const char *  oldVal,
const char *  newVal 
)

Definition at line 472 of file pg_enum.c.

References CatalogTupleUpdate(), EnumRelationId, ENUMTYPOIDNAME, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, ExclusiveLock, GETSTRUCT, heap_close, heap_copytuple(), heap_freetuple(), heap_open(), i, sort-test::list, LockDatabaseObject(), catclist::members, catclist::n_members, NAMEDATALEN, NameStr, namestrcpy(), NULL, ObjectIdGetDatum, ReleaseCatCacheList(), RowExclusiveLock, SearchSysCacheList1, HeapTupleData::t_self, catctup::tuple, and TypeRelationId.

Referenced by AlterEnum().

475 {
476  Relation pg_enum;
477  HeapTuple enum_tup;
478  Form_pg_enum en;
479  CatCList *list;
480  int nelems;
481  HeapTuple old_tup;
482  bool found_new;
483  int i;
484 
485  /* check length of new label is ok */
486  if (strlen(newVal) > (NAMEDATALEN - 1))
487  ereport(ERROR,
488  (errcode(ERRCODE_INVALID_NAME),
489  errmsg("invalid enum label \"%s\"", newVal),
490  errdetail("Labels must be %d characters or less.",
491  NAMEDATALEN - 1)));
492 
493  /*
494  * Acquire a lock on the enum type, which we won't release until commit.
495  * This ensures that two backends aren't concurrently modifying the same
496  * enum type. Since we are not changing the type's sort order, this is
497  * probably not really necessary, but there seems no reason not to take
498  * the lock to be sure.
499  */
501 
503 
504  /* Get the list of existing members of the enum */
506  ObjectIdGetDatum(enumTypeOid));
507  nelems = list->n_members;
508 
509  /*
510  * Locate the element to rename and check if the new label is already in
511  * use. (The unique index on pg_enum would catch that anyway, but we
512  * prefer a friendlier error message.)
513  */
514  old_tup = NULL;
515  found_new = false;
516  for (i = 0; i < nelems; i++)
517  {
518  enum_tup = &(list->members[i]->tuple);
519  en = (Form_pg_enum) GETSTRUCT(enum_tup);
520  if (strcmp(NameStr(en->enumlabel), oldVal) == 0)
521  old_tup = enum_tup;
522  if (strcmp(NameStr(en->enumlabel), newVal) == 0)
523  found_new = true;
524  }
525  if (!old_tup)
526  ereport(ERROR,
527  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
528  errmsg("\"%s\" is not an existing enum label",
529  oldVal)));
530  if (found_new)
531  ereport(ERROR,
533  errmsg("enum label \"%s\" already exists",
534  newVal)));
535 
536  /* OK, make a writable copy of old tuple */
537  enum_tup = heap_copytuple(old_tup);
538  en = (Form_pg_enum) GETSTRUCT(enum_tup);
539 
540  ReleaseCatCacheList(list);
541 
542  /* Update the pg_enum entry */
543  namestrcpy(&en->enumlabel, newVal);
544  CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup);
545  heap_freetuple(enum_tup);
546 
547  heap_close(pg_enum, RowExclusiveLock);
548 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
int n_members
Definition: catcache.h:154
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ExclusiveLock
Definition: lockdefs.h:44
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1665
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define EnumRelationId
Definition: pg_enum.h:32
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:830
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:46
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:194
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define NULL
Definition: c.h:226
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
tuple list
Definition: sort-test.py:11
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:495
HeapTupleData tuple
Definition: catcache.h:116
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34

Variable Documentation

FormData_pg_enum

Definition at line 39 of file pg_enum.h.