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

Commit 470a104

Browse files
committed
plpgsql functions can return RECORD, per Neil Conway.
1 parent 1903221 commit 470a104

File tree

7 files changed

+123
-17
lines changed

7 files changed

+123
-17
lines changed

doc/src/sgml/plpgsql.sgml

Lines changed: 1 addition & 3 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.5 2002/08/30 00:28:40 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl Exp $
33
-->
44

55
<chapter id="plpgsql">
@@ -538,8 +538,6 @@ END;
538538

539539
<para>
540540
Note that <literal>RECORD</> is not a true data type, only a placeholder.
541-
Thus, for example, one cannot declare a function returning
542-
<literal>RECORD</>.
543541
</para>
544542
</sect2>
545543

doc/src/sgml/xfunc.sgml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.59 2002/08/30 00:28:40 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.60 2002/09/01 16:28:05 tgl Exp $
33
-->
44

55
<chapter id="xfunc">
@@ -2119,6 +2119,27 @@ SELECT * FROM vw_getfoo;
21192119
</programlisting>
21202120
are all valid statements.
21212121
</para>
2122+
2123+
<para>
2124+
In some cases it is useful to define table functions that can return
2125+
different column sets depending on how they are invoked. To support this,
2126+
the table function can be declared as returning the pseudo-type
2127+
<type>record</>. When such a function is used in a query, the expected
2128+
row structure must be specified in the query itself, so that the system
2129+
can know how to parse and plan the query. Consider this example:
2130+
<programlisting>
2131+
SELECT *
2132+
FROM dblink('dbname=template1', 'select proname, prosrc from pg_proc')
2133+
AS t1(proname name, prosrc text)
2134+
WHERE proname LIKE 'bytea%';
2135+
</programlisting>
2136+
The <literal>dblink</> function executes a remote query (see
2137+
<literal>contrib/dblink</>). It is declared to return <type>record</>
2138+
since it might be used for any kind of query. The actual column set
2139+
must be specified in the calling query so that the parser knows, for
2140+
example, what <literal>*</> should expand to.
2141+
</para>
2142+
21222143
</sect1>
21232144

21242145
<sect1 id="xfunc-plhandler">

src/pl/plpgsql/src/gram.y

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* procedural language
55
*
66
* IDENTIFICATION
7-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.36 2002/08/30 00:28:41 tgl Exp $
7+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.37 2002/09/01 16:28:06 tgl Exp $
88
*
99
* This software is copyrighted by Jan Wieck - Hamburg.
1010
*
@@ -1159,7 +1159,6 @@ stmt_return : K_RETURN lno
11591159
}
11601160
;
11611161

1162-
/* FIXME: this syntax needs work, RETURN NEXT breaks stmt_return */
11631162
stmt_return_next: K_RETURN_NEXT lno
11641163
{
11651164
PLpgSQL_stmt_return_next *new;

src/pl/plpgsql/src/pl_comp.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.49 2002/08/30 00:28:41 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.50 2002/09/01 16:28:06 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -211,11 +211,11 @@ plpgsql_compile(Oid fn_oid, int functype)
211211
procStruct->prorettype);
212212
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
213213

214-
/* Disallow pseudotype result, except VOID */
215-
/* XXX someday allow RECORD? */
214+
/* Disallow pseudotype result, except VOID or RECORD */
216215
if (typeStruct->typtype == 'p')
217216
{
218-
if (procStruct->prorettype == VOIDOID)
217+
if (procStruct->prorettype == VOIDOID ||
218+
procStruct->prorettype == RECORDOID)
219219
/* okay */;
220220
else if (procStruct->prorettype == TRIGGEROID ||
221221
procStruct->prorettype == OPAQUEOID)
@@ -227,7 +227,8 @@ plpgsql_compile(Oid fn_oid, int functype)
227227
format_type_be(procStruct->prorettype));
228228
}
229229

230-
if (typeStruct->typrelid != InvalidOid)
230+
if (typeStruct->typrelid != InvalidOid ||
231+
procStruct->prorettype == RECORDOID)
231232
function->fn_retistuple = true;
232233
else
233234
{
@@ -486,8 +487,7 @@ plpgsql_compile(Oid fn_oid, int functype)
486487
}
487488

488489
/*
489-
* Create the magic found variable indicating if the last FOR or
490-
* SELECT statement returned data
490+
* Create the magic FOUND variable.
491491
*/
492492
var = malloc(sizeof(PLpgSQL_var));
493493
memset(var, 0, sizeof(PLpgSQL_var));

