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

Lines changed: 12 additions & 9 deletions
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

Lines changed: 13 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy