summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane2020-03-19 15:43:11 +0000
committerTom Lane2020-03-19 15:43:11 +0000
commit24e2885ee304cb6a94fdfc25a1a108344ed9f4f7 (patch)
tree040c3eead18de05e313c808e07aee262ef2de336 /src/test
parentfab13dc50ba5e7a12b474a7366024681bc169ac8 (diff)
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray, anycompatiblenonarray, and anycompatiblerange. They work much like anyelement, anyarray, anynonarray, and anyrange respectively, except that the actual input values need not match precisely in type. Instead, if we can find a common supertype (using the same rules as for UNION/CASE type resolution), then the parser automatically promotes the input values to that type. For example, "myfunc(anycompatible, anycompatible)" can match a call with one integer and one bigint argument, with the integer automatically promoted to bigint. With anyelement in the definition, the user would have had to cast the integer explicitly. The new types also provide a second, independent set of type variables for function matching; thus with "myfunc(anyelement, anyelement, anycompatible) returns anycompatible" the first two arguments are constrained to be the same type, but the third can be some other type, and the result has the type of the third argument. The need for more than one set of type variables was foreseen back when we first invented the polymorphic types, but we never did anything about it. Pavel Stehule, revised a bit by me Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/aggregates.out24
-rw-r--r--src/test/regress/expected/create_aggregate.out28
-rw-r--r--src/test/regress/expected/opr_sanity.out52
-rw-r--r--src/test/regress/expected/plpgsql.out101
-rw-r--r--src/test/regress/expected/polymorphism.out311
-rw-r--r--src/test/regress/expected/rangefuncs.out53
-rw-r--r--src/test/regress/expected/rangetypes.out26
-rw-r--r--src/test/regress/expected/type_sanity.out10
-rw-r--r--src/test/regress/sql/aggregates.sql4
-rw-r--r--src/test/regress/sql/create_aggregate.sql34
-rw-r--r--src/test/regress/sql/opr_sanity.sql33
-rw-r--r--src/test/regress/sql/plpgsql.sql68
-rw-r--r--src/test/regress/sql/polymorphism.sql159
-rw-r--r--src/test/regress/sql/rangefuncs.sql21
-rw-r--r--src/test/regress/sql/rangetypes.sql16
-rw-r--r--src/test/regress/sql/type_sanity.sql10
16 files changed, 934 insertions, 16 deletions
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 0073072a368..3259a22516e 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -1950,6 +1950,30 @@ select least_agg(variadic array[q1,q2]) from int8_tbl;
-4567890123456789
(1 row)
+select cleast_agg(q1,q2) from int8_tbl;
+ cleast_agg
+-------------------
+ -4567890123456789
+(1 row)
+
+select cleast_agg(4.5,f1) from int4_tbl;
+ cleast_agg
+-------------
+ -2147483647
+(1 row)
+
+select cleast_agg(variadic array[4.5,f1]) from int4_tbl;
+ cleast_agg
+-------------
+ -2147483647
+(1 row)
+
+select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl;
+ pg_typeof
+-----------
+ numeric
+(1 row)
+
-- test aggregates with common transition functions share the same states
begin work;
create type avg_state as (total bigint, count bigint);
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out
index a2eb9996e15..dcf69094237 100644
--- a/src/test/regress/expected/create_aggregate.out
+++ b/src/test/regress/expected/create_aggregate.out
@@ -59,13 +59,39 @@ create aggregate aggfns(integer,integer,text) (
sfunc = aggfns_trans, stype = aggtype[], sspace = 10000,
initcond = '{}'
);
--- variadic aggregate
+-- check error cases that would require run-time type coercion
+create function least_accum(int8, int8) returns int8 language sql as
+ 'select least($1, $2)';
+create aggregate least_agg(int4) (
+ stype = int8, sfunc = least_accum
+); -- fails
+ERROR: function least_accum(bigint, bigint) requires run-time type coercion
+drop function least_accum(int8, int8);
+create function least_accum(anycompatible, anycompatible)
+returns anycompatible language sql as
+ 'select least($1, $2)';
+create aggregate least_agg(int4) (
+ stype = int8, sfunc = least_accum
+); -- fails
+ERROR: function least_accum(bigint, bigint) requires run-time type coercion
+create aggregate least_agg(int8) (
+ stype = int8, sfunc = least_accum
+);
+drop function least_accum(anycompatible, anycompatible) cascade;
+NOTICE: drop cascades to function least_agg(bigint)
+-- variadic aggregates
create function least_accum(anyelement, variadic anyarray)
returns anyelement language sql as
'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
create aggregate least_agg(variadic items anyarray) (
stype = anyelement, sfunc = least_accum
);
+create function cleast_accum(anycompatible, variadic anycompatiblearray)
+returns anycompatible language sql as
+ 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
+create aggregate cleast_agg(variadic items anycompatiblearray) (
+ stype = anycompatible, sfunc = cleast_accum
+);
-- test ordered-set aggs using built-in support functions
create aggregate my_percentile_disc(float8 ORDER BY anyelement) (
stype = internal,
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 40468e8f497..3c0b21d633e 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -329,7 +329,7 @@ SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype IN
('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
- 'anyenum'::regtype, 'anyrange'::regtype)
+ 'anyenum'::regtype)
AND NOT
('anyelement'::regtype = ANY (p1.proargtypes) OR
'anyarray'::regtype = ANY (p1.proargtypes) OR
@@ -337,22 +337,64 @@ WHERE p1.prorettype IN
'anyenum'::regtype = ANY (p1.proargtypes) OR
'anyrange'::regtype = ANY (p1.proargtypes))
ORDER BY 2;
- oid | proname
-------+------------------
+ oid | proname
+------+----------------
2296 | anyarray_in
2502 | anyarray_recv
2312 | anyelement_in
3504 | anyenum_in
2777 | anynonarray_in
- 3832 | anyrange_in
750 | array_in
2400 | array_recv
3506 | enum_in
3532 | enum_recv
+(9 rows)
+
+-- anyrange is tighter than the rest, can only resolve from anyrange input
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype = 'anyrange'::regtype
+ AND NOT
+ 'anyrange'::regtype = ANY (p1.proargtypes)
+ORDER BY 2;
+ oid | proname
+------+------------------
+ 3832 | anyrange_in
3876 | range_gist_union
3834 | range_in
3836 | range_recv
-(13 rows)
+(4 rows)
+
+-- similarly for the anycompatible family
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype IN
+ ('anycompatible'::regtype, 'anycompatiblearray'::regtype,
+ 'anycompatiblenonarray'::regtype)
+ AND NOT
+ ('anycompatible'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblearray'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblenonarray'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblerange'::regtype = ANY (p1.proargtypes))
+ORDER BY 2;
+ oid | proname
+------+--------------------------
+ 9559 | anycompatible_in
+ 9561 | anycompatiblearray_in
+ 9563 | anycompatiblearray_recv
+ 9565 | anycompatiblenonarray_in
+(4 rows)
+
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype = 'anycompatiblerange'::regtype
+ AND NOT
+ 'anycompatiblerange'::regtype = ANY (p1.proargtypes)
+ORDER BY 2;
+ oid | proname
+------+-----------------------
+ 9567 | anycompatiblerange_in
+(1 row)
-- Look for functions that accept cstring and are neither datatype input
-- functions nor encoding conversion functions. It's almost never a good
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index dfc10e32426..d0a6b630b8f 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -1823,6 +1823,88 @@ select f1(int4range(42, 49)) as int, f1(float8range(4.5, 7.8)) as num;
(1 row)
drop function f1(x anyrange);
+create function f1(x anycompatible, y anycompatible) returns anycompatiblearray as $$
+begin
+ return array[x, y];
+end$$ language plpgsql;
+select f1(2, 4) as int, f1(2, 4.5) as num;
+ int | num
+-------+---------
+ {2,4} | {2,4.5}
+(1 row)
+
+drop function f1(x anycompatible, y anycompatible);
+create function f1(x anycompatiblerange, y anycompatible, z anycompatible) returns anycompatiblearray as $$
+begin
+ return array[lower(x), upper(x), y, z];
+end$$ language plpgsql;
+select f1(int4range(42, 49), 11, 2::smallint) as int, f1(float8range(4.5, 7.8), 7.8, 11::real) as num;
+ int | num
+--------------+------------------
+ {42,49,11,2} | {4.5,7.8,7.8,11}
+(1 row)
+
+select f1(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
+ERROR: function f1(int4range, integer, numeric) does not exist
+LINE 1: select f1(int4range(42, 49), 11, 4.5) as fail;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function f1(x anycompatiblerange, y anycompatible, z anycompatible);
+-- fail, can't infer type:
+create function f1(x anycompatible) returns anycompatiblerange as $$
+begin
+ return array[x + 1, x + 2];
+end$$ language plpgsql;
+ERROR: cannot determine result data type
+DETAIL: A result of type anycompatiblerange requires at least one input of type anycompatiblerange.
+create function f1(x anycompatiblerange, y anycompatiblearray) returns anycompatiblerange as $$
+begin
+ return x;
+end$$ language plpgsql;
+select f1(int4range(42, 49), array[11]) as int, f1(float8range(4.5, 7.8), array[7]) as num;
+ int | num
+---------+-----------
+ [42,49) | [4.5,7.8)
+(1 row)
+
+drop function f1(x anycompatiblerange, y anycompatiblearray);
+create function f1(a anyelement, b anyarray,
+ c anycompatible, d anycompatible,
+ OUT x anyarray, OUT y anycompatiblearray)
+as $$
+begin
+ x := a || b;
+ y := array[c, d];
+end$$ language plpgsql;
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2], 42, 34.5);
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-----------+-----------
+ {11,1,2} | integer[] | {42,34.5} | numeric[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2], point(1,2), point(3,4));
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-------------------+-----------
+ {11,1,2} | integer[] | {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, '{1,2}', point(1,2), '(3,4)');
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-------------------+-----------
+ {11,1,2} | integer[] | {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2.2], 42, 34.5); -- fail
+ERROR: function f1(integer, numeric[], integer, numeric) does not exist
+LINE 2: from f1(11, array[1, 2.2], 42, 34.5);
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function f1(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
--
-- Test handling of OUT parameters, including polymorphic cases.
-- Note that RETURN is optional with OUT params; we try both ways.
@@ -1940,6 +2022,25 @@ select * from duplic('foo'::text);
(1 row)
drop function duplic(anyelement);
+create function duplic(in i anycompatiblerange, out j anycompatible, out k anycompatiblearray) as $$
+begin
+ j := lower(i);
+ k := array[lower(i),upper(i)];
+ return;
+end$$ language plpgsql;
+select * from duplic(int4range(42,49));
+ j | k
+----+---------
+ 42 | {42,49}
+(1 row)
+
+select * from duplic(textrange('aaa', 'bbb'));
+ j | k
+-----+-----------
+ aaa | {aaa,bbb}
+(1 row)
+
+drop function duplic(anycompatiblerange);
--
-- test PERFORM
--
diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out
index 331562de19d..d86a7004a6f 100644
--- a/src/test/regress/expected/polymorphism.out
+++ b/src/test/regress/expected/polymorphism.out
@@ -72,6 +72,82 @@ select polyf(int4range(42, 49)) as int, polyf(float8range(4.5, 7.8)) as num;
(1 row)
drop function polyf(x anyrange);
+create function polyf(x anycompatible, y anycompatible) returns anycompatiblearray as $$
+ select array[x, y]
+$$ language sql;
+select polyf(2, 4) as int, polyf(2, 4.5) as num;
+ int | num
+-------+---------
+ {2,4} | {2,4.5}
+(1 row)
+
+drop function polyf(x anycompatible, y anycompatible);
+create function polyf(x anycompatiblerange, y anycompatible, z anycompatible) returns anycompatiblearray as $$
+ select array[lower(x), upper(x), y, z]
+$$ language sql;
+select polyf(int4range(42, 49), 11, 2::smallint) as int, polyf(float8range(4.5, 7.8), 7.8, 11::real) as num;
+ int | num
+--------------+------------------
+ {42,49,11,2} | {4.5,7.8,7.8,11}
+(1 row)
+
+select polyf(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
+ERROR: function polyf(int4range, integer, numeric) does not exist
+LINE 1: select polyf(int4range(42, 49), 11, 4.5) as fail;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function polyf(x anycompatiblerange, y anycompatible, z anycompatible);
+-- fail, can't infer type:
+create function polyf(x anycompatible) returns anycompatiblerange as $$
+ select array[x + 1, x + 2]
+$$ language sql;
+ERROR: cannot determine result data type
+DETAIL: A result of type anycompatiblerange requires at least one input of type anycompatiblerange.
+create function polyf(x anycompatiblerange, y anycompatiblearray) returns anycompatiblerange as $$
+ select x
+$$ language sql;
+select polyf(int4range(42, 49), array[11]) as int, polyf(float8range(4.5, 7.8), array[7]) as num;
+ int | num
+---------+-----------
+ [42,49) | [4.5,7.8)
+(1 row)
+
+drop function polyf(x anycompatiblerange, y anycompatiblearray);
+create function polyf(a anyelement, b anyarray,
+ c anycompatible, d anycompatible,
+ OUT x anyarray, OUT y anycompatiblearray)
+as $$
+ select a || b, array[c, d]
+$$ language sql;
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2], 42, 34.5);
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-----------+-----------
+ {11,1,2} | integer[] | {42,34.5} | numeric[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2], point(1,2), point(3,4));
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-------------------+-----------
+ {11,1,2} | integer[] | {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, '{1,2}', point(1,2), '(3,4)');
+ x | pg_typeof | y | pg_typeof
+----------+-----------+-------------------+-----------
+ {11,1,2} | integer[] | {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2.2], 42, 34.5); -- fail
+ERROR: function polyf(integer, numeric[], integer, numeric) does not exist
+LINE 2: from polyf(11, array[1, 2.2], 42, 34.5);
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function polyf(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
--
-- Polymorphic aggregate tests
--
@@ -1621,3 +1697,238 @@ View definition:
drop view dfview;
drop function dfunc(anyelement, anyelement, bool);
+--
+-- Tests for ANYCOMPATIBLE polymorphism family
+--
+create function anyctest(anycompatible, anycompatible)
+returns anycompatible as $$
+ select greatest($1, $2)
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, 12) x;
+ x | pg_typeof
+----+-----------
+ 12 | integer
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+ x | pg_typeof
+------+-----------
+ 12.3 | numeric
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, point(1,2)) x; -- fail
+ERROR: function anyctest(integer, point) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, point(1,2)) x;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select x, pg_typeof(x) from anyctest('11', '12.3') x; -- defaults to text
+ x | pg_typeof
+------+-----------
+ 12.3 | text
+(1 row)
+
+drop function anyctest(anycompatible, anycompatible);
+create function anyctest(anycompatible, anycompatible)
+returns anycompatiblearray as $$
+ select array[$1, $2]
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, 12) x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+ x | pg_typeof
+-----------+-----------
+ {11,12.3} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, array[1,2]) x; -- fail
+ERROR: function anyctest(integer, integer[]) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, array[1,2]) x;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anyctest(anycompatible, anycompatible);
+create function anyctest(anycompatible, anycompatiblearray)
+returns anycompatiblearray as $$
+ select array[$1] || $2
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, array[12]) x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, array[12.3]) x;
+ x | pg_typeof
+-----------+-----------
+ {11,12.3} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(12.3, array[13]) x;
+ x | pg_typeof
+-----------+-----------
+ {12.3,13} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(12.3, '{13,14.4}') x;
+ x | pg_typeof
+----------------+-----------
+ {12.3,13,14.4} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) x; -- fail
+ERROR: function anyctest(integer, point[]) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) ...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
+ERROR: function anyctest(integer, integer) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anyctest(anycompatible, anycompatiblearray);
+create function anyctest(anycompatible, anycompatiblerange)
+returns anycompatiblerange as $$
+ select $2
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, int4range(4,7)) x;
+ x | pg_typeof
+-------+-----------
+ [4,7) | int4range
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, numrange(4,7)) x;
+ x | pg_typeof
+-------+-----------
+ [4,7) | numrange
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
+ERROR: function anyctest(integer, integer) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, 12) x;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x; -- fail
+ERROR: function anyctest(numeric, int4range) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select x, pg_typeof(x) from anyctest(11.2, '[4,7)') x; -- fail
+ERROR: could not determine polymorphic type anycompatiblerange because input has type unknown
+drop function anyctest(anycompatible, anycompatiblerange);
+create function anyctest(anycompatiblerange, anycompatiblerange)
+returns anycompatible as $$
+ select lower($1) + upper($2)
+$$ language sql;
+select x, pg_typeof(x) from anyctest(int4range(11,12), int4range(4,7)) x;
+ x | pg_typeof
+----+-----------
+ 18 | integer
+(1 row)
+
+select x, pg_typeof(x) from anyctest(int4range(11,12), numrange(4,7)) x; -- fail
+ERROR: function anyctest(int4range, numrange) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(int4range(11,12), numra...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anyctest(anycompatiblerange, anycompatiblerange);
+-- fail, can't infer result type:
+create function anyctest(anycompatible)
+returns anycompatiblerange as $$
+ select $1
+$$ language sql;
+ERROR: cannot determine result data type
+DETAIL: A result of type anycompatiblerange requires at least one input of type anycompatiblerange.
+create function anyctest(anycompatiblenonarray, anycompatiblenonarray)
+returns anycompatiblearray as $$
+ select array[$1, $2]
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, 12) x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+ x | pg_typeof
+-----------+-----------
+ {11,12.3} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(array[11], array[1,2]) x; -- fail
+ERROR: function anyctest(integer[], integer[]) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(array[11], array[1,2]) ...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anyctest(anycompatiblenonarray, anycompatiblenonarray);
+create function anyctest(a anyelement, b anyarray,
+ c anycompatible, d anycompatible)
+returns anycompatiblearray as $$
+ select array[c, d]
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, array[1, 2], 42, 34.5) x;
+ x | pg_typeof
+-----------+-----------
+ {42,34.5} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, array[1, 2], point(1,2), point(3,4)) x;
+ x | pg_typeof
+-------------------+-----------
+ {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, '{1,2}', point(1,2), '(3,4)') x;
+ x | pg_typeof
+-------------------+-----------
+ {"(1,2)","(3,4)"} | point[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, 34.5) x; -- fail
+ERROR: function anyctest(integer, numeric[], integer, numeric) does not exist
+LINE 1: select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, ...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anyctest(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
+create function anyctest(variadic anycompatiblearray)
+returns anycompatiblearray as $$
+ select $1
+$$ language sql;
+select x, pg_typeof(x) from anyctest(11, 12) x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, 12.2) x;
+ x | pg_typeof
+-----------+-----------
+ {11,12.2} | numeric[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, '12') x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(11, '12.2') x; -- fail
+ERROR: invalid input syntax for type integer: "12.2"
+LINE 1: select x, pg_typeof(x) from anyctest(11, '12.2') x;
+ ^
+select x, pg_typeof(x) from anyctest(variadic array[11, 12]) x;
+ x | pg_typeof
+---------+-----------
+ {11,12} | integer[]
+(1 row)
+
+select x, pg_typeof(x) from anyctest(variadic array[11, 12.2]) x;
+ x | pg_typeof
+-----------+-----------
+ {11,12.2} | numeric[]
+(1 row)
+
+drop function anyctest(variadic anycompatiblearray);
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index cdfc43e8549..7eced284520 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -1557,6 +1557,59 @@ CREATE FUNCTION bad (f1 int, out f2 anyelement, out f3 anyarray)
AS 'select $1, array[$1,$1]' LANGUAGE sql;
ERROR: cannot determine result data type
DETAIL: A result of type anyelement requires at least one input of type anyelement, anyarray, anynonarray, anyenum, or anyrange.
+CREATE FUNCTION dup (f1 anycompatible, f2 anycompatiblearray, f3 out anycompatible, f4 out anycompatiblearray)
+AS 'select $1, $2' LANGUAGE sql;
+SELECT dup(22, array[44]);
+ dup
+-----------
+ (22,{44})
+(1 row)
+
+SELECT dup(4.5, array[44]);
+ dup
+------------
+ (4.5,{44})
+(1 row)
+
+SELECT dup(22, array[44::bigint]);
+ dup
+-----------
+ (22,{44})
+(1 row)
+
+SELECT *, pg_typeof(f3), pg_typeof(f4) FROM dup(22, array[44::bigint]);
+ f3 | f4 | pg_typeof | pg_typeof
+----+------+-----------+-----------
+ 22 | {44} | bigint | bigint[]
+(1 row)
+
+DROP FUNCTION dup(f1 anycompatible, f2 anycompatiblearray);
+CREATE FUNCTION dup (f1 anycompatiblerange, f2 out anycompatible, f3 out anycompatiblearray, f4 out anycompatiblerange)
+AS 'select lower($1), array[lower($1), upper($1)], $1' LANGUAGE sql;
+SELECT dup(int4range(4,7));
+ dup
+---------------------
+ (4,"{4,7}","[4,7)")
+(1 row)
+
+SELECT dup(numrange(4,7));
+ dup
+---------------------
+ (4,"{4,7}","[4,7)")
+(1 row)
+
+SELECT dup(textrange('aaa', 'bbb'));
+ dup
+-------------------------------
+ (aaa,"{aaa,bbb}","[aaa,bbb)")
+(1 row)
+
+DROP FUNCTION dup(f1 anycompatiblerange);
+-- fails, no way to deduce outputs
+CREATE FUNCTION bad (f1 anyarray, out f2 anycompatible, out f3 anycompatiblearray)
+AS 'select $1, array[$1,$1]' LANGUAGE sql;
+ERROR: cannot determine result data type
+DETAIL: A result of type anycompatible requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, or anycompatiblerange.
--
-- table functions
--
diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out
index a28741a888c..c421f5394fe 100644
--- a/src/test/regress/expected/rangetypes.out
+++ b/src/test/regress/expected/rangetypes.out
@@ -1405,6 +1405,32 @@ ERROR: function rangetypes_sql(numrange, integer[]) does not exist
LINE 1: select rangetypes_sql(numrange(1,10), ARRAY[2,20]);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+create function anycompatiblearray_anycompatiblerange_func(a anycompatiblearray, r anycompatiblerange)
+ returns anycompatible as 'select $1[1] + lower($2);' language sql;
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], int4range(10,20));
+ anycompatiblearray_anycompatiblerange_func
+--------------------------------------------
+ 11
+(1 row)
+
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], numrange(10,20));
+ anycompatiblearray_anycompatiblerange_func
+--------------------------------------------
+ 11
+(1 row)
+
+-- should fail
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,2], int4range(10,20));
+ERROR: function anycompatiblearray_anycompatiblerange_func(numeric[], int4range) does not exist
+LINE 1: select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,...
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+drop function anycompatiblearray_anycompatiblerange_func(anycompatiblearray, anycompatiblerange);
+-- should fail
+create function bogus_func(anycompatible)
+ returns anycompatiblerange as 'select int4range(1,10)' language sql;
+ERROR: cannot determine result data type
+DETAIL: A result of type anycompatiblerange requires at least one input of type anycompatiblerange.
--
-- Arrays of ranges
--
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index cd7fc03b04c..274130e7062 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -131,14 +131,16 @@ WHERE p1.typinput = p2.oid AND NOT
-- Check for type of the variadic array parameter's elements.
-- provariadic should be ANYOID if the type of the last element is ANYOID,
--- ANYELEMENTOID if the type of the last element is ANYARRAYOID, and otherwise
--- the element type corresponding to the array type.
+-- ANYELEMENTOID if the type of the last element is ANYARRAYOID,
+-- ANYCOMPATIBLEOID if the type of the last element is ANYCOMPATIBLEARRAYOID,
+-- and otherwise the element type corresponding to the array type.
SELECT oid::regprocedure, provariadic::regtype, proargtypes::regtype[]
FROM pg_proc
WHERE provariadic != 0
AND case proargtypes[array_length(proargtypes, 1)-1]
- WHEN 2276 THEN 2276 -- any -> any
- WHEN 2277 THEN 2283 -- anyarray -> anyelement
+ WHEN '"any"'::regtype THEN '"any"'::regtype
+ WHEN 'anyarray'::regtype THEN 'anyelement'::regtype
+ WHEN 'anycompatiblearray'::regtype THEN 'anycompatible'::regtype
ELSE (SELECT t.oid
FROM pg_type t
WHERE t.typarray = proargtypes[array_length(proargtypes, 1)-1])
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index 02578330a6f..5da6f4152be 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -740,6 +740,10 @@ drop view aggordview1;
select least_agg(q1,q2) from int8_tbl;
select least_agg(variadic array[q1,q2]) from int8_tbl;
+select cleast_agg(q1,q2) from int8_tbl;
+select cleast_agg(4.5,f1) from int4_tbl;
+select cleast_agg(variadic array[4.5,f1]) from int4_tbl;
+select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl;
-- test aggregates with common transition functions share the same states
begin work;
diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql
index fd7cd400c19..d4b4036fd7d 100644
--- a/src/test/regress/sql/create_aggregate.sql
+++ b/src/test/regress/sql/create_aggregate.sql
@@ -72,7 +72,31 @@ create aggregate aggfns(integer,integer,text) (
initcond = '{}'
);
--- variadic aggregate
+-- check error cases that would require run-time type coercion
+create function least_accum(int8, int8) returns int8 language sql as
+ 'select least($1, $2)';
+
+create aggregate least_agg(int4) (
+ stype = int8, sfunc = least_accum
+); -- fails
+
+drop function least_accum(int8, int8);
+
+create function least_accum(anycompatible, anycompatible)
+returns anycompatible language sql as
+ 'select least($1, $2)';
+
+create aggregate least_agg(int4) (
+ stype = int8, sfunc = least_accum
+); -- fails
+
+create aggregate least_agg(int8) (
+ stype = int8, sfunc = least_accum
+);
+
+drop function least_accum(anycompatible, anycompatible) cascade;
+
+-- variadic aggregates
create function least_accum(anyelement, variadic anyarray)
returns anyelement language sql as
'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
@@ -81,6 +105,14 @@ create aggregate least_agg(variadic items anyarray) (
stype = anyelement, sfunc = least_accum
);
+create function cleast_accum(anycompatible, variadic anycompatiblearray)
+returns anycompatible language sql as
+ 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
+
+create aggregate cleast_agg(variadic items anycompatiblearray) (
+ stype = anycompatible, sfunc = cleast_accum
+);
+
-- test ordered-set aggs using built-in support functions
create aggregate my_percentile_disc(float8 ORDER BY anyelement) (
stype = internal,
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index f06f245db3b..389d5b2464a 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -273,7 +273,7 @@ SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype IN
('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
- 'anyenum'::regtype, 'anyrange'::regtype)
+ 'anyenum'::regtype)
AND NOT
('anyelement'::regtype = ANY (p1.proargtypes) OR
'anyarray'::regtype = ANY (p1.proargtypes) OR
@@ -282,6 +282,37 @@ WHERE p1.prorettype IN
'anyrange'::regtype = ANY (p1.proargtypes))
ORDER BY 2;
+-- anyrange is tighter than the rest, can only resolve from anyrange input
+
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype = 'anyrange'::regtype
+ AND NOT
+ 'anyrange'::regtype = ANY (p1.proargtypes)
+ORDER BY 2;
+
+-- similarly for the anycompatible family
+
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype IN
+ ('anycompatible'::regtype, 'anycompatiblearray'::regtype,
+ 'anycompatiblenonarray'::regtype)
+ AND NOT
+ ('anycompatible'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblearray'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblenonarray'::regtype = ANY (p1.proargtypes) OR
+ 'anycompatiblerange'::regtype = ANY (p1.proargtypes))
+ORDER BY 2;
+
+SELECT p1.oid, p1.proname
+FROM pg_proc as p1
+WHERE p1.prorettype = 'anycompatiblerange'::regtype
+ AND NOT
+ 'anycompatiblerange'::regtype = ANY (p1.proargtypes)
+ORDER BY 2;
+
+
-- Look for functions that accept cstring and are neither datatype input
-- functions nor encoding conversion functions. It's almost never a good
-- idea to use cstring input for a function meant to be called from SQL;
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index c5e6e6e5ede..07c60c80e48 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -1618,6 +1618,62 @@ select f1(int4range(42, 49)) as int, f1(float8range(4.5, 7.8)) as num;
drop function f1(x anyrange);
+create function f1(x anycompatible, y anycompatible) returns anycompatiblearray as $$
+begin
+ return array[x, y];
+end$$ language plpgsql;
+
+select f1(2, 4) as int, f1(2, 4.5) as num;
+
+drop function f1(x anycompatible, y anycompatible);
+
+create function f1(x anycompatiblerange, y anycompatible, z anycompatible) returns anycompatiblearray as $$
+begin
+ return array[lower(x), upper(x), y, z];
+end$$ language plpgsql;
+
+select f1(int4range(42, 49), 11, 2::smallint) as int, f1(float8range(4.5, 7.8), 7.8, 11::real) as num;
+
+select f1(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
+
+drop function f1(x anycompatiblerange, y anycompatible, z anycompatible);
+
+-- fail, can't infer type:
+create function f1(x anycompatible) returns anycompatiblerange as $$
+begin
+ return array[x + 1, x + 2];
+end$$ language plpgsql;
+
+create function f1(x anycompatiblerange, y anycompatiblearray) returns anycompatiblerange as $$
+begin
+ return x;
+end$$ language plpgsql;
+
+select f1(int4range(42, 49), array[11]) as int, f1(float8range(4.5, 7.8), array[7]) as num;
+
+drop function f1(x anycompatiblerange, y anycompatiblearray);
+
+create function f1(a anyelement, b anyarray,
+ c anycompatible, d anycompatible,
+ OUT x anyarray, OUT y anycompatiblearray)
+as $$
+begin
+ x := a || b;
+ y := array[c, d];
+end$$ language plpgsql;
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2], 42, 34.5);
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2], point(1,2), point(3,4));
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, '{1,2}', point(1,2), '(3,4)');
+select x, pg_typeof(x), y, pg_typeof(y)
+ from f1(11, array[1, 2.2], 42, 34.5); -- fail
+
+drop function f1(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
+
--
-- Test handling of OUT parameters, including polymorphic cases.
-- Note that RETURN is optional with OUT params; we try both ways.
@@ -1699,6 +1755,18 @@ select * from duplic('foo'::text);
drop function duplic(anyelement);
+create function duplic(in i anycompatiblerange, out j anycompatible, out k anycompatiblearray) as $$
+begin
+ j := lower(i);
+ k := array[lower(i),upper(i)];
+ return;
+end$$ language plpgsql;
+
+select * from duplic(int4range(42,49));
+select * from duplic(textrange('aaa', 'bbb'));
+
+drop function duplic(anycompatiblerange);
+
--
-- test PERFORM
--
diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql
index 9c7b43efebb..b57591f69f6 100644
--- a/src/test/regress/sql/polymorphism.sql
+++ b/src/test/regress/sql/polymorphism.sql
@@ -53,6 +53,56 @@ select polyf(int4range(42, 49)) as int, polyf(float8range(4.5, 7.8)) as num;
drop function polyf(x anyrange);
+create function polyf(x anycompatible, y anycompatible) returns anycompatiblearray as $$
+ select array[x, y]
+$$ language sql;
+
+select polyf(2, 4) as int, polyf(2, 4.5) as num;
+
+drop function polyf(x anycompatible, y anycompatible);
+
+create function polyf(x anycompatiblerange, y anycompatible, z anycompatible) returns anycompatiblearray as $$
+ select array[lower(x), upper(x), y, z]
+$$ language sql;
+
+select polyf(int4range(42, 49), 11, 2::smallint) as int, polyf(float8range(4.5, 7.8), 7.8, 11::real) as num;
+
+select polyf(int4range(42, 49), 11, 4.5) as fail; -- range type doesn't fit
+
+drop function polyf(x anycompatiblerange, y anycompatible, z anycompatible);
+
+-- fail, can't infer type:
+create function polyf(x anycompatible) returns anycompatiblerange as $$
+ select array[x + 1, x + 2]
+$$ language sql;
+
+create function polyf(x anycompatiblerange, y anycompatiblearray) returns anycompatiblerange as $$
+ select x
+$$ language sql;
+
+select polyf(int4range(42, 49), array[11]) as int, polyf(float8range(4.5, 7.8), array[7]) as num;
+
+drop function polyf(x anycompatiblerange, y anycompatiblearray);
+
+create function polyf(a anyelement, b anyarray,
+ c anycompatible, d anycompatible,
+ OUT x anyarray, OUT y anycompatiblearray)
+as $$
+ select a || b, array[c, d]
+$$ language sql;
+
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2], 42, 34.5);
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2], point(1,2), point(3,4));
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, '{1,2}', point(1,2), '(3,4)');
+select x, pg_typeof(x), y, pg_typeof(y)
+ from polyf(11, array[1, 2.2], 42, 34.5); -- fail
+
+drop function polyf(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
+
--
-- Polymorphic aggregate tests
@@ -868,3 +918,112 @@ select * from dfview;
drop view dfview;
drop function dfunc(anyelement, anyelement, bool);
+
+--
+-- Tests for ANYCOMPATIBLE polymorphism family
+--
+
+create function anyctest(anycompatible, anycompatible)
+returns anycompatible as $$
+ select greatest($1, $2)
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, 12) x;
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+select x, pg_typeof(x) from anyctest(11, point(1,2)) x; -- fail
+select x, pg_typeof(x) from anyctest('11', '12.3') x; -- defaults to text
+
+drop function anyctest(anycompatible, anycompatible);
+
+create function anyctest(anycompatible, anycompatible)
+returns anycompatiblearray as $$
+ select array[$1, $2]
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, 12) x;
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+select x, pg_typeof(x) from anyctest(11, array[1,2]) x; -- fail
+
+drop function anyctest(anycompatible, anycompatible);
+
+create function anyctest(anycompatible, anycompatiblearray)
+returns anycompatiblearray as $$
+ select array[$1] || $2
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, array[12]) x;
+select x, pg_typeof(x) from anyctest(11, array[12.3]) x;
+select x, pg_typeof(x) from anyctest(12.3, array[13]) x;
+select x, pg_typeof(x) from anyctest(12.3, '{13,14.4}') x;
+select x, pg_typeof(x) from anyctest(11, array[point(1,2)]) x; -- fail
+select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
+
+drop function anyctest(anycompatible, anycompatiblearray);
+
+create function anyctest(anycompatible, anycompatiblerange)
+returns anycompatiblerange as $$
+ select $2
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, int4range(4,7)) x;
+select x, pg_typeof(x) from anyctest(11, numrange(4,7)) x;
+select x, pg_typeof(x) from anyctest(11, 12) x; -- fail
+select x, pg_typeof(x) from anyctest(11.2, int4range(4,7)) x; -- fail
+select x, pg_typeof(x) from anyctest(11.2, '[4,7)') x; -- fail
+
+drop function anyctest(anycompatible, anycompatiblerange);
+
+create function anyctest(anycompatiblerange, anycompatiblerange)
+returns anycompatible as $$
+ select lower($1) + upper($2)
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(int4range(11,12), int4range(4,7)) x;
+select x, pg_typeof(x) from anyctest(int4range(11,12), numrange(4,7)) x; -- fail
+
+drop function anyctest(anycompatiblerange, anycompatiblerange);
+
+-- fail, can't infer result type:
+create function anyctest(anycompatible)
+returns anycompatiblerange as $$
+ select $1
+$$ language sql;
+
+create function anyctest(anycompatiblenonarray, anycompatiblenonarray)
+returns anycompatiblearray as $$
+ select array[$1, $2]
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, 12) x;
+select x, pg_typeof(x) from anyctest(11, 12.3) x;
+select x, pg_typeof(x) from anyctest(array[11], array[1,2]) x; -- fail
+
+drop function anyctest(anycompatiblenonarray, anycompatiblenonarray);
+
+create function anyctest(a anyelement, b anyarray,
+ c anycompatible, d anycompatible)
+returns anycompatiblearray as $$
+ select array[c, d]
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, array[1, 2], 42, 34.5) x;
+select x, pg_typeof(x) from anyctest(11, array[1, 2], point(1,2), point(3,4)) x;
+select x, pg_typeof(x) from anyctest(11, '{1,2}', point(1,2), '(3,4)') x;
+select x, pg_typeof(x) from anyctest(11, array[1, 2.2], 42, 34.5) x; -- fail
+
+drop function anyctest(a anyelement, b anyarray,
+ c anycompatible, d anycompatible);
+
+create function anyctest(variadic anycompatiblearray)
+returns anycompatiblearray as $$
+ select $1
+$$ language sql;
+
+select x, pg_typeof(x) from anyctest(11, 12) x;
+select x, pg_typeof(x) from anyctest(11, 12.2) x;
+select x, pg_typeof(x) from anyctest(11, '12') x;
+select x, pg_typeof(x) from anyctest(11, '12.2') x; -- fail
+select x, pg_typeof(x) from anyctest(variadic array[11, 12]) x;
+select x, pg_typeof(x) from anyctest(variadic array[11, 12.2]) x;
+
+drop function anyctest(variadic anycompatiblearray);
diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql
index 476b4f27e25..ae3119a959e 100644
--- a/src/test/regress/sql/rangefuncs.sql
+++ b/src/test/regress/sql/rangefuncs.sql
@@ -407,6 +407,27 @@ DROP FUNCTION dup(anyelement);
CREATE FUNCTION bad (f1 int, out f2 anyelement, out f3 anyarray)
AS 'select $1, array[$1,$1]' LANGUAGE sql;
+CREATE FUNCTION dup (f1 anycompatible, f2 anycompatiblearray, f3 out anycompatible, f4 out anycompatiblearray)
+AS 'select $1, $2' LANGUAGE sql;
+SELECT dup(22, array[44]);
+SELECT dup(4.5, array[44]);
+SELECT dup(22, array[44::bigint]);
+SELECT *, pg_typeof(f3), pg_typeof(f4) FROM dup(22, array[44::bigint]);
+
+DROP FUNCTION dup(f1 anycompatible, f2 anycompatiblearray);
+
+CREATE FUNCTION dup (f1 anycompatiblerange, f2 out anycompatible, f3 out anycompatiblearray, f4 out anycompatiblerange)
+AS 'select lower($1), array[lower($1), upper($1)], $1' LANGUAGE sql;
+SELECT dup(int4range(4,7));
+SELECT dup(numrange(4,7));
+SELECT dup(textrange('aaa', 'bbb'));
+
+DROP FUNCTION dup(f1 anycompatiblerange);
+
+-- fails, no way to deduce outputs
+CREATE FUNCTION bad (f1 anyarray, out f2 anycompatible, out f3 anycompatiblearray)
+AS 'select $1, array[$1,$1]' LANGUAGE sql;
+
--
-- table functions
--
diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql
index 85eaa9b34c6..4048b1d1854 100644
--- a/src/test/regress/sql/rangetypes.sql
+++ b/src/test/regress/sql/rangetypes.sql
@@ -456,6 +456,22 @@ create function rangetypes_sql(q anyrange, b anyarray, out c anyelement)
select rangetypes_sql(int4range(1,10), ARRAY[2,20]);
select rangetypes_sql(numrange(1,10), ARRAY[2,20]); -- match failure
+create function anycompatiblearray_anycompatiblerange_func(a anycompatiblearray, r anycompatiblerange)
+ returns anycompatible as 'select $1[1] + lower($2);' language sql;
+
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], int4range(10,20));
+
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1,2], numrange(10,20));
+
+-- should fail
+select anycompatiblearray_anycompatiblerange_func(ARRAY[1.1,2], int4range(10,20));
+
+drop function anycompatiblearray_anycompatiblerange_func(anycompatiblearray, anycompatiblerange);
+
+-- should fail
+create function bogus_func(anycompatible)
+ returns anycompatiblerange as 'select int4range(1,10)' language sql;
+
--
-- Arrays of ranges
--
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index fed413bf98a..4b492ce0625 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -106,15 +106,17 @@ WHERE p1.typinput = p2.oid AND NOT
-- Check for type of the variadic array parameter's elements.
-- provariadic should be ANYOID if the type of the last element is ANYOID,
--- ANYELEMENTOID if the type of the last element is ANYARRAYOID, and otherwise
--- the element type corresponding to the array type.
+-- ANYELEMENTOID if the type of the last element is ANYARRAYOID,
+-- ANYCOMPATIBLEOID if the type of the last element is ANYCOMPATIBLEARRAYOID,
+-- and otherwise the element type corresponding to the array type.
SELECT oid::regprocedure, provariadic::regtype, proargtypes::regtype[]
FROM pg_proc
WHERE provariadic != 0
AND case proargtypes[array_length(proargtypes, 1)-1]
- WHEN 2276 THEN 2276 -- any -> any
- WHEN 2277 THEN 2283 -- anyarray -> anyelement
+ WHEN '"any"'::regtype THEN '"any"'::regtype
+ WHEN 'anyarray'::regtype THEN 'anyelement'::regtype
+ WHEN 'anycompatiblearray'::regtype THEN 'anycompatible'::regtype
ELSE (SELECT t.oid
FROM pg_type t
WHERE t.typarray = proargtypes[array_length(proargtypes, 1)-1])