diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 7933283cabc..a2633f5785c 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.161.2.1 2008/10/25 17:19:17 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.161.2.2 2008/12/14 19:46:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1265,6 +1265,15 @@ check_generic_type_consistency(Oid *actual_arg_types, * 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.) + * + * A special case is that we could see ANYARRAY as an actual_arg_type even + * when allow_poly is false (this is possible only because pg_statistic has + * columns shown as anyarray in the catalogs). We allow this to match a + * declared ANYARRAY argument, but only if there is no ANYELEMENT argument + * or result (since we can't determine a specific element type to match to + * ANYELEMENT). Note this means that functions taking ANYARRAY had better + * behave sanely if applied to the pg_statistic columns; they can't just + * assume that successive inputs are of the same actual element type. */ Oid enforce_generic_type_consistency(Oid *actual_arg_types, @@ -1279,6 +1288,9 @@ 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); @@ -1295,7 +1307,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types, decl_type == ANYNONARRAYOID || decl_type == ANYENUMOID) { - have_generics = true; + have_generics = have_anyelement = true; if (decl_type == ANYNONARRAYOID) have_anynonarray = true; else if (decl_type == ANYENUMOID) @@ -1347,12 +1359,20 @@ 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)) { - 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 (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)))); + } if (!OidIsValid(elem_typeid)) { diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out index a208203c6d3..5741b075be9 100644 --- a/src/test/regress/expected/polymorphism.out +++ b/src/test/regress/expected/polymorphism.out @@ -613,3 +613,14 @@ create aggregate build_group(int8, integer) ( SFUNC = add_group, STYPE = int8[] ); +-- check that we can apply functions taking ANYARRAY to pg_stats +select distinct array_eq(histogram_bounds,histogram_bounds) from pg_stats +where histogram_bounds is not null; + array_eq +---------- + t +(1 row) + +-- such functions must protect themselves if varying element type isn't OK +select max(histogram_bounds) from pg_stats; +ERROR: cannot compare arrays of different element types diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql index 2df963952f4..015443ce22c 100644 --- a/src/test/regress/sql/polymorphism.sql +++ b/src/test/regress/sql/polymorphism.sql @@ -426,3 +426,10 @@ create aggregate build_group(int8, integer) ( SFUNC = add_group, STYPE = int8[] ); + +-- check that we can apply functions taking ANYARRAY to pg_stats +select distinct array_eq(histogram_bounds,histogram_bounds) from pg_stats +where histogram_bounds is not null; + +-- such functions must protect themselves if varying element type isn't OK +select max(histogram_bounds) from pg_stats;