diff options
Diffstat (limited to 'src/backend/parser/parse_coerce.c')
-rw-r--r-- | src/backend/parser/parse_coerce.c | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 388d98b3436..24676404340 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.160 2008/01/01 19:45:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.161 2008/01/11 18:39:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1255,12 +1255,20 @@ check_generic_type_consistency(Oid *actual_arg_types, * we add the extra condition that the ANYELEMENT type must not be an array. * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but * is an extra restriction if not.) + * + * When allow_poly is false, we are not expecting any of the actual_arg_types + * to be polymorphic, and we should not return a polymorphic result type + * either. When allow_poly is true, it is okay to have polymorphic "actual" + * arg types, and we can return ANYARRAY or ANYELEMENT as the result. (This + * case is currently used only to check compatibility of an aggregate's + * declaration with the underlying transfn.) */ Oid enforce_generic_type_consistency(Oid *actual_arg_types, Oid *declared_arg_types, int nargs, - Oid rettype) + Oid rettype, + bool allow_poly) { int j; bool have_generics = false; @@ -1268,9 +1276,6 @@ enforce_generic_type_consistency(Oid *actual_arg_types, Oid elem_typeid = InvalidOid; Oid array_typeid = InvalidOid; Oid array_typelem; - bool have_anyelement = (rettype == ANYELEMENTOID || - rettype == ANYNONARRAYOID || - rettype == ANYENUMOID); bool have_anynonarray = (rettype == ANYNONARRAYOID); bool have_anyenum = (rettype == ANYENUMOID); @@ -1287,7 +1292,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types, decl_type == ANYNONARRAYOID || decl_type == ANYENUMOID) { - have_generics = have_anyelement = true; + have_generics = true; if (decl_type == ANYNONARRAYOID) have_anynonarray = true; else if (decl_type == ANYENUMOID) @@ -1297,6 +1302,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types, have_unknowns = true; continue; } + if (allow_poly && decl_type == actual_type) + continue; /* no new information here */ if (OidIsValid(elem_typeid) && actual_type != elem_typeid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -1314,6 +1321,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types, have_unknowns = true; continue; } + if (allow_poly && decl_type == actual_type) + continue; /* no new information here */ if (OidIsValid(array_typeid) && actual_type != array_typeid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -1335,20 +1344,12 @@ enforce_generic_type_consistency(Oid *actual_arg_types, /* Get the element type based on the array type, if we have one */ if (OidIsValid(array_typeid)) { - if (array_typeid == ANYARRAYOID && !have_anyelement) - { - /* Special case for ANYARRAY input: okay iff no ANYELEMENT */ - array_typelem = InvalidOid; - } - else - { - array_typelem = get_element_type(array_typeid); - if (!OidIsValid(array_typelem)) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("argument declared \"anyarray\" is not an array but type %s", - format_type_be(array_typeid)))); - } + array_typelem = get_element_type(array_typeid); + if (!OidIsValid(array_typelem)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("argument declared \"anyarray\" is not an array but type %s", + format_type_be(array_typeid)))); if (!OidIsValid(elem_typeid)) { @@ -1370,13 +1371,21 @@ enforce_generic_type_consistency(Oid *actual_arg_types, } else if (!OidIsValid(elem_typeid)) { - /* Only way to get here is if all the generic args are UNKNOWN */ - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("could not determine polymorphic type because input has type \"unknown\""))); + if (allow_poly) + { + array_typeid = ANYARRAYOID; + elem_typeid = ANYELEMENTOID; + } + else + { + /* Only way to get here is if all the generic args are UNKNOWN */ + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("could not determine polymorphic type because input has type \"unknown\""))); + } } - if (have_anynonarray) + if (have_anynonarray && elem_typeid != ANYELEMENTOID) { /* require the element type to not be an array */ if (type_is_array(elem_typeid)) @@ -1386,7 +1395,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types, format_type_be(elem_typeid)))); } - if (have_anyenum) + if (have_anyenum && elem_typeid != ANYELEMENTOID) { /* require the element type to be an enum */ if (!type_is_enum(elem_typeid)) |