PostgreSQL Source Code  git master
enum.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/pg_enum.h"
#include "libpq/pqformat.h"
#include "storage/procarray.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for enum.c:

Go to the source code of this file.

Functions

static Oid enum_endpoint (Oid enumtypoid, ScanDirection direction)
 
static ArrayTypeenum_range_internal (Oid enumtypoid, Oid lower, Oid upper)
 
static void check_safe_enum_use (HeapTuple enumval_tup)
 
Datum enum_in (PG_FUNCTION_ARGS)
 
Datum enum_out (PG_FUNCTION_ARGS)
 
Datum enum_recv (PG_FUNCTION_ARGS)
 
Datum enum_send (PG_FUNCTION_ARGS)
 
static int enum_cmp_internal (Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
 
Datum enum_lt (PG_FUNCTION_ARGS)
 
Datum enum_le (PG_FUNCTION_ARGS)
 
Datum enum_eq (PG_FUNCTION_ARGS)
 
Datum enum_ne (PG_FUNCTION_ARGS)
 
Datum enum_ge (PG_FUNCTION_ARGS)
 
Datum enum_gt (PG_FUNCTION_ARGS)
 
Datum enum_smaller (PG_FUNCTION_ARGS)
 
Datum enum_larger (PG_FUNCTION_ARGS)
 
Datum enum_cmp (PG_FUNCTION_ARGS)
 
Datum enum_first (PG_FUNCTION_ARGS)
 
Datum enum_last (PG_FUNCTION_ARGS)
 
Datum enum_range_bounds (PG_FUNCTION_ARGS)
 
Datum enum_range_all (PG_FUNCTION_ARGS)
 

Function Documentation

◆ check_safe_enum_use()

static void check_safe_enum_use ( HeapTuple  enumval_tup)
static

Definition at line 63 of file enum.c.

References EnumUncommitted(), ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleHeaderGetXmin, HeapTupleHeaderXminCommitted, NameStr, HeapTupleData::t_data, TransactionIdDidCommit(), and TransactionIdIsInProgress().

Referenced by enum_endpoint(), enum_in(), enum_range_internal(), and enum_recv().

64 {
65  TransactionId xmin;
66  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enumval_tup);
67 
68  /*
69  * If the row is hinted as committed, it's surely safe. This provides a
70  * fast path for all normal use-cases.
71  */
72  if (HeapTupleHeaderXminCommitted(enumval_tup->t_data))
73  return;
74 
75  /*
76  * Usually, a row would get hinted as committed when it's read or loaded
77  * into syscache; but just in case not, let's check the xmin directly.
78  */
79  xmin = HeapTupleHeaderGetXmin(enumval_tup->t_data);
80  if (!TransactionIdIsInProgress(xmin) &&
82  return;
83 
84  /*
85  * Check if the enum value is uncommitted. If not, it's safe, because it
86  * was made during CREATE TYPE AS ENUM and can't be shorter-lived than its
87  * owning type. (This'd also be false for values made by other
88  * transactions; but the previous tests should have handled all of those.)
89  */
90  if (!EnumUncommitted(en->oid))
91  return;
92 
93  /*
94  * There might well be other tests we could do here to narrow down the
95  * unsafe conditions, but for now just raise an exception.
96  */
97  ereport(ERROR,
98  (errcode(ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE),
99  errmsg("unsafe use of new value \"%s\" of enum type %s",
100  NameStr(en->enumlabel),
101  format_type_be(en->enumtypid)),
102  errhint("New enum values must be committed before they can be used.")));
103 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
uint32 TransactionId
Definition: c.h:587
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1325
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:46
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
bool EnumUncommitted(Oid enum_id)
Definition: pg_enum.c:591
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NameStr(name)
Definition: c.h:681

◆ enum_cmp()

Datum enum_cmp ( PG_FUNCTION_ARGS  )

Definition at line 372 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_INT32.

Referenced by gbt_enumkey_cmp(), and gin_enum_cmp().

373 {
374  Oid a = PG_GETARG_OID(0);
375  Oid b = PG_GETARG_OID(1);
376 
377  PG_RETURN_INT32(enum_cmp_internal(a, b, fcinfo));
378 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246

◆ enum_cmp_internal()

static int enum_cmp_internal ( Oid  arg1,
Oid  arg2,
FunctionCallInfo  fcinfo 
)
static

Definition at line 246 of file enum.c.

References Assert, compare_values_of_enum(), ENUMOID, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, GETSTRUCT, HeapTupleIsValid, lookup_type_cache(), ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache1().

Referenced by enum_cmp(), enum_ge(), enum_gt(), enum_larger(), enum_le(), enum_lt(), and enum_smaller().

247 {
248  TypeCacheEntry *tcache;
249 
250  /*
251  * We don't need the typcache except in the hopefully-uncommon case that
252  * one or both Oids are odd. This means that cursory testing of code that
253  * fails to pass flinfo to an enum comparison function might not disclose
254  * the oversight. To make such errors more obvious, Assert that we have a
255  * place to cache even when we take a fast-path exit.
256  */
257  Assert(fcinfo->flinfo != NULL);
258 
259  /* Equal OIDs are equal no matter what */
260  if (arg1 == arg2)
261  return 0;
262 
263  /* Fast path: even-numbered Oids are known to compare correctly */
264  if ((arg1 & 1) == 0 && (arg2 & 1) == 0)
265  {
266  if (arg1 < arg2)
267  return -1;
268  else
269  return 1;
270  }
271 
272  /* Locate the typcache entry for the enum type */
273  tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
274  if (tcache == NULL)
275  {
276  HeapTuple enum_tup;
277  Form_pg_enum en;
278  Oid typeoid;
279 
280  /* Get the OID of the enum type containing arg1 */
281  enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
282  if (!HeapTupleIsValid(enum_tup))
283  ereport(ERROR,
284  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
285  errmsg("invalid internal value for enum: %u",
286  arg1)));
287  en = (Form_pg_enum) GETSTRUCT(enum_tup);
288  typeoid = en->enumtypid;
289  ReleaseSysCache(enum_tup);
290  /* Now locate and remember the typcache entry */
291  tcache = lookup_type_cache(typeoid, 0);
292  fcinfo->flinfo->fn_extra = (void *) tcache;
293  }
294 
295  /* The remaining comparison logic is in typcache.c */
296  return compare_values_of_enum(tcache, arg1, arg2);
297 }
int compare_values_of_enum(TypeCacheEntry *tcache, Oid arg1, Oid arg2)
Definition: typcache.c:2452
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FmgrInfo * flinfo
Definition: fmgr.h:87
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void * fn_extra
Definition: fmgr.h:64
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ enum_endpoint()

static Oid enum_endpoint ( Oid  enumtypoid,
ScanDirection  direction 
)
static

Definition at line 386 of file enum.c.

References AccessShareLock, BTEqualStrategyNumber, check_safe_enum_use(), EnumTypIdSortOrderIndexId, GETSTRUCT, HeapTupleIsValid, index_close(), index_open(), InvalidOid, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), table_close(), and table_open().

Referenced by enum_first(), and enum_last().

387 {
388  Relation enum_rel;
389  Relation enum_idx;
390  SysScanDesc enum_scan;
391  HeapTuple enum_tuple;
392  ScanKeyData skey;
393  Oid minmax;
394 
395  /*
396  * Find the first/last enum member using pg_enum_typid_sortorder_index.
397  * Note we must not use the syscache. See comments for RenumberEnumType
398  * in catalog/pg_enum.c for more info.
399  */
400  ScanKeyInit(&skey,
401  Anum_pg_enum_enumtypid,
402  BTEqualStrategyNumber, F_OIDEQ,
403  ObjectIdGetDatum(enumtypoid));
404 
405  enum_rel = table_open(EnumRelationId, AccessShareLock);
407  enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL,
408  1, &skey);
409 
410  enum_tuple = systable_getnext_ordered(enum_scan, direction);
411  if (HeapTupleIsValid(enum_tuple))
412  {
413  /* check it's safe to use in SQL */
414  check_safe_enum_use(enum_tuple);
415  minmax = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
416  }
417  else
418  {
419  /* should only happen with an empty enum */
420  minmax = InvalidOid;
421  }
422 
423  systable_endscan_ordered(enum_scan);
424  index_close(enum_idx, AccessShareLock);
425  table_close(enum_rel, AccessShareLock);
426 
427  return minmax;
428 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define AccessShareLock
Definition: lockdefs.h:36
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:707
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define EnumTypIdSortOrderIndexId
Definition: pg_enum.h:51
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:732
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:642
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:63
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ enum_eq()

Datum enum_eq ( PG_FUNCTION_ARGS  )

Definition at line 318 of file enum.c.

References PG_GETARG_OID, and PG_RETURN_BOOL.

319 {
320  Oid a = PG_GETARG_OID(0);
321  Oid b = PG_GETARG_OID(1);
322 
323  PG_RETURN_BOOL(a == b);
324 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ enum_first()

Datum enum_first ( PG_FUNCTION_ARGS  )

Definition at line 431 of file enum.c.

References enum_endpoint(), ereport, errcode(), errmsg(), ERROR, format_type_be(), ForwardScanDirection, get_fn_expr_argtype(), InvalidOid, OidIsValid, and PG_RETURN_OID.

432 {
433  Oid enumtypoid;
434  Oid min;
435 
436  /*
437  * We rely on being able to get the specific enum type from the calling
438  * expression tree. Notice that the actual value of the argument isn't
439  * examined at all; in particular it might be NULL.
440  */
441  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
442  if (enumtypoid == InvalidOid)
443  ereport(ERROR,
444  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
445  errmsg("could not determine actual enum type")));
446 
447  /* Get the OID using the index */
448  min = enum_endpoint(enumtypoid, ForwardScanDirection);
449 
450  if (!OidIsValid(min))
451  ereport(ERROR,
452  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
453  errmsg("enum %s contains no values",
454  format_type_be(enumtypoid))));
455 
456  PG_RETURN_OID(min);
457 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction)
Definition: enum.c:386
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

