PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
enum.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * enum.c
4  * I/O functions, operators, aggregates etc for enum types
5  *
6  * Copyright (c) 2006-2017, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/enum.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "access/genam.h"
17 #include "access/heapam.h"
18 #include "access/htup_details.h"
19 #include "catalog/indexing.h"
20 #include "catalog/pg_enum.h"
21 #include "libpq/pqformat.h"
22 #include "storage/procarray.h"
23 #include "utils/array.h"
24 #include "utils/builtins.h"
25 #include "utils/fmgroids.h"
26 #include "utils/snapmgr.h"
27 #include "utils/syscache.h"
28 #include "utils/typcache.h"
29 
30 
31 static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction);
32 static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
33 
34 
35 /*
36  * Disallow use of an uncommitted pg_enum tuple.
37  *
38  * We need to make sure that uncommitted enum values don't get into indexes.
39  * If they did, and if we then rolled back the pg_enum addition, we'd have
40  * broken the index because value comparisons will not work reliably without
41  * an underlying pg_enum entry. (Note that removal of the heap entry
42  * containing an enum value is not sufficient to ensure that it doesn't appear
43  * in upper levels of indexes.) To do this we prevent an uncommitted row from
44  * being used for any SQL-level purpose. This is stronger than necessary,
45  * since the value might not be getting inserted into a table or there might
46  * be no index on its column, but it's easy to enforce centrally.
47  *
48  * However, it's okay to allow use of uncommitted values belonging to enum
49  * types that were themselves created in the same transaction, because then
50  * any such index would also be new and would go away altogether on rollback.
51  * (This case is required by pg_upgrade.)
52  *
53  * This function needs to be called (directly or indirectly) in any of the
54  * functions below that could return an enum value to SQL operations.
55  */
56 static void
58 {
59  TransactionId xmin;
60  Form_pg_enum en;
61  HeapTuple enumtyp_tup;
62 
63  /*
64  * If the row is hinted as committed, it's surely safe. This provides a
65  * fast path for all normal use-cases.
66  */
67  if (HeapTupleHeaderXminCommitted(enumval_tup->t_data))
68  return;
69 
70  /*
71  * Usually, a row would get hinted as committed when it's read or loaded
72  * into syscache; but just in case not, let's check the xmin directly.
73  */
74  xmin = HeapTupleHeaderGetXmin(enumval_tup->t_data);
75  if (!TransactionIdIsInProgress(xmin) &&
77  return;
78 
79  /* It is a new enum value, so check to see if the whole enum is new */
80  en = (Form_pg_enum) GETSTRUCT(enumval_tup);
81  enumtyp_tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(en->enumtypid));
82  if (!HeapTupleIsValid(enumtyp_tup))
83  elog(ERROR, "cache lookup failed for type %u", en->enumtypid);
84 
85  /*
86  * We insist that the type have been created in the same (sub)transaction
87  * as the enum value. It would be safe to allow the type's originating
88  * xact to be a subcommitted child of the enum value's xact, but not vice
89  * versa (since we might now be in a subxact of the type's originating
90  * xact, which could roll back along with the enum value's subxact). The
91  * former case seems a sufficiently weird usage pattern as to not be worth
92  * spending code for, so we're left with a simple equality check.
93  *
94  * We also insist that the type's pg_type row not be HEAP_UPDATED. If it
95  * is, we can't tell whether the row was created or only modified in the
96  * apparent originating xact, so it might be older than that xact. (We do
97  * not worry whether the enum value is HEAP_UPDATED; if it is, we might
98  * think it's too new and throw an unnecessary error, but we won't allow
99  * an unsafe case.)
100  */
101  if (xmin == HeapTupleHeaderGetXmin(enumtyp_tup->t_data) &&
102  !(enumtyp_tup->t_data->t_infomask & HEAP_UPDATED))
103  {
104  /* same (sub)transaction, so safe */
105  ReleaseSysCache(enumtyp_tup);
106  return;
107  }
108 
109  /*
110  * There might well be other tests we could do here to narrow down the
111  * unsafe conditions, but for now just raise an exception.
112  */
113  ereport(ERROR,
114  (errcode(ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE),
115  errmsg("unsafe use of new value \"%s\" of enum type %s",
116  NameStr(en->enumlabel),
117  format_type_be(en->enumtypid)),
118  errhint("New enum values must be committed before they can be used.")));
119 }
120 
121 
122 /* Basic I/O support */
123 
124 Datum
126 {
127  char *name = PG_GETARG_CSTRING(0);
128  Oid enumtypoid = PG_GETARG_OID(1);
129  Oid enumoid;
130  HeapTuple tup;
131 
132  /* must check length to prevent Assert failure within SearchSysCache */
133  if (strlen(name) >= NAMEDATALEN)
134  ereport(ERROR,
135  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
136  errmsg("invalid input value for enum %s: \"%s\"",
137  format_type_be(enumtypoid),
138  name)));
139 
141  ObjectIdGetDatum(enumtypoid),
142  CStringGetDatum(name));
143  if (!HeapTupleIsValid(tup))
144  ereport(ERROR,
145  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
146  errmsg("invalid input value for enum %s: \"%s\"",
147  format_type_be(enumtypoid),
148  name)));
149 
150  /* check it's safe to use in SQL */
151  check_safe_enum_use(tup);
152 
153  /*
154  * This comes from pg_enum.oid and stores system oids in user tables. This
155  * oid must be preserved by binary upgrades.
156  */
157  enumoid = HeapTupleGetOid(tup);
158 
159  ReleaseSysCache(tup);
160 
161  PG_RETURN_OID(enumoid);
162 }
163 
164 Datum
166 {
167  Oid enumval = PG_GETARG_OID(0);
168  char *result;
169  HeapTuple tup;
170  Form_pg_enum en;
171 
172  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
173  if (!HeapTupleIsValid(tup))
174  ereport(ERROR,
175  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
176  errmsg("invalid internal value for enum: %u",
177  enumval)));
178  en = (Form_pg_enum) GETSTRUCT(tup);
179 
180  result = pstrdup(NameStr(en->enumlabel));
181 
182  ReleaseSysCache(tup);
183 
184  PG_RETURN_CSTRING(result);
185 }
186 
187 /* Binary I/O support */
188 Datum
190 {
192  Oid enumtypoid = PG_GETARG_OID(1);
193  Oid enumoid;
194  HeapTuple tup;
195  char *name;
196  int nbytes;
197 
198  name = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
199 
200  /* must check length to prevent Assert failure within SearchSysCache */
201  if (strlen(name) >= NAMEDATALEN)
202  ereport(ERROR,
203  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
204  errmsg("invalid input value for enum %s: \"%s\"",
205  format_type_be(enumtypoid),
206  name)));
207 
209  ObjectIdGetDatum(enumtypoid),
210  CStringGetDatum(name));
211  if (!HeapTupleIsValid(tup))
212  ereport(ERROR,
213  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
214  errmsg("invalid input value for enum %s: \"%s\"",
215  format_type_be(enumtypoid),
216  name)));
217 
218  /* check it's safe to use in SQL */
219  check_safe_enum_use(tup);
220 
221  enumoid = HeapTupleGetOid(tup);
222 
223  ReleaseSysCache(tup);
224 
225  pfree(name);
226 
227  PG_RETURN_OID(enumoid);
228 }
229 
230 Datum
232 {
233  Oid enumval = PG_GETARG_OID(0);
235  HeapTuple tup;
236  Form_pg_enum en;
237 
238  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
239  if (!HeapTupleIsValid(tup))
240  ereport(ERROR,
241  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
242  errmsg("invalid internal value for enum: %u",
243  enumval)));
244  en = (Form_pg_enum) GETSTRUCT(tup);
245 
246  pq_begintypsend(&buf);
247  pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel)));
248 
249  ReleaseSysCache(tup);
250 
252 }
253 
254 /* Comparison functions and related */
255 
256 /*
257  * enum_cmp_internal is the common engine for all the visible comparison
258  * functions, except for enum_eq and enum_ne which can just check for OID
259  * equality directly.
260  */
261 static int
263 {
264  TypeCacheEntry *tcache;
265 
266  /*
267  * We don't need the typcache except in the hopefully-uncommon case that
268  * one or both Oids are odd. This means that cursory testing of code that
269  * fails to pass flinfo to an enum comparison function might not disclose
270  * the oversight. To make such errors more obvious, Assert that we have a
271  * place to cache even when we take a fast-path exit.
272  */
273  Assert(fcinfo->flinfo != NULL);
274 
275  /* Equal OIDs are equal no matter what */
276  if (arg1 == arg2)
277  return 0;
278 
279  /* Fast path: even-numbered Oids are known to compare correctly */
280  if ((arg1 & 1) == 0 && (arg2 & 1) == 0)
281  {
282  if (arg1 < arg2)
283  return -1;
284  else
285  return 1;
286  }
287 
288  /* Locate the typcache entry for the enum type */
289  tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
290  if (tcache == NULL)
291  {
292  HeapTuple enum_tup;
293  Form_pg_enum en;
294  Oid typeoid;
295 
296  /* Get the OID of the enum type containing arg1 */
297  enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
298  if (!HeapTupleIsValid(enum_tup))
299  ereport(ERROR,
300  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
301  errmsg("invalid internal value for enum: %u",
302  arg1)));
303  en = (Form_pg_enum) GETSTRUCT(enum_tup);
304  typeoid = en->enumtypid;
305  ReleaseSysCache(enum_tup);
306  /* Now locate and remember the typcache entry */
307  tcache = lookup_type_cache(typeoid, 0);
308  fcinfo->flinfo->fn_extra = (void *) tcache;
309  }
310 
311  /* The remaining comparison logic is in typcache.c */
312  return compare_values_of_enum(tcache, arg1, arg2);
313 }
314 
315 Datum
317 {
318  Oid a = PG_GETARG_OID(0);
319  Oid b = PG_GETARG_OID(1);
320 
321  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) < 0);
322 }
323 
324 Datum
326 {
327  Oid a = PG_GETARG_OID(0);
328  Oid b = PG_GETARG_OID(1);
329 
330  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) <= 0);
331 }
332 
333 Datum
335 {
336  Oid a = PG_GETARG_OID(0);
337  Oid b = PG_GETARG_OID(1);
338 
339  PG_RETURN_BOOL(a == b);
340 }
341 
342 Datum
344 {
345  Oid a = PG_GETARG_OID(0);
346  Oid b = PG_GETARG_OID(1);
347 
348  PG_RETURN_BOOL(a != b);
349 }
350 
351 Datum
353 {
354  Oid a = PG_GETARG_OID(0);
355  Oid b = PG_GETARG_OID(1);
356 
357  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) >= 0);
358 }
359 
360 Datum
362 {
363  Oid a = PG_GETARG_OID(0);
364  Oid b = PG_GETARG_OID(1);
365 
366  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) > 0);
367 }
368 
369 Datum
371 {
372  Oid a = PG_GETARG_OID(0);
373  Oid b = PG_GETARG_OID(1);
374 
375  PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) < 0 ? a : b);
376 }
377 
378 Datum
380 {
381  Oid a = PG_GETARG_OID(0);
382  Oid b = PG_GETARG_OID(1);
383 
384  PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) > 0 ? a : b);
385 }
386 
387 Datum
389 {
390  Oid a = PG_GETARG_OID(0);
391  Oid b = PG_GETARG_OID(1);
392 
393  PG_RETURN_INT32(enum_cmp_internal(a, b, fcinfo));
394 }
395 
396 /* Enum programming support functions */
397 
398 /*
399  * enum_endpoint: common code for enum_first/enum_last
400  */
401 static Oid
402 enum_endpoint(Oid enumtypoid, ScanDirection direction)
403 {
404  Relation enum_rel;
405  Relation enum_idx;
406  SysScanDesc enum_scan;
407  HeapTuple enum_tuple;
408  ScanKeyData skey;
409  Oid minmax;
410 
411  /*
412  * Find the first/last enum member using pg_enum_typid_sortorder_index.
413  * Note we must not use the syscache. See comments for RenumberEnumType
414  * in catalog/pg_enum.c for more info.
415  */
416  ScanKeyInit(&skey,
418  BTEqualStrategyNumber, F_OIDEQ,
419  ObjectIdGetDatum(enumtypoid));
420 
423  enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL,
424  1, &skey);
425 
426  enum_tuple = systable_getnext_ordered(enum_scan, direction);
427  if (HeapTupleIsValid(enum_tuple))
428  {
429  /* check it's safe to use in SQL */
430  check_safe_enum_use(enum_tuple);
431  minmax = HeapTupleGetOid(enum_tuple);
432  }
433  else
434  {
435  /* should only happen with an empty enum */
436  minmax = InvalidOid;
437  }
438 
439  systable_endscan_ordered(enum_scan);
440  index_close(enum_idx, AccessShareLock);
441  heap_close(enum_rel, AccessShareLock);
442 
443  return minmax;
444 }
445 
446 Datum
448 {
449  Oid enumtypoid;
450  Oid min;
451 
452  /*
453  * We rely on being able to get the specific enum type from the calling
454  * expression tree. Notice that the actual value of the argument isn't
455  * examined at all; in particular it might be NULL.
456  */
457  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
458  if (enumtypoid == InvalidOid)
459  ereport(ERROR,
460  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
461  errmsg("could not determine actual enum type")));
462 
463  /* Get the OID using the index */
464  min = enum_endpoint(enumtypoid, ForwardScanDirection);
465 
466  if (!OidIsValid(min))
467  ereport(ERROR,
468  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
469  errmsg("enum %s contains no values",
470  format_type_be(enumtypoid))));
471 
472  PG_RETURN_OID(min);
473 }
474 
475 Datum
477 {
478  Oid enumtypoid;
479  Oid max;
480 
481  /*
482  * We rely on being able to get the specific enum type from the calling
483  * expression tree. Notice that the actual value of the argument isn't
484  * examined at all; in particular it might be NULL.
485  */
486  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
487  if (enumtypoid == InvalidOid)
488  ereport(ERROR,
489  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
490  errmsg("could not determine actual enum type")));
491 
492  /* Get the OID using the index */
493  max = enum_endpoint(enumtypoid, BackwardScanDirection);
494 
495  if (!OidIsValid(max))
496  ereport(ERROR,
497  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
498  errmsg("enum %s contains no values",
499  format_type_be(enumtypoid))));
500 
501  PG_RETURN_OID(max);
502 }
503 
504 /* 2-argument variant of enum_range */
505 Datum
507 {
508  Oid lower;
509  Oid upper;
510  Oid enumtypoid;
511 
512  if (PG_ARGISNULL(0))
513  lower = InvalidOid;
514  else
515  lower = PG_GETARG_OID(0);
516  if (PG_ARGISNULL(1))
517  upper = InvalidOid;
518  else
519  upper = PG_GETARG_OID(1);
520 
521  /*
522  * We rely on being able to get the specific enum type from the calling
523  * expression tree. The generic type mechanism should have ensured that
524  * both are of the same type.
525  */
526  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
527  if (enumtypoid == InvalidOid)
528  ereport(ERROR,
529  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
530  errmsg("could not determine actual enum type")));
531 
532  PG_RETURN_ARRAYTYPE_P(enum_range_internal(enumtypoid, lower, upper));
533 }
534 
535 /* 1-argument variant of enum_range */
536 Datum
538 {
539  Oid enumtypoid;
540 
541  /*
542  * We rely on being able to get the specific enum type from the calling
543  * expression tree. Notice that the actual value of the argument isn't
544  * examined at all; in particular it might be NULL.
545  */
546  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
547  if (enumtypoid == InvalidOid)
548  ereport(ERROR,
549  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
550  errmsg("could not determine actual enum type")));
551 
554 }
555 
556 static ArrayType *
558 {
559  ArrayType *result;
560  Relation enum_rel;
561  Relation enum_idx;
562  SysScanDesc enum_scan;
563  HeapTuple enum_tuple;
564  ScanKeyData skey;
565  Datum *elems;
566  int max,
567  cnt;
568  bool left_found;
569 
570  /*
571  * Scan the enum members in order using pg_enum_typid_sortorder_index.
572  * Note we must not use the syscache. See comments for RenumberEnumType
573  * in catalog/pg_enum.c for more info.
574  */
575  ScanKeyInit(&skey,
577  BTEqualStrategyNumber, F_OIDEQ,
578  ObjectIdGetDatum(enumtypoid));
579 
582  enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL, 1, &skey);
583 
584  max = 64;
585  elems = (Datum *) palloc(max * sizeof(Datum));
586  cnt = 0;
587  left_found = !OidIsValid(lower);
588 
589  while (HeapTupleIsValid(enum_tuple = systable_getnext_ordered(enum_scan, ForwardScanDirection)))
590  {
591  Oid enum_oid = HeapTupleGetOid(enum_tuple);
592 
593  if (!left_found && lower == enum_oid)
594  left_found = true;
595 
596  if (left_found)
597  {
598  /* check it's safe to use in SQL */
599  check_safe_enum_use(enum_tuple);
600 
601  if (cnt >= max)
602  {
603  max *= 2;
604  elems = (Datum *) repalloc(elems, max * sizeof(Datum));
605  }
606 
607  elems[cnt++] = ObjectIdGetDatum(enum_oid);
608  }
609 
610  if (OidIsValid(upper) && upper == enum_oid)
611  break;
612  }
613 
614  systable_endscan_ordered(enum_scan);
615  index_close(enum_idx, AccessShareLock);
616  heap_close(enum_rel, AccessShareLock);
617 
618  /* and build the result array */
619  /* note this hardwires some details about the representation of Oid */
620  result = construct_array(elems, cnt, enumtypoid, sizeof(Oid), true, 'i');
621 
622  pfree(elems);
623 
624  return result;
625 }
int compare_values_of_enum(TypeCacheEntry *tcache, Oid arg1, Oid arg2)
Definition: typcache.c:1543
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Datum enum_recv(PG_FUNCTION_ARGS)
Definition: enum.c:189
Datum enum_in(PG_FUNCTION_ARGS)
Definition: enum.c:125
uint32 TransactionId
Definition: c.h:394
Datum enum_last(PG_FUNCTION_ARGS)
Definition: enum.c:476
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:43
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:995
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:359
char * pstrdup(const char *in)
Definition: mcxt.c:1165
StringInfoData * StringInfo
Definition: stringinfo.h:46
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3306
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:163
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define heap_close(r, l)
Definition: heapam.h:97
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:313
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:74
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:591
#define HEAP_UPDATED
Definition: htup_details.h:195
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
Datum enum_eq(PG_FUNCTION_ARGS)
Definition: enum.c:334
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
Datum enum_lt(PG_FUNCTION_ARGS)
Definition: enum.c:316
HeapTupleHeader t_data
Definition: htup.h:67
Datum enum_range_all(PG_FUNCTION_ARGS)
Definition: enum.c:537
#define NAMEDATALEN
Datum enum_out(PG_FUNCTION_ARGS)
Definition: enum.c:165
FmgrInfo * flinfo
Definition: fmgr.h:71
void pfree(void *pointer)
Definition: mcxt.c:992
Datum enum_gt(PG_FUNCTION_ARGS)
Definition: enum.c:361
static ArrayType * enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
Definition: enum.c:557
Datum enum_ne(PG_FUNCTION_ARGS)
Definition: enum.c:343
Datum enum_first(PG_FUNCTION_ARGS)
Definition: enum.c:447
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define EnumRelationId
Definition: pg_enum.h:32
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
Datum enum_le(PG_FUNCTION_ARGS)
Definition: enum.c:325
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction)
Definition: enum.c:402
ScanDirection
Definition: sdir.h:22
#define CStringGetDatum(X)
Definition: postgres.h:586
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:46
Datum enum_ge(PG_FUNCTION_ARGS)
Definition: enum.c:352
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:122
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:588
Datum enum_larger(PG_FUNCTION_ARGS)
Definition: enum.c:379
Datum enum_smaller(PG_FUNCTION_ARGS)
Definition: enum.c:370
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Datum enum_range_bounds(PG_FUNCTION_ARGS)
Definition: enum.c:506
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:608
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define InvalidOid
Definition: postgres_ext.h:36
Datum enum_send(PG_FUNCTION_ARGS)
Definition: enum.c:231
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
Datum enum_cmp(PG_FUNCTION_ARGS)
Definition: enum.c:388
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:306
void * fn_extra
Definition: fmgr.h:61
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
const char * name
Definition: encode.c:521
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
#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
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:527
#define EnumTypIdSortOrderIndexId
Definition: indexing.h:159
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:262
#define NameStr(name)
Definition: c.h:495
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:233
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:57
#define PG_RETURN_OID(x)
Definition: fmgr.h:304
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:151