Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 69a785b

Browse files
committed
Implement SQL-spec RETURNS TABLE syntax for functions.
(Unlike the original submission, this patch treats TABLE output parameters as being entirely equivalent to OUT parameters -- tgl) Pavel Stehule
1 parent a8fb90c commit 69a785b

File tree

23 files changed

+626
-85
lines changed

23 files changed

+626
-85
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.170 2008/07/16 16:55:23 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.171 2008/07/18 03:32:51 tgl Exp $ -->
22
<!--
33
Documentation of the system catalogs, directed toward PostgreSQL developers
44
-->
@@ -3680,7 +3680,8 @@
36803680
<literal>i</literal> for <literal>IN</> arguments,
36813681
<literal>o</literal> for <literal>OUT</> arguments,
36823682
<literal>b</literal> for <literal>INOUT</> arguments,
3683-
<literal>v</literal> for <literal>VARIADIC</> arguments.
3683+
<literal>v</literal> for <literal>VARIADIC</> arguments,
3684+
<literal>t</literal> for <literal>TABLE</> arguments.
36843685
If all the arguments are <literal>IN</literal> arguments,
36853686
this field will be null.
36863687
Note that subscripts correspond to positions of

doc/src/sgml/func.sgml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.441 2008/07/16 00:48:53 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.442 2008/07/18 03:32:51 tgl Exp $ -->
22

33
<chapter id="functions">
44
<title>Functions and Operators</title>
@@ -11563,6 +11563,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1156311563
<primary>pg_get_ruledef</primary>
1156411564
</indexterm>
1156511565

11566+
<indexterm>
11567+
<primary>pg_get_function_arguments</primary>
11568+
</indexterm>
11569+
11570+
<indexterm>
11571+
<primary>pg_get_function_result</primary>
11572+
</indexterm>
11573+
1156611574
<indexterm>
1156711575
<primary>pg_get_indexdef</primary>
1156811576
</indexterm>
@@ -11636,6 +11644,16 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1163611644
<entry>decompile internal form of an expression, assuming that any Vars
1163711645
in it refer to the relation indicated by the second parameter</entry>
1163811646
</row>
11647+
<row>
11648+
<entry><literal><function>pg_get_function_arguments</function>(<parameter>func_oid</parameter>)</literal></entry>
11649+
<entry><type>text</type></entry>
11650+
<entry>get argument list for function</entry>
11651+
</row>
11652+
<row>
11653+
<entry><literal><function>pg_get_function_result</function>(<parameter>func_oid</parameter>)</literal></entry>
11654+
<entry><type>text</type></entry>
11655+
<entry>get <literal>RETURNS</> clause for function</entry>
11656+
</row>
1163911657
<row>
1164011658
<entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>)</literal></entry>
1164111659
<entry><type>text</type></entry>
@@ -11738,6 +11756,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1173811756
the same result as the variant that does not have the parameter at all.
1173911757
</para>
1174011758

11759+
<para>
11760+
<function>pg_get_function_arguments</function> returns the argument list
11761+
of a function, in the form it would need to appear in within
11762+
<command>CREATE FUNCTION</>.
11763+
<function>pg_get_function_result</function> similarly returns the
11764+
appropriate <literal>RETURNS</> clause for the function.
11765+
</para>
11766+
1174111767
<para>
1174211768
<function>pg_get_serial_sequence</function> returns the name of the
1174311769
sequence associated with a column, or NULL if no sequence is associated

doc/src/sgml/plpgsql.sgml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.132 2008/07/16 01:30:21 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.133 2008/07/18 03:32:51 tgl Exp $ -->
22

33
<chapter id="plpgsql">
44
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -157,6 +157,8 @@
157157
parameters in place of an explicit specification of the return type.
158158
This does not add any fundamental capability to the language, but
159159
it is often convenient, especially for returning multiple values.
160+
The <literal>RETURNS TABLE</> notation can also be used in place
161+
of <literal>RETURNS SETOF</>.
160162
</para>
161163

162164
<para>
@@ -468,6 +470,23 @@ $$ LANGUAGE plpgsql;
468470
<literal>RETURNS record</>.
469471
</para>
470472

