Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 07871d4

Browse files
committed
Remove bogus Assert, add some regression test cases showing why.
Commit 77ec5af added an assertion to enforce_generic_type_consistency that boils down to "if the function result is polymorphic, there must be at least one polymorphic argument". This should be true for user-created functions, but there are built-in functions for which it's not true, as pointed out by Jaime Casanova. Hence, go back to the old behavior of leaving the return type alone. There's only a limited amount of stuff you can do with such a function result, but it does work to some extent; add some regression test cases to ensure we don't break that again. Discussion: https://postgr.es/m/CAJGNTeMbhtsCUZgJJ8h8XxAJbK7U2ipsX8wkHRtZRz-NieT8RA@mail.gmail.com
1 parent c6b9204 commit 07871d4

File tree

3 files changed

+30
-9
lines changed

3 files changed

+30
-9
lines changed

src/backend/parser/parse_coerce.c

+12-9
Original file line numberDiff line numberDiff line change
@@ -1813,19 +1813,20 @@ check_generic_type_consistency(const Oid *actual_arg_types,
18131813
* arguments to the proper type.
18141814
*
18151815
* Rules are applied to the function's return type (possibly altering it)
1816-
* if it is declared as a polymorphic type:
1816+
* if it is declared as a polymorphic type and there is at least one
1817+
* polymorphic argument type:
18171818
*
18181819
* 1) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
18191820
* argument's actual type as the function's return type.
18201821
* 2) If return type is ANYARRAY, and any argument is ANYARRAY, use the
18211822
* argument's actual type as the function's return type.
18221823
* 3) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
18231824
* use the argument's actual type as the function's return type.
1824-
* 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, there should be
1825-
* at least one ANYELEMENT, ANYARRAY, or ANYRANGE input; deduce the
1825+
* 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
1826+
* at least one ANYELEMENT, ANYARRAY, or ANYRANGE input, deduce the
18261827
* return type from those inputs, or throw error if we can't.
1827-
* 5) Otherwise, if return type is ANYRANGE, throw error. (There should
1828-
* be at least one ANYRANGE input, since CREATE FUNCTION enforces that.)
1828+
* 5) Otherwise, if return type is ANYRANGE, throw error. (We have no way to
1829+
* select a specific range type if the arguments don't include ANYRANGE.)
18291830
* 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
18301831
* (alone or in combination with plain ANYELEMENT), we add the extra
18311832
* condition that the ANYELEMENT type must be an enum.
@@ -1869,6 +1870,11 @@ check_generic_type_consistency(const Oid *actual_arg_types,
18691870
* input to an ANYCOMPATIBLEARRAY argument, but at present that seems useless
18701871
* as well, since there's no value in using ANYCOMPATIBLEARRAY unless there's
18711872
* at least one other ANYCOMPATIBLE-family argument or result.
1873+
*
1874+
* Also, if there are no arguments declared to be of polymorphic types,
1875+
* we'll return the rettype unmodified even if it's polymorphic. This should
1876+
* never occur for user-declared functions, because CREATE FUNCTION prevents
1877+
* it. But it does happen for some built-in functions, such as array_in().
18721878
*/
18731879
Oid
18741880
enforce_generic_type_consistency(const Oid *actual_arg_types,
@@ -2042,13 +2048,10 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
20422048

20432049
/*
20442050
* Fast Track: if none of the arguments are polymorphic, return the
2045-
* unmodified rettype. We assume it can't be polymorphic either.
2051+
* unmodified rettype. Not our job to resolve it if it's polymorphic.
20462052
*/
20472053
if (n_poly_args == 0 && !have_poly_anycompatible)
2048-
{
2049-
Assert(!IsPolymorphicType(rettype));
20502054
return rettype;
2051-
}
20522055

20532056
/* Check matching of family-1 polymorphic arguments, if any */
20542057
if (n_poly_args)

src/test/regress/expected/polymorphism.out

+13
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,19 @@ where histogram_bounds is not null;
852852
-- (WHERE clause here is to avoid possibly getting a collation error instead)
853853
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
854854
ERROR: cannot compare arrays of different element types
855+
-- another corner case is the input functions for polymorphic pseudotypes
856+
select array_in('{1,2,3}','int4'::regtype,-1); -- this has historically worked
857+
array_in
858+
----------
859+
{1,2,3}
860+
(1 row)
861+
862+
select * from array_in('{1,2,3}','int4'::regtype,-1); -- this not
863+
ERROR: function "array_in" in FROM has unsupported return type anyarray
864+
LINE 1: select * from array_in('{1,2,3}','int4'::regtype,-1);
865+
^
866+
select anyrange_in('[10,20)','int4range'::regtype,-1);
867+
ERROR: cannot accept a value of type anyrange
855868
-- test variadic polymorphic functions
856869
create function myleast(variadic anyarray) returns anyelement as $$
857870
select min($1[i]) from generate_subscripts($1,1) g(i)

src/test/regress/sql/polymorphism.sql

+5
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,11 @@ where histogram_bounds is not null;
577577
-- (WHERE clause here is to avoid possibly getting a collation error instead)
578578
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
579579

580+
-- another corner case is the input functions for polymorphic pseudotypes
581+
select array_in('{1,2,3}','int4'::regtype,-1); -- this has historically worked
582+
select * from array_in('{1,2,3}','int4'::regtype,-1); -- this not
583+
select anyrange_in('[10,20)','int4range'::regtype,-1);
584+
580585
-- test variadic polymorphic functions
581586

582587
create function myleast(variadic anyarray) returns anyelement as $$

0 commit comments

Comments
 (0)