diff options
| author | Tom Lane | 2008-07-16 01:30:23 +0000 |
|---|---|---|
| committer | Tom Lane | 2008-07-16 01:30:23 +0000 |
| commit | d89737d31c03d90a2b0412e63953493576a2a3d7 (patch) | |
| tree | 0afc63e59fae7ec3c53339641a6f65e6a04733d2 /src/test/regress | |
| parent | 2c773296f88fe800315ca1bf131287662ecef999 (diff) | |
Support "variadic" functions, which can accept a variable number of arguments
so long as all the trailing arguments are of the same (non-array) type.
The function receives them as a single array argument (which is why they
have to all be the same type).
It might be useful to extend this facility to aggregates, but this patch
doesn't do that.
This patch imposes a noticeable slowdown on function lookup --- a follow-on
patch will fix that by adding a redundant column to pg_proc.
Pavel Stehule
Diffstat (limited to 'src/test/regress')
| -rw-r--r-- | src/test/regress/expected/plpgsql.out | 90 | ||||
| -rw-r--r-- | src/test/regress/expected/polymorphism.out | 108 | ||||
| -rw-r--r-- | src/test/regress/sql/plpgsql.sql | 47 | ||||
| -rw-r--r-- | src/test/regress/sql/polymorphism.sql | 43 |
4 files changed, 288 insertions, 0 deletions
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 582c06785a8..1e4ef2645fa 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -3544,3 +3544,93 @@ select case_test(13); drop function catch(); drop function case_test(bigint); +-- test variadic functions +create or replace function vari(variadic int[]) +returns void as $$ +begin + for i in array_lower($1,1)..array_upper($1,1) loop + raise notice '%', $1[i]; + end loop; end; +$$ language plpgsql; +select vari(1,2,3,4,5); +NOTICE: 1 +NOTICE: 2 +NOTICE: 3 +NOTICE: 4 +NOTICE: 5 + vari +------ + +(1 row) + +select vari(3,4,5); +NOTICE: 3 +NOTICE: 4 +NOTICE: 5 + vari +------ + +(1 row) + +select vari(variadic array[5,6,7]); +NOTICE: 5 +NOTICE: 6 +NOTICE: 7 + vari +------ + +(1 row) + +drop function vari(int[]); +-- coercion test +create or replace function pleast(variadic numeric[]) +returns numeric as $$ +declare aux numeric = $1[array_lower($1,1)]; +begin + for i in array_lower($1,1)+1..array_upper($1,1) loop + if $1[i] < aux then aux := $1[i]; end if; + end loop; + return aux; +end; +$$ language plpgsql immutable strict; +select pleast(10,1,2,3,-16); + pleast +-------- + -16 +(1 row) + +select pleast(10.2,2.2,-1.1); + pleast +-------- + -1.1 +(1 row) + +select pleast(10.2,10, -20); + pleast +-------- + -20 +(1 row) + +select pleast(10,20, -1.0); + pleast +-------- + -1.0 +(1 row) + +-- in case of conflict, non-variadic version is preferred +create or replace function pleast(numeric) +returns numeric as $$ +begin + raise notice 'non-variadic function called'; + return $1; +end; +$$ language plpgsql immutable strict; +select pleast(10); +NOTICE: non-variadic function called + pleast +-------- + 10 +(1 row) + +drop function pleast(numeric[]); +drop function pleast(numeric); diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out index a208203c6d3..3779f8e58ce 100644 --- a/src/test/regress/expected/polymorphism.out +++ b/src/test/regress/expected/polymorphism.out @@ -613,3 +613,111 @@ create aggregate build_group(int8, integer) ( SFUNC = add_group, STYPE = int8[] ); +-- test variadic polymorphic functions +create function myleast(variadic anyarray) returns anyelement as $$ + select min($1[i]) from generate_subscripts($1,1) g(i) +$$ language sql immutable strict; +select myleast(10, 1, 20, 33); + myleast +--------- + 1 +(1 row) + +select myleast(1.1, 0.22, 0.55); + myleast +--------- + 0.22 +(1 row) + +select myleast('z'::text); + myleast +--------- + z +(1 row) + +select myleast(); -- fail +ERROR: function myleast() does not exist +LINE 1: select myleast(); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +-- test with variadic call parameter +select myleast(variadic array[1,2,3,4,-1]); + myleast +--------- + -1 +(1 row) + +select myleast(variadic array[1.1, -5.5]); + myleast +--------- + -5.5 +(1 row) + +--test with empty variadic call parameter +select myleast(variadic array[]::int[]); + myleast +--------- + +(1 row) + +-- an example with some ordinary arguments too +create function concat(text, variadic anyarray) returns text as $$ + select array_to_string($2, $1); +$$ language sql immutable strict; +select concat('%', 1, 2, 3, 4, 5); + concat +----------- + 1%2%3%4%5 +(1 row) + +select concat('|', 'a'::text, 'b', 'c'); + concat +-------- + a|b|c +(1 row) + +select concat('|', variadic array[1,2,33]); + concat +-------- + 1|2|33 +(1 row) + +select concat('|', variadic array[]::int[]); + concat +-------- + +(1 row) + +drop function concat(text, anyarray); +-- mix variadic with anyelement +create function formarray(anyelement, variadic anyarray) returns anyarray as $$ + select array_prepend($1, $2); +$$ language sql immutable strict; +select formarray(1,2,3,4,5); + formarray +------------- + {1,2,3,4,5} +(1 row) + +select formarray(1.1, variadic array[1.2,55.5]); + formarray +---------------- + {1.1,1.2,55.5} +(1 row) + +select formarray(1.1, array[1.2,55.5]); -- fail without variadic +ERROR: function formarray(numeric, numeric[]) does not exist +LINE 1: select formarray(1.1, array[1.2,55.5]); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +select formarray(1, 'x'::text); -- fail, type mismatch +ERROR: function formarray(integer, text) does not exist +LINE 1: select formarray(1, 'x'::text); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +select formarray(1, variadic array['x'::text]); -- fail, type mismatch +ERROR: function formarray(integer, text[]) does not exist +LINE 1: select formarray(1, variadic array['x'::text]); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +drop function formarray(anyelement, variadic anyarray); diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 0267dda30ca..4d45dba2efc 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -2878,3 +2878,50 @@ select case_test(13); drop function catch(); drop function case_test(bigint); + +-- test variadic functions + +create or replace function vari(variadic int[]) +returns void as $$ +begin + for i in array_lower($1,1)..array_upper($1,1) loop + raise notice '%', $1[i]; + end loop; end; +$$ language plpgsql; + +select vari(1,2,3,4,5); +select vari(3,4,5); +select vari(variadic array[5,6,7]); + +drop function vari(int[]); + +-- coercion test +create or replace function pleast(variadic numeric[]) +returns numeric as $$ +declare aux numeric = $1[array_lower($1,1)]; +begin + for i in array_lower($1,1)+1..array_upper($1,1) loop + if $1[i] < aux then aux := $1[i]; end if; + end loop; + return aux; +end; +$$ language plpgsql immutable strict; + +select pleast(10,1,2,3,-16); +select pleast(10.2,2.2,-1.1); +select pleast(10.2,10, -20); +select pleast(10,20, -1.0); + +-- in case of conflict, non-variadic version is preferred +create or replace function pleast(numeric) +returns numeric as $$ +begin + raise notice 'non-variadic function called'; + return $1; +end; +$$ language plpgsql immutable strict; + +select pleast(10); + +drop function pleast(numeric[]); +drop function pleast(numeric); diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql index 2df963952f4..a4e2b2da3e3 100644 --- a/src/test/regress/sql/polymorphism.sql +++ b/src/test/regress/sql/polymorphism.sql @@ -426,3 +426,46 @@ create aggregate build_group(int8, integer) ( SFUNC = add_group, STYPE = int8[] ); + +-- test variadic polymorphic functions + +create function myleast(variadic anyarray) returns anyelement as $$ + select min($1[i]) from generate_subscripts($1,1) g(i) +$$ language sql immutable strict; + +select myleast(10, 1, 20, 33); +select myleast(1.1, 0.22, 0.55); +select myleast('z'::text); +select myleast(); -- fail + +-- test with variadic call parameter +select myleast(variadic array[1,2,3,4,-1]); +select myleast(variadic array[1.1, -5.5]); + +--test with empty variadic call parameter +select myleast(variadic array[]::int[]); + +-- an example with some ordinary arguments too +create function concat(text, variadic anyarray) returns text as $$ + select array_to_string($2, $1); +$$ language sql immutable strict; + +select concat('%', 1, 2, 3, 4, 5); +select concat('|', 'a'::text, 'b', 'c'); +select concat('|', variadic array[1,2,33]); +select concat('|', variadic array[]::int[]); + +drop function concat(text, anyarray); + +-- mix variadic with anyelement +create function formarray(anyelement, variadic anyarray) returns anyarray as $$ + select array_prepend($1, $2); +$$ language sql immutable strict; + +select formarray(1,2,3,4,5); +select formarray(1.1, variadic array[1.2,55.5]); +select formarray(1.1, array[1.2,55.5]); -- fail without variadic +select formarray(1, 'x'::text); -- fail, type mismatch +select formarray(1, variadic array['x'::text]); -- fail, type mismatch + +drop function formarray(anyelement, variadic anyarray); |
