Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

enum.c File Reference

#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"
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)
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

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));
}

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

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);
}