summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/Makefile4
-rw-r--r--src/backend/utils/adt/enum.c409
-rw-r--r--src/backend/utils/adt/format_type.c4
-rw-r--r--src/backend/utils/adt/pseudotypes.c27
-rw-r--r--src/backend/utils/adt/xml.c6
-rw-r--r--src/backend/utils/cache/lsyscache.c18
-rw-r--r--src/backend/utils/cache/syscache.c27
-rw-r--r--src/backend/utils/cache/typcache.c4
-rw-r--r--src/backend/utils/fmgr/funcapi.c42
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