]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
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:46:02 +0000 (19:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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;