◆ enum_ge()

Datum enum_ge ( PG_FUNCTION_ARGS  )

Definition at line 336 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumge().

337 {
338  Oid a = PG_GETARG_OID(0);
339  Oid b = PG_GETARG_OID(1);
340 
341  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) >= 0);
342 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246

◆ enum_gt()

Datum enum_gt ( PG_FUNCTION_ARGS  )

Definition at line 345 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumgt().

346 {
347  Oid a = PG_GETARG_OID(0);
348  Oid b = PG_GETARG_OID(1);
349 
350  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) > 0);
351 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246

◆ enum_in()

Datum enum_in ( PG_FUNCTION_ARGS  )

Definition at line 109 of file enum.c.

References check_safe_enum_use(), CStringGetDatum, ENUMTYPOIDNAME, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleIsValid, name, NAMEDATALEN, ObjectIdGetDatum, PG_GETARG_CSTRING, PG_GETARG_OID, PG_RETURN_OID, ReleaseSysCache(), and SearchSysCache2().

110 {
111  char *name = PG_GETARG_CSTRING(0);
112  Oid enumtypoid = PG_GETARG_OID(1);
113  Oid enumoid;
114  HeapTuple tup;
115 
116  /* must check length to prevent Assert failure within SearchSysCache */
117  if (strlen(name) >= NAMEDATALEN)
118  ereport(ERROR,
119  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
120  errmsg("invalid input value for enum %s: \"%s\"",
121  format_type_be(enumtypoid),
122  name)));
123 
125  ObjectIdGetDatum(enumtypoid),
126  CStringGetDatum(name));
127  if (!HeapTupleIsValid(tup))
128  ereport(ERROR,
129  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
130  errmsg("invalid input value for enum %s: \"%s\"",
131  format_type_be(enumtypoid),
132  name)));
133 
134  /* check it's safe to use in SQL */
135  check_safe_enum_use(tup);
136 
137  /*
138  * This comes from pg_enum.oid and stores system oids in user tables. This
139  * oid must be preserved by binary upgrades.
140  */
141  enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
142 
143  ReleaseSysCache(tup);
144 
145  PG_RETURN_OID(enumoid);
146 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define CStringGetDatum(X)
Definition: postgres.h:622
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
const char * name
Definition: encode.c:515
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:63
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

