#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
#include "catalog/pg_enum.h"
#include "libpq/pqformat.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"
Go to the source code of this file.
Functions | |
static Oid | enum_endpoint (Oid enumtypoid, ScanDirection direction) |
static ArrayType * | enum_range_internal (Oid enumtypoid, Oid lower, Oid upper) |
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) |
Datum enum_cmp | ( | PG_FUNCTION_ARGS | ) |
Definition at line 285 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_INT32.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); if (a == b) PG_RETURN_INT32(0); else if (enum_cmp_internal(a, b, fcinfo) > 0) PG_RETURN_INT32(1); else PG_RETURN_INT32(-1); }
static int enum_cmp_internal | ( | Oid | arg1, | |
Oid | arg2, | |||
FunctionCallInfo | fcinfo | |||
) | [static] |
Definition at line 168 of file enum.c.
References compare_values_of_enum(), ENUMOID, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, GETSTRUCT, HeapTupleIsValid, lookup_type_cache(), NULL, ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache1.
Referenced by enum_cmp(), enum_ge(), enum_gt(), enum_larger(), enum_le(), enum_lt(), and enum_smaller().
{ TypeCacheEntry *tcache; /* Equal OIDs are equal no matter what */ if (arg1 == arg2) return 0; /* Fast path: even-numbered Oids are known to compare correctly */ if ((arg1 & 1) == 0 && (arg2 & 1) == 0) { if (arg1 < arg2) return -1; else return 1; } /* Locate the typcache entry for the enum type */ tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (tcache == NULL) { HeapTuple enum_tup; Form_pg_enum en; Oid typeoid; /* Get the OID of the enum type containing arg1 */ enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1)); if (!HeapTupleIsValid(enum_tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid internal value for enum: %u", arg1))); en = (Form_pg_enum) GETSTRUCT(enum_tup); typeoid = en->enumtypid; ReleaseSysCache(enum_tup); /* Now locate and remember the typcache entry */ tcache = lookup_type_cache(typeoid, 0); fcinfo->flinfo->fn_extra = (void *) tcache; } /* The remaining comparison logic is in typcache.c */ return compare_values_of_enum(tcache, arg1, arg2); }
static Oid enum_endpoint | ( | Oid | enumtypoid, | |
ScanDirection | direction | |||
) | [static] |
Definition at line 304 of file enum.c.
References AccessShareLock, Anum_pg_enum_enumtypid, BTEqualStrategyNumber, EnumRelationId, EnumTypIdSortOrderIndexId, GetTransactionSnapshot(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, index_close(), index_open(), ObjectIdGetDatum, ScanKeyInit(), systable_beginscan_ordered(), systable_endscan_ordered(), and systable_getnext_ordered().
Referenced by enum_first(), and enum_last().
{ Relation enum_rel; Relation enum_idx; SysScanDesc enum_scan; HeapTuple enum_tuple; ScanKeyData skey; Oid minmax; /* * Find the first/last enum member using pg_enum_typid_sortorder_index. * Note we must not use the syscache, and must use an MVCC snapshot here. * See comments for RenumberEnumType in catalog/pg_enum.c for more info. */ ScanKeyInit(&skey, Anum_pg_enum_enumtypid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(enumtypoid)); enum_rel = heap_open(EnumRelationId, AccessShareLock); enum_idx = index_open(EnumTypIdSortOrderIndexId, AccessShareLock); enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, GetTransactionSnapshot(), 1, &skey); enum_tuple = systable_getnext_ordered(enum_scan, direction); if (HeapTupleIsValid(enum_tuple)) minmax = HeapTupleGetOid(enum_tuple); else minmax = InvalidOid; systable_endscan_ordered(enum_scan); index_close(enum_idx, AccessShareLock); heap_close(enum_rel, AccessShareLock); return minmax; }
Datum enum_eq | ( | PG_FUNCTION_ARGS | ) |
Definition at line 231 of file enum.c.
References PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(a == b); }
Datum enum_first | ( | PG_FUNCTION_ARGS | ) |
Definition at line 343 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.
{ Oid enumtypoid; Oid min; /* * We rely on being able to get the specific enum type from the calling * expression tree. Notice that the actual value of the argument isn't * examined at all; in particular it might be NULL. */ enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0); if (enumtypoid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine actual enum type"))); /* Get the OID using the index */ min = enum_endpoint(enumtypoid, ForwardScanDirection); if (!OidIsValid(min)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("enum %s contains no values", format_type_be(enumtypoid)))); PG_RETURN_OID(min); }
Datum enum_ge | ( | PG_FUNCTION_ARGS | ) |
Definition at line 249 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) >= 0); }
Datum enum_gt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 258 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) > 0); }
Datum enum_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 37 of file enum.c.
References CStringGetDatum, ENUMTYPOIDNAME, ereport, errcode(), errmsg(), ERROR, format_type_be(), HeapTupleGetOid, HeapTupleIsValid, name, NAMEDATALEN, ObjectIdGetDatum, PG_GETARG_CSTRING, PG_GETARG_OID, PG_RETURN_OID, ReleaseSysCache(), and SearchSysCache2.
{ char *name = PG_GETARG_CSTRING(0); Oid enumtypoid = PG_GETARG_OID(1); Oid enumoid; HeapTuple tup; /* must check length to prevent Assert failure within SearchSysCache */ if (strlen(name) >= NAMEDATALEN) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input value for enum %s: \"%s\"", format_type_be(enumtypoid), name))); tup = SearchSysCache2(ENUMTYPOIDNAME, ObjectIdGetDatum(enumtypoid), CStringGetDatum(name)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input value for enum %s: \"%s\"", format_type_be(enumtypoid), name))); /* * This comes from pg_enum.oid and stores system oids in user tables. This * oid must be preserved by binary upgrades. */ enumoid = HeapTupleGetOid(tup); ReleaseSysCache(tup); PG_RETURN_OID(enumoid); }
Datum enum_larger | ( | PG_FUNCTION_ARGS | ) |
Definition at line 276 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) > 0 ? a : b); }
Datum enum_last | ( | PG_FUNCTION_ARGS | ) |
Definition at line 372 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.
{ Oid enumtypoid; Oid max; /* * We rely on being able to get the specific enum type from the calling * expression tree. Notice that the actual value of the argument isn't * examined at all; in particular it might be NULL. */ enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0); if (enumtypoid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine actual enum type"))); /* Get the OID using the index */ max = enum_endpoint(enumtypoid, BackwardScanDirection); if (!OidIsValid(max)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("enum %s contains no values", format_type_be(enumtypoid)))); PG_RETURN_OID(max); }
Datum enum_le | ( | PG_FUNCTION_ARGS | ) |
Definition at line 222 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) <= 0); }
Datum enum_lt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 213 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) < 0); }
Datum enum_ne | ( | PG_FUNCTION_ARGS | ) |
Definition at line 240 of file enum.c.
References PG_GETARG_OID, and PG_RETURN_BOOL.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_BOOL(a != b); }
Datum enum_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 74 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().
{ Oid enumval = PG_GETARG_OID(0); char *result; HeapTuple tup; Form_pg_enum en; tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid internal value for enum: %u", enumval))); en = (Form_pg_enum) GETSTRUCT(tup); result = pstrdup(NameStr(en->enumlabel)); ReleaseSysCache(tup); PG_RETURN_CSTRING(result); }
Datum enum_range_all | ( | PG_FUNCTION_ARGS | ) |
Definition at line 433 of file enum.c.
References enum_range_internal(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, and PG_RETURN_ARRAYTYPE_P.
{ Oid enumtypoid; /* * We rely on being able to get the specific enum type from the calling * expression tree. Notice that the actual value of the argument isn't * examined at all; in particular it might be NULL. */ enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0); if (enumtypoid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine actual enum type"))); PG_RETURN_ARRAYTYPE_P(enum_range_internal(enumtypoid, InvalidOid, InvalidOid)); }
Datum enum_range_bounds | ( | PG_FUNCTION_ARGS | ) |
Definition at line 402 of file enum.c.
References enum_range_internal(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, PG_ARGISNULL, PG_GETARG_OID, and PG_RETURN_ARRAYTYPE_P.
{ Oid lower; Oid upper; Oid enumtypoid; if (PG_ARGISNULL(0)) lower = InvalidOid; else lower = PG_GETARG_OID(0); if (PG_ARGISNULL(1)) upper = InvalidOid; else upper = PG_GETARG_OID(1); /* * We rely on being able to get the specific enum type from the calling * expression tree. The generic type mechanism should have ensured that * both are of the same type. */ enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0); if (enumtypoid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not determine actual enum type"))); PG_RETURN_ARRAYTYPE_P(enum_range_internal(enumtypoid, lower, upper)); }
Definition at line 453 of file enum.c.
References AccessShareLock, Anum_pg_enum_enumtypid, BTEqualStrategyNumber, construct_array(), EnumRelationId, EnumTypIdSortOrderIndexId, ForwardScanDirection, GetTransactionSnapshot(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, index_close(), index_open(), ObjectIdGetDatum, OidIsValid, palloc(), pfree(), repalloc(), ScanKeyInit(), systable_beginscan_ordered(), systable_endscan_ordered(), and systable_getnext_ordered().
Referenced by enum_range_all(), and enum_range_bounds().
{ ArrayType *result; Relation enum_rel; Relation enum_idx; SysScanDesc enum_scan; HeapTuple enum_tuple; ScanKeyData skey; Datum *elems; int max, cnt; bool left_found; /* * Scan the enum members in order using pg_enum_typid_sortorder_index. * Note we must not use the syscache, and must use an MVCC snapshot here. * See comments for RenumberEnumType in catalog/pg_enum.c for more info. */ ScanKeyInit(&skey, Anum_pg_enum_enumtypid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(enumtypoid)); enum_rel = heap_open(EnumRelationId, AccessShareLock); enum_idx = index_open(EnumTypIdSortOrderIndexId, AccessShareLock); enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, GetTransactionSnapshot(), 1, &skey); max = 64; elems = (Datum *) palloc(max * sizeof(Datum)); cnt = 0; left_found = !OidIsValid(lower); while (HeapTupleIsValid(enum_tuple = systable_getnext_ordered(enum_scan, ForwardScanDirection))) { Oid enum_oid = HeapTupleGetOid(enum_tuple); if (!left_found && lower == enum_oid) left_found = true; if (left_found) { if (cnt >= max) { max *= 2; elems = (Datum *) repalloc(elems, max * sizeof(Datum)); } elems[cnt++] = ObjectIdGetDatum(enum_oid); } if (OidIsValid(upper) && upper == enum_oid) break; } systable_endscan_ordered(enum_scan); index_close(enum_idx, AccessShareLock); heap_close(enum_rel, AccessShareLock); /* and build the result array */ /* note this hardwires some details about the representation of Oid */ result = construct_array(elems, cnt, enumtypoid, sizeof(Oid), true, 'i'); pfree(elems); return result; }
Datum enum_recv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 98 of file enum.c.
References buf, CStringGetDatum, StringInfoData::cursor, ENUMTYPOIDNAME, ereport, errcode(), errmsg(), ERROR, format_type_be(), HeapTupleGetOid, HeapTupleIsValid, StringInfoData::len, name, NAMEDATALEN, ObjectIdGetDatum, pfree(), PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_OID, pq_getmsgtext(), ReleaseSysCache(), and SearchSysCache2.
{ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Oid enumtypoid = PG_GETARG_OID(1); Oid enumoid; HeapTuple tup; char *name; int nbytes; name = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); /* must check length to prevent Assert failure within SearchSysCache */ if (strlen(name) >= NAMEDATALEN) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input value for enum %s: \"%s\"", format_type_be(enumtypoid), name))); tup = SearchSysCache2(ENUMTYPOIDNAME, ObjectIdGetDatum(enumtypoid), CStringGetDatum(name)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input value for enum %s: \"%s\"", format_type_be(enumtypoid), name))); enumoid = HeapTupleGetOid(tup); ReleaseSysCache(tup); pfree(name); PG_RETURN_OID(enumoid); }
Datum enum_send | ( | PG_FUNCTION_ARGS | ) |
Definition at line 137 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.
{ Oid enumval = PG_GETARG_OID(0); StringInfoData buf; HeapTuple tup; Form_pg_enum en; tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid internal value for enum: %u", enumval))); en = (Form_pg_enum) GETSTRUCT(tup); pq_begintypsend(&buf); pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel))); ReleaseSysCache(tup); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum enum_smaller | ( | PG_FUNCTION_ARGS | ) |
Definition at line 267 of file enum.c.
References enum_cmp_internal(), PG_GETARG_OID, and PG_RETURN_OID.
{ Oid a = PG_GETARG_OID(0); Oid b = PG_GETARG_OID(1); PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) < 0 ? a : b); }