Restore enforce_generic_type_consistency's pre-8.3 behavior of allowing an
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Dec 2008 19:45:52 +0000 (19:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Dec 2008 19:45:52 +0000 (19:45 +0000)
actual argument type of ANYARRAY to match an argument declared ANYARRAY,
so long as ANYELEMENT etc aren't used.  I had overlooked the fact that this
is a possible case while fixing bug #3852; but it is possible because
pg_statistic contains columns declared ANYARRAY.  Per gripe from Corey Horton.

src/backend/parser/parse_coerce.c
src/test/regress/expected/polymorphism.out
src/test/regress/sql/polymorphism.sql

index 112a07beb581e5aed663924a22f1a48d5249a3f6..1bac7ca2fcea96a1a13006f031963aa892f86116 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.171 2008/10/31 08:39:21 heikki Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.172 2008/12/14 19:45:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1424,6 +1424,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,
@@ -1438,6 +1447,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);
 
@@ -1454,7 +1466,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)
@@ -1506,12 +1518,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))
        {
index 340b7c0f9736103871638269b2f1679419f0b373..69e0ea47463a36a605c768105af2c0321a32b36e 100644 (file)
@@ -613,6 +613,17 @@ 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_ndims(histogram_bounds) from pg_stats
+where histogram_bounds is not null;
+ array_ndims 
+-------------
+           1
+(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
 -- test variadic polymorphic functions
 create function myleast(variadic anyarray) returns anyelement as $$
   select min($1[i]) from generate_subscripts($1,1) g(i)
index 56f90c597a8d222c43c187299373f69c4a9d85ac..6c7b1813f94cb78aaefcbc1d4b60d96e3f300639 100644 (file)
@@ -427,6 +427,13 @@ create aggregate build_group(int8, integer) (
   STYPE = int8[]
 );
 
+-- check that we can apply functions taking ANYARRAY to pg_stats
+select distinct array_ndims(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;
+
 -- test variadic polymorphic functions
 
 create function myleast(variadic anyarray) returns anyelement as $$