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 179 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().

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

Definition at line 49 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().

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

145 {
146  Relation pg_enum;
147  ScanKeyData key[1];
148  SysScanDesc scan;
149  HeapTuple tup;
150 
152 
153  ScanKeyInit(&key[0],
155  BTEqualStrategyNumber, F_OIDEQ,
156  ObjectIdGetDatum(enumTypeOid));
157 
158  scan = systable_beginscan(pg_enum, EnumTypIdLabelIndexId, true,
159  NULL, 1, key);
160 
161  while (HeapTupleIsValid(tup = systable_getnext(scan)))
162  {
163  CatalogTupleDelete(pg_enum, &tup->t_self);
164  }
165 
166  systable_endscan(scan);
167 
168  heap_close(pg_enum, RowExclusiveLock);
169 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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 471 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().

474 {
475  Relation pg_enum;
476  HeapTuple enum_tup;
477  Form_pg_enum en;
478  CatCList *list;
479  int nelems;
480  HeapTuple old_tup;
481  bool found_new;
482  int i;
483 
484  /* check length of new label is ok */
485  if (strlen(newVal) > (NAMEDATALEN - 1))
486  ereport(ERROR,
487  (errcode(ERRCODE_INVALID_NAME),
488  errmsg("invalid enum label \"%s\"", newVal),
489  errdetail("Labels must be %d characters or less.",
490  NAMEDATALEN - 1)));
491 
492  /*
493  * Acquire a lock on the enum type, which we won't release until commit.
494  * This ensures that two backends aren't concurrently modifying the same
495  * enum type. Since we are not changing the type's sort order, this is
496  * probably not really necessary, but there seems no reason not to take
497  * the lock to be sure.
498  */
500 
502 
503  /* Get the list of existing members of the enum */
505  ObjectIdGetDatum(enumTypeOid));
506  nelems = list->n_members;
507 
508  /*
509  * Locate the element to rename and check if the new label is already in
510  * use. (The unique index on pg_enum would catch that anyway, but we
511  * prefer a friendlier error message.)
512  */
513  old_tup = NULL;
514  found_new = false;
515  for (i = 0; i < nelems; i++)
516  {
517  enum_tup = &(list->members[i]->tuple);
518  en = (Form_pg_enum) GETSTRUCT(enum_tup);
519  if (strcmp(NameStr(en->enumlabel), oldVal) == 0)
520  old_tup = enum_tup;
521  if (strcmp(NameStr(en->enumlabel), newVal) == 0)
522  found_new = true;
523  }
524  if (!old_tup)
525  ereport(ERROR,
526  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
527  errmsg("\"%s\" is not an existing enum label",
528  oldVal)));
529  if (found_new)
530  ereport(ERROR,
532  errmsg("enum label \"%s\" already exists",
533  newVal)));
534 
535  /* OK, make a writable copy of old tuple */
536  enum_tup = heap_copytuple(old_tup);
537  en = (Form_pg_enum) GETSTRUCT(enum_tup);
538 
539  ReleaseCatCacheList(list);
540 
541  /* Update the pg_enum entry */
542  namestrcpy(&en->enumlabel, newVal);
543  CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup);
544  heap_freetuple(enum_tup);
545 
546  heap_close(pg_enum, RowExclusiveLock);
547 }
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:1372
#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:1651
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:201
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define NULL
Definition: c.h:229
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:499
HeapTupleData tuple
Definition: catcache.h:116
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31

Variable Documentation

FormData_pg_enum

Definition at line 39 of file pg_enum.h.