Restore enforce_generic_type_consistency's pre-8.3 behavior of allowing an
authorTom Lane <[email protected]>
Sun, 14 Dec 2008 19:46:02 +0000 (19:46 +0000)
committerTom Lane <[email protected]>
Sun, 14 Dec 2008 19:46:02 +0000 (19:46 +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 7933283cabc60be3ba2b36fb3356ab58bc95eac9..a2633f5785c1dcc6e232e2590e81b3a7e5b00124 100644 (file)
@@ -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))
        {
index a208203c6d39881a911919f9a221ce5c0e96a7b0..5741b075be97254fd0c5885a7678afd8a03cad7e 100644 (file)
@@ -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
index 2df963952f4e2ff9583a5ad63a4520cbb6df3d51..015443ce22c54221e5abd0435d2cecdf2bb6daac 100644 (file)
@@ -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;