Remove bogus Assert, add some regression test cases showing why.
Commit 77ec5affb 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
This commit is contained in:
parent
c6b92041d3
commit
07871d40c7
@ -1813,7 +1813,8 @@ check_generic_type_consistency(const Oid *actual_arg_types,
|
|||||||
* arguments to the proper type.
|
* arguments to the proper type.
|
||||||
*
|
*
|
||||||
* Rules are applied to the function's return type (possibly altering it)
|
* Rules are applied to the function's return type (possibly altering it)
|
||||||
* if it is declared as a polymorphic type:
|
* if it is declared as a polymorphic type and there is at least one
|
||||||
|
* polymorphic argument type:
|
||||||
*
|
*
|
||||||
* 1) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
* 1) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
||||||
* argument's actual type as the function's return type.
|
* argument's actual type as the function's return type.
|
||||||
@ -1821,11 +1822,11 @@ check_generic_type_consistency(const Oid *actual_arg_types,
|
|||||||
* argument's actual type as the function's return type.
|
* argument's actual type as the function's return type.
|
||||||
* 3) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
|
* 3) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
|
||||||
* use the argument's actual type as the function's return type.
|
* use the argument's actual type as the function's return type.
|
||||||
* 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, there should be
|
* 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
|
||||||
* at least one ANYELEMENT, ANYARRAY, or ANYRANGE input; deduce the
|
* at least one ANYELEMENT, ANYARRAY, or ANYRANGE input, deduce the
|
||||||
* return type from those inputs, or throw error if we can't.
|
* return type from those inputs, or throw error if we can't.
|
||||||
* 5) Otherwise, if return type is ANYRANGE, throw error. (There should
|
* 5) Otherwise, if return type is ANYRANGE, throw error. (We have no way to
|
||||||
* be at least one ANYRANGE input, since CREATE FUNCTION enforces that.)
|
* select a specific range type if the arguments don't include ANYRANGE.)
|
||||||
* 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
* 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
||||||
* (alone or in combination with plain ANYELEMENT), we add the extra
|
* (alone or in combination with plain ANYELEMENT), we add the extra
|
||||||
* condition that the ANYELEMENT type must be an enum.
|
* condition that the ANYELEMENT type must be an enum.
|
||||||
@ -1869,6 +1870,11 @@ check_generic_type_consistency(const Oid *actual_arg_types,
|
|||||||
* input to an ANYCOMPATIBLEARRAY argument, but at present that seems useless
|
* input to an ANYCOMPATIBLEARRAY argument, but at present that seems useless
|
||||||
* as well, since there's no value in using ANYCOMPATIBLEARRAY unless there's
|
* as well, since there's no value in using ANYCOMPATIBLEARRAY unless there's
|
||||||
* at least one other ANYCOMPATIBLE-family argument or result.
|
* at least one other ANYCOMPATIBLE-family argument or result.
|
||||||
|
*
|
||||||
|
* Also, if there are no arguments declared to be of polymorphic types,
|
||||||
|
* we'll return the rettype unmodified even if it's polymorphic. This should
|
||||||
|
* never occur for user-declared functions, because CREATE FUNCTION prevents
|
||||||
|
* it. But it does happen for some built-in functions, such as array_in().
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
enforce_generic_type_consistency(const Oid *actual_arg_types,
|
enforce_generic_type_consistency(const Oid *actual_arg_types,
|
||||||
@ -2042,13 +2048,10 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Fast Track: if none of the arguments are polymorphic, return the
|
* Fast Track: if none of the arguments are polymorphic, return the
|
||||||
* unmodified rettype. We assume it can't be polymorphic either.
|
* unmodified rettype. Not our job to resolve it if it's polymorphic.
|
||||||
*/
|
*/
|
||||||
if (n_poly_args == 0 && !have_poly_anycompatible)
|
if (n_poly_args == 0 && !have_poly_anycompatible)
|
||||||
{
|
|
||||||
Assert(!IsPolymorphicType(rettype));
|
|
||||||
return rettype;
|
return rettype;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check matching of family-1 polymorphic arguments, if any */
|
/* Check matching of family-1 polymorphic arguments, if any */
|
||||||
if (n_poly_args)
|
if (n_poly_args)
|
||||||
|
@ -852,6 +852,19 @@ where histogram_bounds is not null;
|
|||||||
-- (WHERE clause here is to avoid possibly getting a collation error instead)
|
-- (WHERE clause here is to avoid possibly getting a collation error instead)
|
||||||
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
|
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
|
||||||
ERROR: cannot compare arrays of different element types
|
ERROR: cannot compare arrays of different element types
|
||||||
|
-- another corner case is the input functions for polymorphic pseudotypes
|
||||||
|
select array_in('{1,2,3}','int4'::regtype,-1); -- this has historically worked
|
||||||
|
array_in
|
||||||
|
----------
|
||||||
|
{1,2,3}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select * from array_in('{1,2,3}','int4'::regtype,-1); -- this not
|
||||||
|
ERROR: function "array_in" in FROM has unsupported return type anyarray
|
||||||
|
LINE 1: select * from array_in('{1,2,3}','int4'::regtype,-1);
|
||||||
|
^
|
||||||
|
select anyrange_in('[10,20)','int4range'::regtype,-1);
|
||||||
|
ERROR: cannot accept a value of type anyrange
|
||||||
-- test variadic polymorphic functions
|
-- test variadic polymorphic functions
|
||||||
create function myleast(variadic anyarray) returns anyelement as $$
|
create function myleast(variadic anyarray) returns anyelement as $$
|
||||||
select min($1[i]) from generate_subscripts($1,1) g(i)
|
select min($1[i]) from generate_subscripts($1,1) g(i)
|
||||||
|
@ -577,6 +577,11 @@ where histogram_bounds is not null;
|
|||||||
-- (WHERE clause here is to avoid possibly getting a collation error instead)
|
-- (WHERE clause here is to avoid possibly getting a collation error instead)
|
||||||
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
|
select max(histogram_bounds) from pg_stats where tablename = 'pg_am';
|
||||||
|
|
||||||
|
-- another corner case is the input functions for polymorphic pseudotypes
|
||||||
|
select array_in('{1,2,3}','int4'::regtype,-1); -- this has historically worked
|
||||||
|
select * from array_in('{1,2,3}','int4'::regtype,-1); -- this not
|
||||||
|
select anyrange_in('[10,20)','int4range'::regtype,-1);
|
||||||
|
|
||||||
-- test variadic polymorphic functions
|
-- test variadic polymorphic functions
|
||||||
|
|
||||||
create function myleast(variadic anyarray) returns anyelement as $$
|
create function myleast(variadic anyarray) returns anyelement as $$
|
||||||
|
Loading…
x
Reference in New Issue
Block a user