473+
<para>
474+
Another way to declare a <application>PL/pgSQL</application> function
475+
is with <literal>RETURNS TABLE</>, for example:
476+
477+
<programlisting>
478+
CREATE FUNCTION extended_sales(p_itemno int) RETURNS TABLE(quantity int, total numeric) AS $$
479+
BEGIN
480+
RETURN QUERY SELECT quantity, quantity * price FROM sales WHERE itemno = p_itemno;
481+
END;
482+
$$ LANGUAGE plpgsql;
483+
</programlisting>
484+
485+
This is exactly equivalent to declaring one or more <literal>OUT</>
486+
parameters and specifying <literal>RETURNS SETOF
487+
<replaceable>sometype</></literal>.
488+
</para>
489+
471490
<para>
472491
When the return type of a <application>PL/pgSQL</application>
473492
function is declared as a polymorphic type (<type>anyelement</type>,

doc/src/sgml/ref/create_function.sgml

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.79 2008/07/16 01:30:21 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.80 2008/07/18 03:32:52 tgl Exp $
33
-->
44

55
<refentry id="SQL-CREATEFUNCTION">
@@ -21,7 +21,8 @@ $PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.79 2008/07/16 01:30
2121
<synopsis>
2222
CREATE [ OR REPLACE ] FUNCTION
2323
<replaceable class="parameter">name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
24-
[ RETURNS <replaceable class="parameter">rettype</replaceable> ]
24+
[ RETURNS <replaceable class="parameter">rettype</replaceable>
25+
| RETURNS TABLE ( <replaceable class="parameter">colname</replaceable> <replaceable class="parameter">coltype</replaceable> [, ...] ) ]
2526
{ LANGUAGE <replaceable class="parameter">langname</replaceable>
2627
| IMMUTABLE | STABLE | VOLATILE
2728
| CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
@@ -49,7 +50,7 @@ CREATE [ OR REPLACE ] FUNCTION
4950
If a schema name is included, then the function is created in the
5051
specified schema. Otherwise it is created in the current schema.
5152
The name of the new function must not match any existing function
52-
with the same argument types in the same schema. However,
53+
with the same input argument types in the same schema. However,
5354
functions of different argument types can share a name (this is
5455
called <firstterm>overloading</>).
5556
</para>
@@ -104,6 +105,9 @@ CREATE [ OR REPLACE ] FUNCTION
104105
The mode of an argument: <literal>IN</>, <literal>OUT</>,
105106
<literal>INOUT</>, or <literal>VARIADIC</>.
106107
If omitted, the default is <literal>IN</>.
108+
Only <literal>OUT</> arguments can follow a <literal>VARIADIC</> one.
109+
Also, <literal>OUT</> and <literal>INOUT</> arguments cannot be used
110+
together with the <literal>RETURNS TABLE</> notation.
107111
</para>
108112
</listitem>
109113
</varlistentry>
@@ -183,6 +187,30 @@ CREATE [ OR REPLACE ] FUNCTION
183187
</listitem>
184188
</varlistentry>
185189

190+
<varlistentry>
191+
<term><replaceable class="parameter">colname</replaceable></term>
192+
193+
<listitem>
194+
<para>
195+
The name of an output column in the <literal>RETURNS TABLE</>
196+
syntax. This is effectively another way of declaring a named
197+
<literal>OUT</> parameter, except that <literal>RETURNS TABLE</>
198+
also implies <literal>RETURNS SETOF</>.
199+
</para>
200+
</listitem>
201+
</varlistentry>
202+
203+
<varlistentry>
204+
<term><replaceable class="parameter">coltype</replaceable></term>
205+
206+
<listitem>
207+
<para>
208+
The data type of an output column in the <literal>RETURNS TABLE</>
209+
syntax.
210+
</para>
211+
</listitem>
212+
</varlistentry>
213+
186214
<varlistentry>
187215
<term><replaceable class="parameter">langname</replaceable></term>
188216

@@ -437,7 +465,7 @@ CREATE [ OR REPLACE ] FUNCTION
437465
<productname>PostgreSQL</productname> allows function
438466
<firstterm>overloading</firstterm>; that is, the same name can be
439467
used for several different functions so long as they have distinct
440-
argument types. However, the C names of all functions must be
468+
input argument types. However, the C names of all functions must be
441469
different, so you must give overloaded C functions different C
442470
names (for example, use the argument types as part of the C
443471
names).
@@ -541,6 +569,18 @@ CREATE FUNCTION dup(int) RETURNS dup_result
541569

542570
SELECT * FROM dup(42);
543571
</programlisting>
572+
Another way to return multiple columns is to use a <literal>TABLE</>
573+
function:
574+
<programlisting>
575+
CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
576+
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
577+
LANGUAGE SQL;
578+
579+
SELECT * FROM dup(42);
580+
</programlisting>
581+
However, a <literal>TABLE</> function is different from the
582+
preceding examples, because it actually returns a <emphasis>set</>
583+
of records, not just one record.
544584
</para>
545585
</refsect1>
546586

doc/src/sgml/xfunc.sgml

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.131 2008/07/16 01:30:21 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.132 2008/07/18 03:32:52 tgl Exp $ -->
22

33
<sect1 id="xfunc">
44
<title>User-Defined Functions</title>
@@ -94,11 +94,12 @@
9494
</para>
9595

9696
<para>
97-
<indexterm><primary>SETOF</><seealso>function</></> Alternatively,
98-
an SQL function can be declared to return a set, by specifying the
99-
function's return type as <literal>SETOF
100-
<replaceable>sometype</></literal>. In this case all rows of the
101-
last query's result are returned. Further details appear below.
97+
Alternatively, an SQL function can be declared to return a set,
98+
by specifying the function's return type as <literal>SETOF
99+
<replaceable>sometype</></literal>, or equivalently by declaring it as
100+
<literal>RETURNS TABLE(<replaceable>columns</>)</literal>. In this case
101+
all rows of the last query's result are returned. Further details appear
102+
below.
102103
</para>
103104

104105
<para>
@@ -117,7 +118,7 @@
117118
other SQL commands. (The only exception is that you cannot put
118119
<command>BEGIN</>, <command>COMMIT</>, <command>ROLLBACK</>, or
119120
<command>SAVEPOINT</> commands into a <acronym>SQL</acronym> function.)
120-
However, the final command
121+
However, the final command
121122
must be a <command>SELECT</command> that returns whatever is
122123
specified as the function's return type. Alternatively, if you
123124
want to define a SQL function that performs actions but has no
@@ -175,7 +176,7 @@ INSERT INTO $1 VALUES (42);
175176
<para>
176177
The simplest possible <acronym>SQL</acronym> function has no arguments and
177178
simply returns a base type, such as <type>integer</type>:
178-
179+
179180
<screen>
180181
CREATE FUNCTION one() RETURNS integer AS $$
181182
SELECT 1 AS result;
@@ -202,7 +203,7 @@ SELECT one();
202203
</para>
203204

204205
<para>
205-
It is almost as easy to define <acronym>SQL</acronym> functions
206+
It is almost as easy to define <acronym>SQL</acronym> functions
206207
that take base types as arguments. In the example below, notice
207208
how we refer to the arguments within the function as <literal>$1</>
208209
and <literal>$2</>.
@@ -226,7 +227,7 @@ SELECT add_em(1, 2) AS answer;
226227

227228
<programlisting>
228229
CREATE FUNCTION tf1 (integer, numeric) RETURNS integer AS $$
229-
UPDATE bank
230+
UPDATE bank
230231
SET balance = balance - $2
231232
WHERE accountno = $1;
232233
SELECT 1;
@@ -248,7 +249,7 @@ SELECT tf1(17, 100.0);
248249

249250
<programlisting>
250251
CREATE FUNCTION tf1 (integer, numeric) RETURNS numeric AS $$
251-
UPDATE bank
252+
UPDATE bank
252253
SET balance = balance - $2
253254
WHERE accountno = $1;
254255
SELECT balance FROM bank WHERE accountno = $1;
@@ -267,7 +268,7 @@ $$ LANGUAGE SQL;
267268
types, we must not only specify which
268269
argument we want (as we did above with <literal>$1</> and <literal>$2</literal>) but
269270
also the desired attribute (field) of that argument. For example,
270-
suppose that
271+
suppose that
271272
<type>emp</type> is a table containing employee data, and therefore
272273
also the name of the composite type of each row of the table. Here
273274
is a function <function>double_salary</function> that computes what someone's
@@ -323,7 +324,7 @@ SELECT name, double_salary(ROW(name, salary*1.1, age, cubicle)) AS dream
323324

324325
<para>
325326
It is also possible to build a function that returns a composite type.
326-
This is an example of a function
327+
This is an example of a function
327328
that returns a single <type>emp</type> row:
328329

329330
<programlisting>
@@ -364,7 +365,7 @@ ERROR: function declared to return emp returns varchar instead of text at colum
364365
</para>
365366
</listitem>
366367
</itemizedlist>
367-
</para>
368+
</para>
368369

369370
<para>
370371
A different way to define the same function is:
@@ -380,7 +381,7 @@ $$ LANGUAGE SQL;
380381
in this situation, but it is a handy alternative in some cases
381382
&mdash; for example, if we need to compute the result by calling
382383
another function that returns the desired composite value.
383-
</para>
384+
</para>
384385

385386
<para>
386387
We could call this function directly in either of two ways:
@@ -401,7 +402,7 @@ SELECT * FROM new_emp();
401402

402403
The second way is described more fully in <xref
403404
linkend="xfunc-sql-table-functions">.
404-
</para>
405+
</para>
405406

406407
<para>
407408
When you use a function that returns a composite type,
@@ -429,7 +430,7 @@ LINE 1: SELECT new_emp().name;
429430

430431
<para>
431432
Another option is to use
432-
functional notation for extracting an attribute. The simple way
433+
functional notation for extracting an attribute. The simple way
433434
to explain this is that we can use the
434435
notations <literal>attribute(table)</> and <literal>table.attribute</>
435436
interchangeably.
@@ -693,9 +694,14 @@ SELECT *, upper(fooname) FROM getfoo(1) AS t1;
693694
</para>
694695
</sect2>
695696

696-
<sect2>
697+
<sect2 id="xfunc-sql-functions-returning-set">
697698
<title><acronym>SQL</acronym> Functions Returning Sets</title>
698699

700+
<indexterm>
701+
<primary>function</primary>
702+
<secondary>with SETOF</secondary>
703+
</indexterm>
704+
699705
<para>
700706
When an SQL function is declared as returning <literal>SETOF
701707
<replaceable>sometype</></literal>, the function's final
@@ -733,7 +739,7 @@ SELECT * FROM getfoo(1) AS t1;
733739

734740
<programlisting>
735741
CREATE FUNCTION sum_n_product_with_tab (x int, OUT sum int, OUT product int) RETURNS SETOF record AS $$
736-
SELECT x + tab.y, x * tab.y FROM tab;
742+
SELECT $1 + tab.y, $1 * tab.y FROM tab;
737743
$$ LANGUAGE SQL;
738744
</programlisting>
739745

@@ -794,6 +800,41 @@ SELECT name, listchildren(name) FROM nodes;
794800
</para>
795801
</sect2>
796802

803+
<sect2 id="xfunc-sql-functions-returning-table">
804+
<title><acronym>SQL</acronym> Functions Returning <literal>TABLE</></title>
805+
806+
<indexterm>
807+
<primary>function</primary>
808+
<secondary>RETURNS TABLE</secondary>
809+
</indexterm>
810+
811+
<para>
812+
There is another way to declare a function as returning a set,
813+
which is to use the syntax
814+
<literal>RETURNS TABLE(<replaceable>columns</>)</literal>.
815+
This is equivalent to using one or more <literal>OUT</> parameters plus
816+
marking the function as returning <literal>SETOF record</> (or
817+
<literal>SETOF</> a single output parameter's type, as appropriate).
818+
This notation is specified in recent versions of the SQL standard, and
819+
thus may be more portable than using <literal>SETOF</>.
820+
</para>
821+
822+
<para>
823+
For example, the preceding sum-and-product example could also be
824+
done this way:
825+
826+
<programlisting>
827+
CREATE FUNCTION sum_n_product_with_tab (x int) RETURNS TABLE(sum int, product int) AS $$
828+
SELECT $1 + tab.y, $1 * tab.y FROM tab;
829+
$$ LANGUAGE SQL;
830+
</programlisting>
831+
832+
It is not allowed to use explicit <literal>OUT</> or <literal>INOUT</>
833+
parameters with the <literal>RETURNS TABLE</> notation &mdash; you must
834+
put all the output columns in the <literal>TABLE</> list.
835+
</para>
836+
</sect2>
837+
797838
<sect2>
798839
<title>Polymorphic <acronym>SQL</acronym> Functions</title>
799840

0 commit comments

Comments
 (0)