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 /doc/src | |
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 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 16 | ||||
-rw-r--r-- | doc/src/sgml/extend.sgml | 12 | ||||
-rw-r--r-- | doc/src/sgml/plpgsql.sgml | 9 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_function.sgml | 11 | ||||
-rw-r--r-- | doc/src/sgml/ref/comment.sgml | 11 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_function.sgml | 7 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_function.sgml | 11 | ||||
-rw-r--r-- | doc/src/sgml/typeconv.sgml | 14 | ||||
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 136 |
9 files changed, 195 insertions, 32 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 76198b0f832..7accea0f76c 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.168 2008/07/14 00:51:45 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.169 2008/07/16 01:30:21 tgl Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -3643,7 +3643,8 @@ <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry> An array with the data types of the function arguments. This includes - only input arguments (including <literal>INOUT</literal> arguments), and thus represents + only input arguments (including <literal>INOUT</literal> and + <literal>VARIADIC</> arguments), and thus represents the call signature of the function </entry> </row> @@ -3654,8 +3655,9 @@ <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry> An array with the data types of the function arguments. This includes - all arguments (including <literal>OUT</literal> and <literal>INOUT</literal> arguments); however, if all the - arguments are IN arguments, this field will be null. + all arguments (including <literal>OUT</literal> and + <literal>INOUT</literal> arguments); however, if all the + arguments are <literal>IN</literal> arguments, this field will be null. Note that subscripting is 1-based, whereas for historical reasons <structfield>proargtypes</> is subscripted from 0 </entry> @@ -3669,8 +3671,10 @@ An array with the modes of the function arguments, encoded as <literal>i</literal> for <literal>IN</> arguments, <literal>o</literal> for <literal>OUT</> arguments, - <literal>b</literal> for <literal>INOUT</> arguments. - If all the arguments are <literal>IN</literal> arguments, this field will be null. + <literal>b</literal> for <literal>INOUT</> arguments, + <literal>v</literal> for <literal>VARIADIC</> arguments. + If all the arguments are <literal>IN</literal> arguments, + this field will be null. Note that subscripts correspond to positions of <structfield>proallargtypes</> not <structfield>proargtypes</> </entry> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index e2805b41917..caeda7e75ca 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.36 2007/08/31 21:33:48 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.37 2008/07/16 01:30:21 tgl Exp $ --> <chapter id="extend"> <title>Extending <acronym>SQL</acronym></title> @@ -254,6 +254,16 @@ is equivalent to declaring it as <literal>f(anyenum, anyenum)</>: both actual arguments have to be the same enum type. </para> + + <para> + A variadic function (one taking a variable number of arguments, as in + <xref linkend="xfunc-sql-variadic-functions">) can be + polymorphic: this is accomplished by declaring its last parameter as + <literal>VARIADIC</> <type>anyarray</>. For purposes of argument + matching and determining the actual result type, such a function behaves + the same as if you had written the appropriate number of + <type>anynonarray</> parameters. + </para> </sect2> </sect1> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index cd1531999b7..42bd6048b68 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.131 2008/06/27 01:52:59 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.132 2008/07/16 01:30:21 tgl Exp $ --> <chapter id="plpgsql"> <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title> @@ -122,6 +122,13 @@ </para> <para> + <application>PL/pgSQL</> functions can be declared to accept a variable + number of arguments by using the <literal>VARIADIC</> marker. This + works exactly the same way as for SQL functions, as discussed in + <xref linkend="xfunc-sql-variadic-functions">. + </para> + + <para> <application>PL/pgSQL</> functions can also be declared to accept and return the polymorphic types <type>anyelement</type>, <type>anyarray</type>, <type>anynonarray</type>, diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml index bee2f6f4390..abedfe7d50b 100644 --- a/doc/src/sgml/ref/alter_function.sgml +++ b/doc/src/sgml/ref/alter_function.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.15 2007/09/03 18:46:29 tgl Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.16 2008/07/16 01:30:21 tgl Exp $ PostgreSQL documentation --> @@ -81,13 +81,14 @@ where <replaceable class="PARAMETER">action</replaceable> is one of: <listitem> <para> - The mode of an argument: either <literal>IN</>, <literal>OUT</>, - or <literal>INOUT</>. If omitted, the default is <literal>IN</>. + The mode of an argument: <literal>IN</>, <literal>OUT</>, + <literal>INOUT</>, or <literal>VARIADIC</>. + If omitted, the default is <literal>IN</>. Note that <command>ALTER FUNCTION</command> does not actually pay any attention to <literal>OUT</> arguments, since only the input arguments are needed to determine the function's identity. - So it is sufficient to list the <literal>IN</> and <literal>INOUT</> - arguments. + So it is sufficient to list the <literal>IN</>, <literal>INOUT</>, + and <literal>VARIADIC</> arguments. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index c8993e915b8..2da64f87aca 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/comment.sgml,v 1.36 2007/08/21 21:08:47 tgl Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/comment.sgml,v 1.37 2008/07/16 01:30:21 tgl Exp $ PostgreSQL documentation --> @@ -136,13 +136,14 @@ COMMENT ON <listitem> <para> - The mode of a function argument: either <literal>IN</>, <literal>OUT</>, - or <literal>INOUT</>. If omitted, the default is <literal>IN</>. + The mode of a function argument: <literal>IN</>, <literal>OUT</>, + <literal>INOUT</>, or <literal>VARIADIC</>. + If omitted, the default is <literal>IN</>. Note that <command>COMMENT ON FUNCTION</command> does not actually pay any attention to <literal>OUT</> arguments, since only the input arguments are needed to determine the function's identity. - So it is sufficient to list the <literal>IN</> and <literal>INOUT</> - arguments. + So it is sufficient to list the <literal>IN</>, <literal>INOUT</>, + and <literal>VARIADIC</> arguments. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index 8c542982d52..18b9bf7beea 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.78 2007/09/11 00:06:41 tgl Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.79 2008/07/16 01:30:21 tgl Exp $ --> <refentry id="SQL-CREATEFUNCTION"> @@ -101,8 +101,9 @@ CREATE [ OR REPLACE ] FUNCTION <listitem> <para> - The mode of an argument: either <literal>IN</>, <literal>OUT</>, - or <literal>INOUT</>. If omitted, the default is <literal>IN</>. + The mode of an argument: <literal>IN</>, <literal>OUT</>, + <literal>INOUT</>, or <literal>VARIADIC</>. + If omitted, the default is <literal>IN</>. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/drop_function.sgml b/doc/src/sgml/ref/drop_function.sgml index bf39f5356dd..256cafe684f 100644 --- a/doc/src/sgml/ref/drop_function.sgml +++ b/doc/src/sgml/ref/drop_function.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/drop_function.sgml,v 1.33 2007/01/31 23:26:03 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/drop_function.sgml,v 1.34 2008/07/16 01:30:21 tgl Exp $ PostgreSQL documentation --> @@ -65,13 +65,14 @@ DROP FUNCTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ( <listitem> <para> - The mode of an argument: either <literal>IN</>, <literal>OUT</>, - or <literal>INOUT</>. If omitted, the default is <literal>IN</>. + The mode of an argument: <literal>IN</>, <literal>OUT</>, + <literal>INOUT</>, or <literal>VARIADIC</>. + If omitted, the default is <literal>IN</>. Note that <command>DROP FUNCTION</command> does not actually pay any attention to <literal>OUT</> arguments, since only the input arguments are needed to determine the function's identity. - So it is sufficient to list the <literal>IN</> and <literal>INOUT</> - arguments. + So it is sufficient to list the <literal>IN</>, <literal>INOUT</>, + and <literal>VARIADIC</> arguments. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index 451555cd022..4f04801210b 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.54 2008/07/11 07:02:43 petere Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.55 2008/07/16 01:30:21 tgl Exp $ --> <chapter Id="typeconv"> <title>Type Conversion</title> @@ -503,6 +503,18 @@ different argument types are considered on an equal footing regardless of search path position. </para> </step> +<step performance="optional"> +<para> +If a function is declared with a <literal>VARIADIC</> array parameter, and +the call does not use the <literal>VARIADIC</> keyword, then the function +is treated as if the array parameter were replaced by one or more occurrences +of its element type, as needed to match the call. After such expansion the +function might have effective argument types identical to some non-variadic +function. In that case the function appearing earlier in the search path is +used, or if the two functions are in the same schema, the non-variadic one is +selected. +</para> +</step> </substeps> </step> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index efee5d8d469..55ed719ec64 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.130 2007/11/10 20:14:36 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.131 2008/07/16 01:30:21 tgl Exp $ --> <sect1 id="xfunc"> <title>User-Defined Functions</title> @@ -495,7 +495,7 @@ SELECT getname(new_emp()); None (1 row) </screen> - </para> + </para> <para> Still another way to use a function that returns a composite type is to @@ -505,7 +505,7 @@ SELECT getname(new_emp()); </sect2> <sect2 id="xfunc-output-parameters"> - <title>Functions with Output Parameters</title> + <title><acronym>SQL</> Functions with Output Parameters</title> <indexterm> <primary>function</primary> @@ -578,9 +578,75 @@ DROP FUNCTION sum_n_product (int, int); <para> Parameters can be marked as <literal>IN</> (the default), - <literal>OUT</>, or <literal>INOUT</>. An <literal>INOUT</> + <literal>OUT</>, <literal>INOUT</>, or <literal>VARIADIC</>. + An <literal>INOUT</> parameter serves as both an input parameter (part of the calling argument list) and an output parameter (part of the result record type). + <literal>VARIADIC</> parameters are input parameters, but are treated + specially as described next. + </para> + </sect2> + + <sect2 id="xfunc-sql-variadic-functions"> + <title><acronym>SQL</> Functions with Variable Numbers of Arguments</title> + + <indexterm> + <primary>function</primary> + <secondary>variadic</secondary> + </indexterm> + + <indexterm> + <primary>variadic function</primary> + </indexterm> + + <para> + <acronym>SQL</acronym> functions can be declared to accept + variable numbers of arguments, so long as all the <quote>optional</> + arguments are of the same data type. The optional arguments will be + passed to the function as an array. The function is declared by + marking the last parameter as <literal>VARIADIC</>; this parameter + must be declared as being of an array type. For example: + +<screen> +CREATE FUNCTION mleast(VARIADIC numeric[]) RETURNS numeric AS $$ + SELECT min($1[i]) FROM generate_subscripts($1, 1) g(i); +$$ LANGUAGE SQL; + +SELECT mleast(10, -1, 5, 4.4); + mleast +-------- + -1 +(1 row) +</screen> + + Effectively, all the actual arguments at or beyond the + <literal>VARIADIC</> position are gathered up into a one-dimensional + array, as if you had written + +<screen> +SELECT mleast(ARRAY[10, -1, 5, 4.4]); -- doesn't work +</screen> + + You can't actually write that, though — or at least, it will + not match this function definition. A parameter marked + <literal>VARIADIC</> matches one or more occurrences of its element + type, not of its own type. + </para> + + <para> + Sometimes it is useful to be able to pass an already-constructed array + to a variadic function; this is particularly handy when one variadic + function wants to pass on its array parameter to another one. You can + do that by specifying <literal>VARIADIC</> in the call: + +<screen> +SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]); +</screen> + + This prevents expansion of the function's variadic parameter into its + element type, thereby allowing the array argument value to match + normally. <literal>VARIADIC</> can only be attached to the last + actual argument of a function call. </para> </sect2> @@ -795,7 +861,7 @@ DETAIL: A function returning a polymorphic type must have at least one polymorp For example: <screen> CREATE FUNCTION dup (f1 anyelement, OUT f2 anyelement, OUT f3 anyarray) -AS 'select $1, array[$1,$1]' LANGUAGE sql; +AS 'select $1, array[$1,$1]' LANGUAGE SQL; SELECT * FROM dup(22); f2 | f3 @@ -804,6 +870,38 @@ SELECT * FROM dup(22); (1 row) </screen> </para> + + <para> + Polymorphism can also be used with variadic functions. + For example: +<screen> +CREATE FUNCTION anyleast (VARIADIC anyarray) RETURNS anyelement AS $$ + SELECT min($1[i]) FROM generate_subscripts($1, 1) g(i); +$$ LANGUAGE SQL; + +SELECT anyleast(10, -1, 5, 4); + anyleast +---------- + -1 +(1 row) + +SELECT anyleast('abc'::text, 'def'); + anyleast +---------- + abc +(1 row) + +CREATE FUNCTION concat(text, VARIADIC anyarray) RETURNS text AS $$ + SELECT array_to_string($2, $1); +$$ LANGUAGE SQL; + +SELECT concat('|', 1, 4, 2); + concat +-------- + 1|4|2 +(1 row) +</screen> + </para> </sect2> </sect1> @@ -853,6 +951,16 @@ CREATE FUNCTION test(smallint, double precision) RETURNS ... </para> <para> + Another possible conflict is between variadic and non-variadic functions. + For instance, it is possible to create both <literal>foo(numeric)</> and + <literal>foo(VARIADIC numeric[])</>. In this case it is unclear which one + should be matched to a call providing a single numeric argument, such as + <literal>foo(10.1)</>. The rule is that the function appearing + earlier in the search path is used, or if the two functions are in the + same schema, the non-variadic one is preferred. + </para> + + <para> When overloading C-language functions, there is an additional constraint: The C name of each function in the family of overloaded functions must be different from the C names of all @@ -2952,7 +3060,25 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray LANGUAGE C IMMUTABLE; </programlisting> </para> + + <para> + There is a variant of polymorphism that is only available to C-language + functions: they can be declared to take parameters of type + <literal>"any"</>. (Note that this type name must be double-quoted, + since it's also a SQL reserved word.) This works like + <type>anyelement</> except that it does not constrain different + <literal>"any"</> arguments to be the same type, nor do they help + determine the function's result type. A C-language function can also + declare its final parameter to be <literal>VARIADIC "any"</>. This will + match one or more actual arguments of any type (not necessarily the same + type). These arguments will <emphasis>not</> be gathered into an array + as happens with normal variadic functions; they will just be passed to + the function separately. The <function>PG_NARGS()</> macro and the + methods described above must be used to determine the number of actual + arguments and their types when using this feature. + </para> </sect2> + <sect2> <title>Shared Memory and LWLocks</title> |