◆ enum_larger()

Datum enum_larger ( PG_FUNCTION_ARGS  )

Definition at line 363 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.

364 {
365  Oid a = PG_GETARG_OID(0);
366  Oid b = PG_GETARG_OID(1);
367 
368  PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) > 0 ? a : b);
369 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

◆ enum_last()

Datum enum_last ( PG_FUNCTION_ARGS  )

Definition at line 460 of file enum.c.

References BackwardScanDirection, enum_endpoint(), ereport, errcode(), errmsg(), ERROR, format_type_be(), get_fn_expr_argtype(), InvalidOid, OidIsValid, and PG_RETURN_OID.

461 {
462  Oid enumtypoid;
463  Oid max;
464 
465  /*
466  * We rely on being able to get the specific enum type from the calling
467  * expression tree. Notice that the actual value of the argument isn't
468  * examined at all; in particular it might be NULL.
469  */
470  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
471  if (enumtypoid == InvalidOid)
472  ereport(ERROR,
473  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
474  errmsg("could not determine actual enum type")));
475 
476  /* Get the OID using the index */
477  max = enum_endpoint(enumtypoid, BackwardScanDirection);
478 
479  if (!OidIsValid(max))
480  ereport(ERROR,
481  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
482  errmsg("enum %s contains no values",
483  format_type_be(enumtypoid))));
484 
485  PG_RETURN_OID(max);
486 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction)
Definition: enum.c:386
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

