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/indexing.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 64 of file enum.c.

References EnumBlacklisted(), 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().

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

◆ enum_cmp()

Datum enum_cmp ( PG_FUNCTION_ARGS  )

Definition at line 373 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_INT32.

Referenced by gbt_enumkey_cmp(), and gin_enum_cmp().

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

◆ enum_cmp_internal()

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

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

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

◆ enum_endpoint()

static Oid enum_endpoint ( Oid  enumtypoid,
ScanDirection  direction 
)
static

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

388 {
389  Relation enum_rel;
390  Relation enum_idx;
391  SysScanDesc enum_scan;
392  HeapTuple enum_tuple;
393  ScanKeyData skey;
394  Oid minmax;
395 
396  /*
397  * Find the first/last enum member using pg_enum_typid_sortorder_index.
398  * Note we must not use the syscache. See comments for RenumberEnumType
399  * in catalog/pg_enum.c for more info.
400  */
401  ScanKeyInit(&skey,
402  Anum_pg_enum_enumtypid,
403  BTEqualStrategyNumber, F_OIDEQ,
404  ObjectIdGetDatum(enumtypoid));
405 
406  enum_rel = table_open(EnumRelationId, AccessShareLock);
408  enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL,
409  1, &skey);
410 
411  enum_tuple = systable_getnext_ordered(enum_scan, direction);
412  if (HeapTupleIsValid(enum_tuple))
413  {
414  /* check it's safe to use in SQL */
415  check_safe_enum_use(enum_tuple);
416  minmax = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
417  }
418  else
419  {
420  /* should only happen with an empty enum */
421  minmax = InvalidOid;
422  }
423 
424  systable_endscan_ordered(enum_scan);
425  index_close(enum_idx, AccessShareLock);
426  table_close(enum_rel, AccessShareLock);
427 
428  return minmax;
429 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:630
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:649
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:565
#define EnumTypIdSortOrderIndexId
Definition: indexing.h:163
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:64
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ enum_eq()

Datum enum_eq ( PG_FUNCTION_ARGS  )

Definition at line 319 of file enum.c.

References PG_GETARG_OID, and PG_RETURN_BOOL.

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

◆ enum_first()

Datum enum_first ( PG_FUNCTION_ARGS  )

Definition at line 432 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.

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

◆ enum_ge()

Datum enum_ge ( PG_FUNCTION_ARGS  )

Definition at line 337 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumge().

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

◆ enum_gt()

Datum enum_gt ( PG_FUNCTION_ARGS  )

Definition at line 346 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumgt().

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

◆ enum_in()

Datum enum_in ( PG_FUNCTION_ARGS  )

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

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

◆ enum_larger()

Datum enum_larger ( PG_FUNCTION_ARGS  )

Definition at line 364 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.

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

◆ enum_last()

Datum enum_last ( PG_FUNCTION_ARGS  )

Definition at line 461 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.

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

◆ enum_le()

Datum enum_le ( PG_FUNCTION_ARGS  )

Definition at line 310 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumle().

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

◆ enum_lt()

Datum enum_lt ( PG_FUNCTION_ARGS  )

Definition at line 301 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.

Referenced by gbt_enumlt().

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

◆ enum_ne()

Datum enum_ne ( PG_FUNCTION_ARGS  )

Definition at line 328 of file enum.c.

References PG_GETARG_OID, and PG_RETURN_BOOL.

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

◆ enum_out()

Datum enum_out ( PG_FUNCTION_ARGS  )

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

151 {
152  Oid enumval = PG_GETARG_OID(0);
153  char *result;
154  HeapTuple tup;
155  Form_pg_enum en;
156 
157  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
158  if (!HeapTupleIsValid(tup))
159  ereport(ERROR,
160  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
161  errmsg("invalid internal value for enum: %u",
162  enumval)));
163  en = (Form_pg_enum) GETSTRUCT(tup);
164 
165  result = pstrdup(NameStr(en->enumlabel));
166 
167  ReleaseSysCache(tup);
168 
169  PG_RETURN_CSTRING(result);
170 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define NameStr(name)
Definition: c.h:609

◆ enum_range_all()

Datum enum_range_all ( PG_FUNCTION_ARGS  )

Definition at line 522 of file enum.c.

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

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

◆ enum_range_bounds()

Datum enum_range_bounds ( PG_FUNCTION_ARGS  )

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

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

◆ enum_range_internal()

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

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

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

◆ enum_recv()

Datum enum_recv ( PG_FUNCTION_ARGS  )

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

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

◆ enum_send()

Datum enum_send ( PG_FUNCTION_ARGS  )

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

217 {
218  Oid enumval = PG_GETARG_OID(0);
220  HeapTuple tup;
221  Form_pg_enum en;
222 
223  tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
224  if (!HeapTupleIsValid(tup))
225  ereport(ERROR,
226  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
227  errmsg("invalid internal value for enum: %u",
228  enumval)));
229  en = (Form_pg_enum) GETSTRUCT(tup);
230 
231  pq_begintypsend(&buf);
232  pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel)));
233 
234  ReleaseSysCache(tup);
235 
237 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
int errcode(int sqlerrcode)
Definition: elog.c:570
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
unsigned int Oid
Definition: postgres_ext.h:31
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define NameStr(name)
Definition: c.h:609

◆ enum_smaller()

Datum enum_smaller ( PG_FUNCTION_ARGS  )

Definition at line 355 of file enum.c.

References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.

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