src/pl/plpgsql/src/pl_exec.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.61 2002/08/30 23:59:46 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.62 2002/09/01 16:28:06 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -1588,9 +1588,9 @@ static int
15881588
exec_stmt_return_next(PLpgSQL_execstate *estate,
15891589
PLpgSQL_stmt_return_next *stmt)
15901590
{
1591-
TupleDesc tupdesc;
1592-
int natts;
1593-
HeapTuple tuple;
1591+
TupleDesc tupdesc;
1592+
int natts;
1593+
HeapTuple tuple;
15941594
bool free_tuple = false;
15951595

15961596
if (!estate->retisset)

src/test/regress/expected/plpgsql.out

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,3 +1680,56 @@ select * from test_ret_set_scalar(1,10);
16801680
11
16811681
(10 rows)
16821682

1683+
create function test_ret_set_rec_dyn(int) returns setof record as '
1684+
DECLARE
1685+
retval RECORD;
1686+
BEGIN
1687+
IF $1 > 10 THEN
1688+
SELECT INTO retval 5, 10, 15;
1689+
RETURN NEXT retval;
1690+
RETURN NEXT retval;
1691+
ELSE
1692+
SELECT INTO retval 50, 5::numeric, ''xxx''::text;
1693+
RETURN NEXT retval;
1694+
RETURN NEXT retval;
1695+
END IF;
1696+
RETURN;
1697+
END;' language 'plpgsql';
1698+
SELECT * FROM test_ret_set_rec_dyn(1500) AS (a int, b int, c int);
1699+
a | b | c
1700+
---+----+----
1701+
5 | 10 | 15
1702+
5 | 10 | 15
1703+
(2 rows)
1704+
1705+
SELECT * FROM test_ret_set_rec_dyn(5) AS (a int, b numeric, c text);
1706+
a | b | c
1707+
----+---+-----
1708+
50 | 5 | xxx
1709+
50 | 5 | xxx
1710+
(2 rows)
1711+
1712+
create function test_ret_rec_dyn(int) returns record as '
1713+
DECLARE
1714+
retval RECORD;
1715+
BEGIN
1716+
IF $1 > 10 THEN
1717+
SELECT INTO retval 5, 10, 15;
1718+
RETURN retval;
1719+
ELSE
1720+
SELECT INTO retval 50, 5::numeric, ''xxx''::text;
1721+
RETURN retval;
1722+
END IF;
1723+
END;' language 'plpgsql';
1724+
SELECT * FROM test_ret_rec_dyn(1500) AS (a int, b int, c int);
1725+
a | b | c
1726+
---+----+----
1727+
5 | 10 | 15
1728+
(1 row)
1729+
1730+
SELECT * FROM test_ret_rec_dyn(5) AS (a int, b numeric, c text);
1731+
a | b | c
1732+
----+---+-----
1733+
50 | 5 | xxx
1734+
(1 row)
1735+

src/test/regress/sql/plpgsql.sql

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,3 +1524,38 @@ BEGIN
15241524
END;' language 'plpgsql';
15251525

15261526
select * from test_ret_set_scalar(1,10);
1527+
1528+
create function test_ret_set_rec_dyn(int) returns setof record as '
1529+
DECLARE
1530+
retval RECORD;
1531+
BEGIN
1532+
IF $1 > 10 THEN
1533+
SELECT INTO retval 5, 10, 15;
1534+
RETURN NEXT retval;
1535+
RETURN NEXT retval;
1536+
ELSE
1537+
SELECT INTO retval 50, 5::numeric, ''xxx''::text;
1538+
RETURN NEXT retval;
1539+
RETURN NEXT retval;
1540+
END IF;
1541+
RETURN;
1542+
END;' language 'plpgsql';
1543+
1544+
SELECT * FROM test_ret_set_rec_dyn(1500) AS (a int, b int, c int);
1545+
SELECT * FROM test_ret_set_rec_dyn(5) AS (a int, b numeric, c text);
1546+
1547+
create function test_ret_rec_dyn(int) returns record as '
1548+
DECLARE
1549+
retval RECORD;
1550+
BEGIN
1551+
IF $1 > 10 THEN
1552+
SELECT INTO retval 5, 10, 15;
1553+
RETURN retval;
1554+
ELSE
1555+
SELECT INTO retval 50, 5::numeric, ''xxx''::text;
1556+
RETURN retval;
1557+
END IF;
1558+
END;' language 'plpgsql';
1559+
1560+
SELECT * FROM test_ret_rec_dyn(1500) AS (a int, b int, c int);
1561+
SELECT * FROM test_ret_rec_dyn(5) AS (a int, b numeric, c text);

0 commit comments

Comments
 (0)