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

Commit e107f3a

Browse files
committed
PL/pgSQL functions can return sets. Neil Conway's patch, modified so
that the functionality is available to anyone via ReturnSetInfo, rather than hard-wiring it to PL/pgSQL.
1 parent 82ccb42 commit e107f3a

File tree

21 files changed

+957
-408
lines changed

21 files changed

+957
-408
lines changed

contrib/intagg/int_aggregate.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616
#include "postgres.h"
1717

1818
#include <ctype.h>
19-
#include <stdio.h>
2019
#include <sys/types.h>
21-
#include <string.h>
22-
#include "postgres.h"
20+
2321
#include "access/heapam.h"
2422
#include "catalog/catname.h"
2523
#include "catalog/indexing.h"
2624
#include "catalog/pg_proc.h"
25+
#include "catalog/pg_type.h"
2726
#include "executor/executor.h"
2827
#include "utils/fcache.h"
2928
#include "utils/sets.h"
@@ -97,7 +96,7 @@ static PGARRAY * GetPGArray(int4 state, int fAdd)
9796
p->a.size = cb;
9897
p->a.ndim = 0;
9998
p->a.flags = 0;
100-
p->a.elmtype = INT4OID;
99+
p->a.elemtype = INT4OID;
101100
p->items = 0;
102101
p->lower= START_NUM;
103102
}
@@ -150,7 +149,7 @@ static PGARRAY *ShrinkPGArray(PGARRAY *p)
150149
pnew->a.size = cb;
151150
pnew->a.ndim=1;
152151
pnew->a.flags = 0;
153-
pnew->a.elmtype = INT4OID;
152+
pnew->a.elemtype = INT4OID;
154153
pnew->lower = 0;
155154
}
156155
else
@@ -171,11 +170,11 @@ Datum int_agg_state(PG_FUNCTION_ARGS)
171170
PGARRAY *p = GetPGArray(state, 1);
172171
if(!p)
173172
{
174-
elog(ERROR,"No aggregate storage\n");
173+
elog(ERROR,"No aggregate storage");
175174
}
176175
else if(p->items >= p->lower)
177176
{
178-
elog(ERROR,"aggregate storage too small\n");
177+
elog(ERROR,"aggregate storage too small");
179178
}
180179
else
181180
{
@@ -202,32 +201,24 @@ Datum int_agg_final_array(PG_FUNCTION_ARGS)
202201
/* This function accepts an array, and returns one item for each entry in the array */
203202
Datum int_enum(PG_FUNCTION_ARGS)
204203
{
205-
CTX *pc;
206204
PGARRAY *p = (PGARRAY *) PG_GETARG_POINTER(0);
205+
CTX *pc;
207206
ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
208207

208+
if (!rsi || !IsA(rsi, ReturnSetInfo))
209+
elog(ERROR, "No ReturnSetInfo sent! function must be declared returning a 'setof' integer");
210+
209211
if(!p)
210212
{
211-
elog(WARNING, "No data sent\n");
212-
return 0;
213-
}
214-
if(!rsi)
215-
{
216-
elog(ERROR, "No ReturnSetInfo sent! function must be declared returning a 'setof' integer");
213+
elog(WARNING, "No data sent");
217214
PG_RETURN_NULL();
218-
219215
}
216+
220217
if(!fcinfo->context)
221218
{
222219
/* Allocate a working context */
223220
pc = (CTX *) palloc(sizeof(CTX));
224221

225-
if(!pc)
226-
{
227-
elog(ERROR, "CTX Alocation failed\n");
228-
PG_RETURN_NULL();
229-
}
230-
231222
/* Don't copy atribute if you don't need too */
232223
if(VARATT_IS_EXTENDED(p) )
233224
{
@@ -236,7 +227,7 @@ Datum int_enum(PG_FUNCTION_ARGS)
236227
pc->flags = TOASTED;
237228
if(!pc->p)
238229
{
239-
elog(ERROR, "Error in toaster!!! no detoasting\n");
230+
elog(ERROR, "Error in toaster!!! no detoasting");
240231
PG_RETURN_NULL();
241232
}
242233
}

doc/src/sgml/plpgsql.sgml

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.4 2002/08/29 04:12:02 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.5 2002/08/30 00:28:40 tgl Exp $
33
-->
44

55
<chapter id="plpgsql">
@@ -1142,11 +1142,20 @@ GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replace
11421142
RETURN <replaceable>expression</replaceable>;
11431143
</synopsis>
11441144

1145+
RETURN with an expression is used to return from a
1146+
<application>PL/pgSQL</> function that does not return a set.
11451147
The function terminates and the value of
1146-
<replaceable>expression</replaceable> will be returned to the
1147-
upper executor.
1148+
<replaceable>expression</replaceable> is returned to the caller.
1149+
</para>
1150+
1151+
<para>
1152+
To return a composite (row) value, you must write a record or row
1153+
variable as the <replaceable>expression</replaceable>. When
1154+
returning a scalar type, any expression can be used.
11481155
The expression's result will be automatically cast into the
11491156
function's return type as described for assignments.
1157+
(If you have declared the function to return <type>void</>,
1158+
then the expression can be omitted, and will be ignored in any case.)
11501159
</para>
11511160

11521161
<para>
@@ -1155,6 +1164,28 @@ RETURN <replaceable>expression</replaceable>;
11551164
the function without hitting a RETURN statement, a run-time error
11561165
will occur.
11571166
</para>
1167+
1168+
<para>
1169+
When a <application>PL/pgSQL</> function is declared to return
1170+
<literal>SETOF</literal> <replaceable>sometype</>, the procedure
1171+
to follow is slightly different. The individual items to be returned
1172+
are specified in RETURN NEXT commands, and then a final RETURN with
1173+
no argument is given to indicate that the function is done generating
1174+
items.
1175+
1176+
<synopsis>
1177+
RETURN NEXT <replaceable>expression</replaceable>;
1178+
</synopsis>
1179+
1180+
RETURN NEXT does not actually return from the function; it simply
1181+
saves away the value of the expression (or record or row variable,
1182+
as appropriate for the datatype being returned).
1183+
Execution then continues with the next statement in the
1184+
<application>PL/pgSQL</> function. As successive RETURN NEXT
1185+
commands are executed, the result set is built up. A final
1186+
RETURN, which need have no argument, causes control to exit
1187+
the function.
1188+
</para>
11581189
</sect2>
11591190

11601191
<sect2 id="plpgsql-conditionals">
@@ -1531,8 +1562,8 @@ END LOOP;
15311562
to worry about that, since FOR loops automatically use a cursor
15321563
internally to avoid memory problems.) A more interesting usage is to
15331564
return a reference to a cursor that it has created, allowing the
1534-
caller to read the rows. This provides a way to return row sets
1535-
from functions.
1565+
caller to read the rows. This provides an efficient way to return
1566+
large row sets from functions.
15361567
</para>
15371568

15381569
<sect2 id="plpgsql-cursor-declarations">
@@ -1794,19 +1825,27 @@ COMMIT;
17941825
RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">variable</replaceable> <optional>...</optional></optional>;
17951826
</synopsis>
17961827

1797-
Possible levels are DEBUG (write the message into the postmaster log),
1798-
NOTICE (write the message into the postmaster log and forward it to
1799-
the client application) and EXCEPTION (raise an error,
1800-
aborting the transaction).
1828+
Possible levels are <literal>DEBUG</literal> (write the message to
1829+
the server log), <literal>LOG</literal> (write the message to the
1830+
server log with a higher priority), <literal>INFO</literal>,
1831+
<literal>NOTICE</literal> and <literal>WARNING</literal> (write
1832+
the message to the server log and send it to the client, with
1833+
respectively higher priorities), and <literal>EXCEPTION</literal>
1834+
(raise an error and abort the current transaction). Whether error
1835+
messages of a particular priority are reported to the client,
1836+
written to the server log, or both is controlled by the
1837+
<option>SERVER_MIN_MESSAGES</option> and
1838+
<option>CLIENT_MIN_MESSAGES</option> configuration variables. See
1839+
the <citetitle>PostgreSQL Administrator's Guide</citetitle> for more
1840+
information.
18011841
</para>
18021842

18031843
<para>
1804-
Inside the format string, <literal>%</literal> is replaced by the next
1805-
optional argument's external representation.
1806-
Write <literal>%%</literal> to emit a literal <literal>%</literal>.
1807-
Note that the optional arguments must presently
1808-
be simple variables, not expressions, and the format must be a simple
1809-
string literal.
1844+
Inside the format string, <literal>%</literal> is replaced by the
1845+
next optional argument's external representation. Write
1846+
<literal>%%</literal> to emit a literal <literal>%</literal>. Note
1847+
that the optional arguments must presently be simple variables,
1848+
not expressions, and the format must be a simple string literal.
18101849
</para>
18111850

18121851
<!--
@@ -1820,8 +1859,9 @@ RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="pa
18201859
<programlisting>
18211860
RAISE NOTICE ''Calling cs_create_job(%)'',v_job_id;
18221861
</programlisting>
1823-
In this example, the value of v_job_id will replace the % in the
1824-
string.
1862+
1863+
In this example, the value of v_job_id will replace the
1864+
<literal>%</literal> in the string.
18251865
</para>
18261866

18271867
<para>
@@ -1852,12 +1892,12 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
18521892
</para>
18531893

18541894
<para>
1855-
Thus, the only thing <application>PL/pgSQL</application> currently does when it encounters
1856-
an abort during execution of a function or trigger
1857-
procedure is to write some additional NOTICE level log messages
1858-
telling in which function and where (line number and type of
1859-
statement) this happened. The error always stops execution of
1860-
the function.
1895+
Thus, the only thing <application>PL/pgSQL</application>
1896+
currently does when it encounters an abort during execution of a
1897+
function or trigger procedure is to write some additional
1898+
<literal>NOTICE</literal> level log messages telling in which
1899+
function and where (line number and type of statement) this
1900+
happened. The error always stops execution of the function.
18611901
</para>
18621902
</sect2>
18631903
</sect1>

doc/src/sgml/release.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.154 2002/08/29 03:22:00 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.155 2002/08/30 00:28:40 tgl Exp $
33
-->
44

55
<appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
2424
worries about funny characters.
2525
-->
2626
<literallayout><![CDATA[
27+
Substantial improvements in functionality for functions returning sets
2728
Client libraries older than 6.3 no longer supported (version 0 protocol removed)
2829
PREPARE statement allows caching query plans for interactive statements
2930
Type OPAQUE is now deprecated in favor of pseudo-types cstring, trigger, etc

doc/src/sgml/runtime.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.128 2002/08/29 19:53:58 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.129 2002/08/30 00:28:40 tgl Exp $
33
-->
44

55
<Chapter Id="runtime">
@@ -921,7 +921,8 @@ env PGOPTIONS='-c geqo=off' psql
921921
built (see the configure option
922922
<literal>--enable-cassert</literal>). Note that
923923
<literal>DEBUG_ASSERTIONS</literal> defaults to on if
924-
<productname>PostgreSQL</productname> has been built this way.
924+
<productname>PostgreSQL</productname> has been built with
925+
assertions enabled.
925926
</para>
926927
</listitem>
927928
</varlistentry>

doc/src/sgml/xfunc.sgml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.58 2002/08/29 17:14:32 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.59 2002/08/30 00:28:40 tgl Exp $
33
-->
44

55
<chapter id="xfunc">
@@ -315,9 +315,7 @@ ERROR: function declared to return emp returns varchar instead of text at colum
315315
function, as described below. It can also be called in the context
316316
of an SQL expression, but only when you
317317
extract a single attribute out of the row or pass the entire row into
318-
another function that accepts the same composite type. (Trying to
319-
display the entire row value will yield
320-
a meaningless number.) For example,
318+
another function that accepts the same composite type. For example,
321319

322320
<programlisting>
323321
SELECT (new_emp()).name;

0 commit comments

Comments
 (0)