◆ enum_le()

Datum enum_le ( PG_FUNCTION_ARGS  )

Definition at line 309 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumle().

310 {
311  Oid a = PG_GETARG_OID(0);
312  Oid b = PG_GETARG_OID(1);
313 
314  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) <= 0);
315 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246

◆ enum_lt()

Datum enum_lt ( PG_FUNCTION_ARGS  )

Definition at line 300 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumlt().

301 {
302  Oid a = PG_GETARG_OID(0);
303  Oid b = PG_GETARG_OID(1);
304 
305  PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) < 0);
306 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246

◆ enum_ne()

Datum enum_ne ( PG_FUNCTION_ARGS  )

Definition at line 327 of file enum.c.

References PG_GETARG_OID, and PG_RETURN_BOOL.

328 {
329  Oid a = PG_GETARG_OID(0);
330  Oid b = PG_GETARG_OID(1);
331 
332  PG_RETURN_BOOL(a != b);
333 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ enum_out()

Datum enum_out ( PG_FUNCTION_ARGS  )

Definition at line 149 of file enum.c.

References ENUMOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, PG_GETARG_OID, PG_RETURN_CSTRING, pstrdup(), ReleaseSysCache(), and SearchSysCache1().

Referenced by anyenum_out().

150 {
151  Oid enumval = PG_GETARG_OID(0);
152  char *result;
153  HeapTuple tup;
154  Form_pg_enum en;
155 
156  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
157  if (!HeapTupleIsValid(tup))
158  ereport(ERROR,
159  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
160  errmsg("invalid internal value for enum: %u",
161  enumval)));
162  en = (Form_pg_enum) GETSTRUCT(tup);
163 
164  result = pstrdup(NameStr(en->enumlabel));
165 
166  ReleaseSysCache(tup);
167 
168  PG_RETURN_CSTRING(result);
169 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NameStr(name)
Definition: c.h:681

◆ enum_range_all()

Datum enum_range_all ( PG_FUNCTION_ARGS  )

Definition at line 521 of file enum.c.

References enum_range_internal(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, and PG_RETURN_ARRAYTYPE_P.

522 {
523  Oid enumtypoid;
524 
525  /*
526  * We rely on being able to get the specific enum type from the calling
527  * expression tree. Notice that the actual value of the argument isn't
528  * examined at all; in particular it might be NULL.
529  */
530  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
531  if (enumtypoid == InvalidOid)
532  ereport(ERROR,
533  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
534  errmsg("could not determine actual enum type")));
535 
538 }
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
static ArrayType * enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
Definition: enum.c:541
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ enum_range_bounds()

Datum enum_range_bounds ( PG_FUNCTION_ARGS  )

Definition at line 490 of file enum.c.

References enum_range_internal(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, lower(), PG_ARGISNULL, PG_GETARG_OID, PG_RETURN_ARRAYTYPE_P, and upper().

491 {
492  Oid lower;
493  Oid upper;
494  Oid enumtypoid;
495 
496  if (PG_ARGISNULL(0))
497  lower = InvalidOid;
498  else
499  lower = PG_GETARG_OID(0);
500  if (PG_ARGISNULL(1))
501  upper = InvalidOid;
502  else
503  upper = PG_GETARG_OID(1);
504 
505  /*
506  * We rely on being able to get the specific enum type from the calling
507  * expression tree. The generic type mechanism should have ensured that
508  * both are of the same type.
509  */
510  enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
511  if (enumtypoid == InvalidOid)
512  ereport(ERROR,
513  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
514  errmsg("could not determine actual enum type")));
515 
516  PG_RETURN_ARRAYTYPE_P(enum_range_internal(enumtypoid, lower, upper));
517 }
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:46
int errcode(int sqlerrcode)
Definition: elog.c:698
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:77
unsigned int Oid
Definition: postgres_ext.h:31
static ArrayType * enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
Definition: enum.c:541
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ enum_range_internal()

static ArrayType * enum_range_internal ( Oid  enumtypoid,
Oid  lower,
Oid  upper 
)
static

Definition at line 541 of file enum.c.

References AccessShareLock, BTEqualStrategyNumber, check_safe_enum_use(), construct_array(), EnumTypIdSortOrderIndexId, ForwardScanDirection, GETSTRUCT, HeapTupleIsValid, index_close(), index_open(), ObjectIdGetDatum, OidIsValid, palloc(), pfree(), repalloc(), ScanKeyInit(), systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), table_close(), and table_open().

