diff options
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/utils/adt/enum.c | 409 | ||||
| -rw-r--r-- | src/backend/utils/adt/format_type.c | 4 | ||||
| -rw-r--r-- | src/backend/utils/adt/pseudotypes.c | 27 | ||||
| -rw-r--r-- | src/backend/utils/adt/xml.c | 6 | ||||
| -rw-r--r-- | src/backend/utils/cache/lsyscache.c | 18 | ||||
| -rw-r--r-- | src/backend/utils/cache/syscache.c | 27 | ||||
| -rw-r--r-- | src/backend/utils/cache/typcache.c | 4 | ||||
| -rw-r--r-- | src/backend/utils/fmgr/funcapi.c | 42 |
9 files changed, 513 insertions, 28 deletions
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index ad3b848607..12d158a49b 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -1,7 +1,7 @@ # # Makefile for utils/adt # -# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.63 2007/01/28 16:16:52 neilc Exp $ +# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.64 2007/04/02 03:49:39 tgl Exp $ # subdir = src/backend/utils/adt @@ -17,7 +17,7 @@ endif OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \ cash.o char.o date.o datetime.o datum.o domains.o \ - float.o format_type.o \ + enum.o float.o format_type.o \ geo_ops.o geo_selfuncs.o int.o int8.o like.o lockfuncs.o \ misc.o nabstime.o name.o not_in.o numeric.o numutils.o \ oid.o oracle_compat.o pseudotypes.o rowtypes.o \ diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c new file mode 100644 index 0000000000..288894ec3f --- /dev/null +++ b/src/backend/utils/adt/enum.c @@ -0,0 +1,409 @@ +/*------------------------------------------------------------------------- + * + * enum.c + * I/O functions, operators, aggregates etc for enum types + * + * Copyright (c) 2006-2007, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.1 2007/04/02 03:49:39 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "catalog/pg_enum.h" +#include "fmgr.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + + +static Oid cstring_enum(char *name, Oid enumtypoid); +static char *enum_cstring(Oid enumval); +static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper); +static int enum_elem_cmp(const void *left, const void *right); + + +/* Basic I/O support */ + +Datum +enum_in(PG_FUNCTION_ARGS) +{ + char *name = PG_GETARG_CSTRING(0); + Oid enumtypoid = PG_GETARG_OID(1); + + PG_RETURN_OID(cstring_enum(name, enumtypoid)); +} + +/* guts of enum_in and text-to-enum */ +static Oid +cstring_enum(char *name, Oid enumtypoid) +{ + HeapTuple tup; + Oid enumoid; + + tup = SearchSysCache(ENUMTYPOIDNAME, + ObjectIdGetDatum(enumtypoid), + CStringGetDatum(name), + 0, 0); + if (tup == NULL) + 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); + return enumoid; +} + +Datum +enum_out(PG_FUNCTION_ARGS) +{ + Oid enumoid = PG_GETARG_OID(0); + + PG_RETURN_CSTRING(enum_cstring(enumoid)); +} + +/* guts of enum_out and enum-to-text */ +static char * +enum_cstring(Oid enumval) +{ + HeapTuple tup; + Form_pg_enum en; + char *label; + + tup = SearchSysCache(ENUMOID, + ObjectIdGetDatum(enumval), + 0, 0, 0); + if (tup == NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid internal value for enum: %u", + enumval))); + en = (Form_pg_enum) GETSTRUCT(tup); + + label = pstrdup(NameStr(en->enumlabel)); + + ReleaseSysCache(tup); + return label; +} + +/* Comparison functions and related */ + +Datum +enum_lt(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a < b); +} + +Datum +enum_le(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a <= b); +} + +Datum +enum_eq(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a == b); +} + +Datum +enum_ne(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a != b); +} + +Datum +enum_ge(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a >= b); +} + +Datum +enum_gt(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_BOOL(a > b); +} + +Datum +enum_smaller(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_OID(a <= b ? a : b); +} + +Datum +enum_larger(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + PG_RETURN_OID(a >= b ? a : b); +} + +Datum +enum_cmp(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +/* Casts between text and enum */ + +Datum +enum_text(PG_FUNCTION_ARGS) +{ + Oid enumval = PG_GETARG_OID(0); + text *result; + char *cstr; + int len; + + cstr = enum_cstring(enumval); + len = strlen(cstr); + result = (text *) palloc(VARHDRSZ + len); + SET_VARSIZE(result, VARHDRSZ + len); + memcpy(VARDATA(result), cstr, len); + pfree(cstr); + PG_RETURN_TEXT_P(result); +} + +Datum +text_enum(PG_FUNCTION_ARGS) +{ + text *textval = PG_GETARG_TEXT_P(0); + Oid enumtypoid; + char *str; + + /* + * We rely on being able to get the specific enum type from the calling + * expression tree. + */ + enumtypoid = get_fn_expr_rettype(fcinfo->flinfo); + if (enumtypoid == InvalidOid) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("could not determine actual enum type"))); + + str = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(textval))); + PG_RETURN_OID(cstring_enum(str, enumtypoid)); +} + +/* Enum programming support functions */ + +Datum +enum_first(PG_FUNCTION_ARGS) +{ + Oid enumtypoid; + Oid min = InvalidOid; + CatCList *list; + int num, i; + + /* + * 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"))); + + list = SearchSysCacheList(ENUMTYPOIDNAME, 1, + ObjectIdGetDatum(enumtypoid), + 0, 0, 0); + num = list->n_members; + for (i = 0; i < num; i++) + { + Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data); + if (!OidIsValid(min) || valoid < min) + min = valoid; + } + + ReleaseCatCacheList(list); + + if (!OidIsValid(min)) /* should not happen */ + elog(ERROR, "no values found for enum %s", + format_type_be(enumtypoid)); + + PG_RETURN_OID(min); +} + +Datum +enum_last(PG_FUNCTION_ARGS) +{ + Oid enumtypoid; + Oid max = InvalidOid; + CatCList *list; + int num, i; + + /* + * 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"))); + + list = SearchSysCacheList(ENUMTYPOIDNAME, 1, + ObjectIdGetDatum(enumtypoid), + 0, 0, 0); + num = list->n_members; + for (i = 0; i < num; i++) + { + Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data); + if(!OidIsValid(max) || valoid > max) + max = valoid; + } + + ReleaseCatCacheList(list); + + if (!OidIsValid(max)) /* should not happen */ + elog(ERROR, "no values found for enum %s", + format_type_be(enumtypoid)); + + PG_RETURN_OID(max); +} + +/* 2-argument variant of enum_range */ +Datum +enum_range_bounds(PG_FUNCTION_ARGS) +{ + 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)); +} + +/* 1-argument variant of enum_range */ +Datum +enum_range_all(PG_FUNCTION_ARGS) +{ + 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)); +} + +static ArrayType * +enum_range_internal(Oid enumtypoid, Oid lower, Oid upper) +{ + ArrayType *result; + CatCList *list; + int total, i, j; + Datum *elems; + + list = SearchSysCacheList(ENUMTYPOIDNAME, 1, + ObjectIdGetDatum(enumtypoid), + 0, 0, 0); + total = list->n_members; + + elems = (Datum *) palloc(total * sizeof(Datum)); + + j = 0; + for (i = 0; i < total; i++) + { + Oid val = HeapTupleGetOid(&(list->members[i]->tuple)); + + if ((!OidIsValid(lower) || lower <= val) && + (!OidIsValid(upper) || val <= upper)) + elems[j++] = ObjectIdGetDatum(val); + } + + /* shouldn't need the cache anymore */ + ReleaseCatCacheList(list); + + /* sort results into OID order */ + qsort(elems, j, sizeof(Datum), enum_elem_cmp); + + /* note this hardwires some details about the representation of Oid */ + result = construct_array(elems, j, enumtypoid, sizeof(Oid), true, 'i'); + + pfree(elems); + + return result; +} + +/* qsort comparison function for Datums that are OIDs */ +static int +enum_elem_cmp(const void *left, const void *right) +{ + Oid l = DatumGetObjectId(*((const Datum *) left)); + Oid r = DatumGetObjectId(*((const Datum *) right)); + + if (l < r) + return -1; + if (l > r) + return 1; + return 0; +} diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index 898534477b..f7879bafc5 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.46 2007/01/05 22:19:40 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.47 2007/04/02 03:49:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -148,7 +148,7 @@ format_type_internal(Oid type_oid, int32 typemod, if (array_base_type != InvalidOid && typeform->typstorage != 'p' && - typeform->typtype != 'd') + typeform->typtype != TYPTYPE_DOMAIN) { /* Switch our attention to the array element type */ ReleaseSysCache(tuple); diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index 3bd5ff66d3..fc9f332482 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.18 2007/01/05 22:19:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.19 2007/04/02 03:49:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -164,6 +164,31 @@ anyarray_send(PG_FUNCTION_ARGS) /* + * anyenum_in - input routine for pseudo-type ANYENUM. + */ +Datum +anyenum_in(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot accept a value of type anyenum"))); + + PG_RETURN_VOID(); /* keep compiler quiet */ +} + +/* + * anyenum_out - output routine for pseudo-type ANYENUM. + * + * We may as well allow this, since enum_out will in fact work. + */ +Datum +anyenum_out(PG_FUNCTION_ARGS) +{ + return enum_out(fcinfo); +} + + +/* * void_in - input routine for pseudo-type VOID. * * We allow this so that PL functions can return VOID without any special diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 55be759c9e..4fea991283 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.38 2007/04/01 09:00:25 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.39 2007/04/02 03:49:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2648,7 +2648,7 @@ map_sql_type_to_xml_name(Oid typeoid, int typmod) Form_pg_type typtuple = (Form_pg_type) GETSTRUCT(tuple); appendStringInfoString(&result, - map_multipart_sql_identifier_to_xml_name((typtuple->typtype == 'd') ? "Domain" : "UDT", + map_multipart_sql_identifier_to_xml_name((typtuple->typtype == TYPTYPE_DOMAIN) ? "Domain" : "UDT", get_database_name(MyDatabaseId), get_namespace_name(typtuple->typnamespace), NameStr(typtuple->typname))); @@ -2877,7 +2877,7 @@ map_sql_type_to_xmlschema_type(Oid typeoid, int typmod) break; default: - if (get_typtype(typeoid) == 'd') + if (get_typtype(typeoid) == TYPTYPE_DOMAIN) { Oid base_typeoid; int32 base_typmod = -1; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 69f1e0c242..391870c3a6 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.150 2007/03/19 16:30:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.151 2007/04/02 03:49:39 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -1770,7 +1770,7 @@ getTypeIOParam(HeapTuple typeTuple) * own type OID as parameter. (As of 8.2, domains must get their own OID * even if their base type is an array.) */ - if (typeStruct->typtype == 'b' && OidIsValid(typeStruct->typelem)) + if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem)) return typeStruct->typelem; else return HeapTupleGetOid(typeTuple); @@ -2022,7 +2022,7 @@ getBaseTypeAndTypmod(Oid typid, int32 *typmod) if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for type %u", typid); typTup = (Form_pg_type) GETSTRUCT(tup); - if (typTup->typtype != 'd') + if (typTup->typtype != TYPTYPE_DOMAIN) { /* Not a domain, so done */ ReleaseSysCache(tup); @@ -2128,7 +2128,17 @@ get_typtype(Oid typid) bool type_is_rowtype(Oid typid) { - return (typid == RECORDOID || get_typtype(typid) == 'c'); + return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE); +} + +/* + * type_is_enum + * Returns true if the given type is an enum type. + */ +bool +type_is_enum(Oid typid) +{ + return (get_typtype(typid) == TYPTYPE_ENUM); } /* diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 75f290dda6..2d52b4299b 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.111 2007/02/14 01:58:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.112 2007/04/02 03:49:39 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -31,6 +31,7 @@ #include "catalog/pg_constraint.h" #include "catalog/pg_conversion.h" #include "catalog/pg_database.h" +#include "catalog/pg_enum.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" @@ -335,6 +336,30 @@ static const struct cachedesc cacheinfo[] = { }, 4 }, + {EnumRelationId, /* ENUMOID */ + EnumOidIndexId, + 0, + 1, + { + ObjectIdAttributeNumber, + 0, + 0, + 0 + }, + 256 + }, + {EnumRelationId, /* ENUMTYPOIDNAME */ + EnumTypIdLabelIndexId, + 0, + 2, + { + Anum_pg_enum_enumtypid, + Anum_pg_enum_enumlabel, + 0, + 0 + }, + 256 + }, {IndexRelationId, /* INDEXRELID */ IndexRelidIndexId, Anum_pg_index_indrelid, diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 523e8ca35a..a8a2409911 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -36,7 +36,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.24 2007/01/05 22:19:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.25 2007/04/02 03:49:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -275,7 +275,7 @@ lookup_type_cache(Oid type_id, int flags) */ if ((flags & TYPECACHE_TUPDESC) && typentry->tupDesc == NULL && - typentry->typtype == 'c') + typentry->typtype == TYPTYPE_COMPOSITE) { Relation rel; diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 218b7646b7..c32130c3ec 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -7,7 +7,7 @@ * Copyright (c) 2002-2007, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.33 2007/02/01 19:10:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.34 2007/04/02 03:49:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -193,8 +193,8 @@ shutdown_MultiFuncCall(Datum arg) * only when we couldn't resolve the actual rowtype for lack of information. * * The other hard case that this handles is resolution of polymorphism. - * We will never return ANYELEMENT or ANYARRAY, either as a scalar result - * type or as a component of a rowtype. + * We will never return ANYELEMENT, ANYARRAY or ANYENUM, either as a scalar + * result type or as a component of a rowtype. * * This function is relatively expensive --- in a function returning set, * try to call it only the first time through. @@ -338,7 +338,7 @@ internal_get_result_type(Oid funcid, /* * If scalar polymorphic result, try to resolve it. */ - if (rettype == ANYARRAYOID || rettype == ANYELEMENTOID) + if (IsPolymorphicType(rettype)) { Oid newrettype = exprType(call_expr); @@ -389,8 +389,8 @@ internal_get_result_type(Oid funcid, /* * Given the result tuple descriptor for a function with OUT parameters, - * replace any polymorphic columns (ANYELEMENT/ANYARRAY) with correct data - * types deduced from the input arguments. Returns TRUE if able to deduce + * replace any polymorphic columns (ANYELEMENT/ANYARRAY/ANYENUM) with correct + * data types deduced from the input arguments. Returns TRUE if able to deduce * all types, FALSE if not. */ static bool @@ -401,6 +401,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, int nargs = declared_args->dim1; bool have_anyelement_result = false; bool have_anyarray_result = false; + bool have_anyenum = false; Oid anyelement_type = InvalidOid; Oid anyarray_type = InvalidOid; int i; @@ -416,6 +417,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, case ANYARRAYOID: have_anyarray_result = true; break; + case ANYENUMOID: + have_anyelement_result = true; + have_anyenum = true; + break; default: break; } @@ -435,6 +440,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, switch (declared_args->values[i]) { case ANYELEMENTOID: + case ANYENUMOID: if (!OidIsValid(anyelement_type)) anyelement_type = get_call_expr_argtype(call_expr, i); break; @@ -461,12 +467,17 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, anyelement_type, ANYELEMENTOID); + /* Check for enum if needed */ + if (have_anyenum && !type_is_enum(anyelement_type)) + return false; + /* And finally replace the tuple column types as needed */ for (i = 0; i < natts; i++) { switch (tupdesc->attrs[i]->atttypid) { case ANYELEMENTOID: + case ANYENUMOID: TupleDescInitEntry(tupdesc, i + 1, NameStr(tupdesc->attrs[i]->attname), anyelement_type, @@ -490,8 +501,8 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, /* * Given the declared argument types and modes for a function, - * replace any polymorphic types (ANYELEMENT/ANYARRAY) with correct data - * types deduced from the input arguments. Returns TRUE if able to deduce + * replace any polymorphic types (ANYELEMENT/ANYARRAY/ANYENUM) with correct + * data types deduced from the input arguments. Returns TRUE if able to deduce * all types, FALSE if not. This is the same logic as * resolve_polymorphic_tupdesc, but with a different argument representation. * @@ -517,6 +528,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, switch (argtypes[i]) { case ANYELEMENTOID: + case ANYENUMOID: if (argmode == PROARGMODE_OUT) have_anyelement_result = true; else @@ -571,12 +583,15 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, anyelement_type, ANYELEMENTOID); + /* XXX do we need to enforce ANYENUM here? I think not */ + /* And finally replace the output column types as needed */ for (i = 0; i < numargs; i++) { switch (argtypes[i]) { case ANYELEMENTOID: + case ANYENUMOID: argtypes[i] = anyelement_type; break; case ANYARRAYOID: @@ -603,12 +618,13 @@ get_type_func_class(Oid typid) { switch (get_typtype(typid)) { - case 'c': + case TYPTYPE_COMPOSITE: return TYPEFUNC_COMPOSITE; - case 'b': - case 'd': + case TYPTYPE_BASE: + case TYPTYPE_DOMAIN: + case TYPTYPE_ENUM: return TYPEFUNC_SCALAR; - case 'p': + case TYPTYPE_PSEUDO: if (typid == RECORDOID) return TYPEFUNC_RECORD; @@ -840,7 +856,7 @@ get_func_result_name(Oid functionId) * Given a pg_proc row for a function, return a tuple descriptor for the * result rowtype, or NULL if the function does not have OUT parameters. * - * Note that this does not handle resolution of ANYELEMENT/ANYARRAY types; + * Note that this does not handle resolution of polymorphic types; * that is deliberate. */ TupleDesc |