Referenced by enum_range_all(), and enum_range_bounds().

542 {
543  ArrayType *result;
544  Relation enum_rel;
545  Relation enum_idx;
546  SysScanDesc enum_scan;
547  HeapTuple enum_tuple;
548  ScanKeyData skey;
549  Datum *elems;
550  int max,
551  cnt;
552  bool left_found;
553 
554  /*
555  * Scan the enum members in order using pg_enum_typid_sortorder_index.
556  * Note we must not use the syscache. See comments for RenumberEnumType
557  * in catalog/pg_enum.c for more info.
558  */
559  ScanKeyInit(&skey,
560  Anum_pg_enum_enumtypid,
561  BTEqualStrategyNumber, F_OIDEQ,
562  ObjectIdGetDatum(enumtypoid));
563 
564  enum_rel = table_open(EnumRelationId, AccessShareLock);
566  enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL, 1, &skey);
567 
568  max = 64;
569  elems = (Datum *) palloc(max * sizeof(Datum));
570  cnt = 0;
571  left_found = !OidIsValid(lower);
572 
573  while (HeapTupleIsValid(enum_tuple = systable_getnext_ordered(enum_scan, ForwardScanDirection)))
574  {
575  Oid enum_oid = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
576 
577  if (!left_found && lower == enum_oid)
578  left_found = true;
579 
580  if (left_found)
581  {
582  /* check it's safe to use in SQL */
583  check_safe_enum_use(enum_tuple);
584 
585  if (cnt >= max)
586  {
587  max *= 2;
588  elems = (Datum *) repalloc(elems, max * sizeof(Datum));
589  }
590 
591  elems[cnt++] = ObjectIdGetDatum(enum_oid);
592  }
593 
594  if (OidIsValid(upper) && upper == enum_oid)
595  break;
596  }
597 
598  systable_endscan_ordered(enum_scan);
599  index_close(enum_idx, AccessShareLock);
600  table_close(enum_rel, AccessShareLock);
601 
602  /* and build the result array */
603  /* note this hardwires some details about the representation of Oid */
604  result = construct_array(elems, cnt, enumtypoid,
605  sizeof(Oid), true, TYPALIGN_INT);
606 
607  pfree(elems);
608 
609  return result;
610 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:46
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3318
#define AccessShareLock
Definition: lockdefs.h:36
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:77
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:707
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define EnumTypIdSortOrderIndexId
Definition: pg_enum.h:51
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
uintptr_t Datum
Definition: postgres.h:411
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:732
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
void * palloc(Size size)
Definition: mcxt.c:1062
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:642
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:63
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ enum_recv()

Datum enum_recv ( PG_FUNCTION_ARGS  )

Definition at line 173 of file enum.c.

References buf, check_safe_enum_use(), CStringGetDatum, StringInfoData::cursor, ENUMTYPOIDNAME, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleIsValid, StringInfoData::len, name, NAMEDATALEN, ObjectIdGetDatum, pfree(), PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_OID, pq_getmsgtext(), ReleaseSysCache(), and SearchSysCache2().

174 {
176  Oid enumtypoid = PG_GETARG_OID(1);
177  Oid enumoid;
178  HeapTuple tup;
179  char *name;
180  int nbytes;
181 
182  name = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
183 
184  /* must check length to prevent Assert failure within SearchSysCache */
185  if (strlen(name) >= NAMEDATALEN)
186  ereport(ERROR,
187  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
188  errmsg("invalid input value for enum %s: \"%s\"",
189  format_type_be(enumtypoid),
190  name)));
191 
193  ObjectIdGetDatum(enumtypoid),
194  CStringGetDatum(name));
195  if (!HeapTupleIsValid(tup))
196  ereport(ERROR,
197  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
198  errmsg("invalid input value for enum %s: \"%s\"",
199  format_type_be(enumtypoid),
200  name)));
201 
202  /* check it's safe to use in SQL */
203  check_safe_enum_use(tup);
204 
205  enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
206 
207  ReleaseSysCache(tup);
208 
209  pfree(name);
210 
211  PG_RETURN_OID(enumoid);
212 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
StringInfoData * StringInfo
Definition: stringinfo.h:44
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
unsigned int Oid
Definition: postgres_ext.h:31
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define CStringGetDatum(X)
Definition: postgres.h:622
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
const char * name
Definition: encode.c:515
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:63
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

◆ enum_send()

Datum enum_send ( PG_FUNCTION_ARGS  )

Definition at line 215 of file enum.c.

References buf, ENUMOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, PG_GETARG_OID, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendtext(), ReleaseSysCache(), and SearchSysCache1().

216 {
217  Oid enumval = PG_GETARG_OID(0);
219  HeapTuple tup;
220  Form_pg_enum en;
221 
222  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
223  if (!HeapTupleIsValid(tup))
224  ereport(ERROR,
225  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
226  errmsg("invalid internal value for enum: %u",
227  enumval)));
228  en = (Form_pg_enum) GETSTRUCT(tup);
229 
230  pq_begintypsend(&buf);
231  pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel)));
232 
233  ReleaseSysCache(tup);
234 
236 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
int errcode(int sqlerrcode)
Definition: elog.c:698
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
unsigned int Oid
Definition: postgres_ext.h:31
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NameStr(name)
Definition: c.h:681

◆ enum_smaller()

Datum enum_smaller ( PG_FUNCTION_ARGS  )

Definition at line 354 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.

355 {
356  Oid a = PG_GETARG_OID(0);
357  Oid b = PG_GETARG_OID(1);
358 
359  PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) < 0 ? a : b);
360 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:246
#define PG_RETURN_OID(x)
Definition: fmgr.h:360