Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5a5e46e

Browse files
committed
Here (finally ;-)) is a doc patch covering the Table Function C API. It
reflects the changes in the tablefunc-fix patch that I sent in the otherday. It also refers to "see contrib/tablefunc for more examples", whichis next on my list of things to finish and submit.Joe Conway
1 parent8c26bc5 commit5a5e46e

File tree

1 file changed

+341
-5
lines changed

1 file changed

+341
-5
lines changed

‎doc/src/sgml/xfunc.sgml

Lines changed: 341 additions & 5 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.52 2002/06/20 16:57:00 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.53 2002/07/18 04:47:17 momjian Exp $
33
-->
44

55
<chapter id="xfunc">
@@ -1459,14 +1459,350 @@ CREATE FUNCTION c_overpaid(emp, int4)
14591459
RETURNS bool
14601460
AS '<replaceable>PGROOT</replaceable>/tutorial/funcs'
14611461
LANGUAGE C;
1462+
</programlisting>
1463+
</para>
1464+
</sect2>
1465+
1466+
<sect2>
1467+
<title>Table Function API</title>
1468+
1469+
<para>
1470+
The Table Function API assists in the creation of a user defined
1471+
C Language table functions (<xref linkend="xfunc-tablefunctions">).
1472+
Table functions are functions that produce a set of rows, made up of
1473+
either base (scalar) data types, or composite (multi-column) data types.
1474+
The API is split into two main components: support for returning
1475+
composite data types, and support for returning multiple rows
1476+
(set returning functions or SRFs).
1477+
</para>
1478+
1479+
<para>
1480+
The Table Function API relies on macros and functions to suppress most
1481+
of the complexity of building composite data types and return multiple
1482+
results. In addition to the version-1 conventions discussed elsewhere,
1483+
a table function always requires the following:
1484+
<programlisting>
1485+
#include "funcapi.h"
1486+
</programlisting>
1487+
</para>
1488+
1489+
<para>
1490+
The Table Function API support for returning composite data types
1491+
(or tuples) starts with the AttInMetadata struct. This struct holds
1492+
arrays of individual attribute information needed to create a tuple from
1493+
raw C strings. It also requires a copy of the TupleDesc. The information
1494+
carried here is derived from the TupleDesc, but it is stored here to
1495+
avoid redundant cpu cycles on each call to a Table Function.
1496+
<programlisting>
1497+
typedef struct
1498+
{
1499+
/* full TupleDesc */
1500+
TupleDesc tupdesc;
1501+
1502+
/* pointer to array of attribute "type"in finfo */
1503+
FmgrInfo *attinfuncs;
1504+
1505+
/* pointer to array of attribute type typelem */
1506+
Oid *attelems;
1507+
1508+
/* pointer to array of attribute type typtypmod */
1509+
int4 *atttypmods;
1510+
1511+
}AttInMetadata;
1512+
</programlisting>
1513+
To assist you in populating this struct, several functions and a macro
1514+
are available. Use
1515+
<programlisting>
1516+
TupleDesc RelationNameGetTupleDesc(char *relname)
1517+
</programlisting>
1518+
to get a TupleDesc based on the function's return type relation, or
1519+
<programlisting>
1520+
TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
1521+
</programlisting>
1522+
to get a TupleDesc based on the function's type oid. This can be used to
1523+
get a TupleDesc for a base (scalar), or composite (relation) type. Then
1524+
<programlisting>
1525+
AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
1526+
</programlisting>
1527+
will return a pointer to an AttInMetadata struct, initialized based on
1528+
the function's TupleDesc. AttInMetadata is be used in conjunction with
1529+
C strings to produce a properly formed tuple. The metadata is stored here
1530+
for use across calls to avoid redundant work.
1531+
</para>
1532+
1533+
<para>
1534+
In order to return a tuple you must create a tuple slot based on the
1535+
TupleDesc. You can use
1536+
<programlisting>
1537+
TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc)
1538+
</programlisting>
1539+
to initialize this tuple slot, or obtain one through other (user provided)
1540+
means. The tuple slot is needed to create a Datum for return by the
1541+
function.
1542+
</para>
1543+
1544+
<para>
1545+
If desired,
1546+
<programlisting>
1547+
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
1548+
</programlisting>
1549+
can be used to build a HeapTuple given user data in C string form.
1550+
"values" is an array of C strings, one for each attribute of the return
1551+
tuple. The C strings should be in the form expected by the "in" function
1552+
of the attribute data type. For more information on this requirement,
1553+
see the individual data type "in" functions in the source code
1554+
(e.g. textin() for data type TEXT). In order to return a NULL value for
1555+
one of the attributes, the corresponding pointer in the "values" array
1556+
should be set to NULL.
1557+
</para>
1558+
1559+
<para>
1560+
Finally, in order to return a tuple using the SRF portion of the API
1561+
(described below), the tuple must be converted into a Datum. Use
1562+
<programlisting>
1563+
TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple)
1564+
</programlisting>
1565+
to get a Datum given a tuple and a slot.
1566+
</para>
1567+
1568+
<para>
1569+
The Table Function API support for set returning functions starts with
1570+
the FuncCallContext struct. This struct holds function context for
1571+
SRFs using fcinfo->flinfo->fn_extra to hold a pointer to it across calls.
1572+
<programlisting>
1573+
typedef struct
1574+
{
1575+
/*
1576+
* Number of times we've been called before.
1577+
*
1578+
* call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
1579+
* incremented for you every time SRF_RETURN_NEXT() is called.
1580+
*/
1581+
uint32call_cntr;
1582+
1583+
/*
1584+
* OPTIONAL maximum number of calls
1585+
*
1586+
* max_calls is here for convenience ONLY and setting it is OPTIONAL.
1587+
* If not set, you must provide alternative means to know when the
1588+
* function is done.
1589+
*/
1590+
uint32max_calls;
1591+
1592+
/*
1593+
* OPTIONAL pointer to result slot
1594+
*
1595+
* slot is for use when returning tuples (i.e. composite data types)
1596+
* and is not needed when returning base (i.e. scalar) data types.
1597+
*/
1598+
TupleTableSlot *slot;
1599+
1600+
/*
1601+
* OPTIONAL pointer to misc user provided context info
1602+
*
1603+
* user_fctx is for use as a pointer to your own struct to retain
1604+
* arbitrary context information between calls for your function.
1605+
*/
1606+
void *user_fctx;
1607+
1608+
/*
1609+
* OPTIONAL pointer to struct containing arrays of attribute type input
1610+
* metainfo
1611+
*
1612+
* attinmeta is for use when returning tuples (i.e. composite data types)
1613+
* and is not needed when returning base (i.e. scalar) data types. It
1614+
* is ONLY needed if you intend to use BuildTupleFromCStrings() to create
1615+
* the return tuple.
1616+
*/
1617+
AttInMetadata *attinmeta;
1618+
1619+
/*
1620+
* memory context used to initialize structure
1621+
*
1622+
* fmctx is set by SRF_FIRSTCALL_INIT() for you, and used by
1623+
* SRF_RETURN_DONE() for cleanup. It is primarily for internal use
1624+
* by the API.
1625+
*/
1626+
MemoryContextfmctx;
1627+
1628+
}FuncCallContext;
1629+
</programlisting>
1630+
To assist you in populating this struct, several functions and macros
1631+
are available. Use
1632+
<programlisting>
1633+
SRF_IS_FIRSTCALL()
1634+
</programlisting>
1635+
to determine if your function has been called for the first or a
1636+
subsequent time. On the first call (only) use
1637+
<programlisting>
1638+
SRF_FIRSTCALL_INIT()
1639+
</programlisting>
1640+
to initialize the FuncCallContext struct. On every function call,
1641+
including the first, use
1642+
<programlisting>
1643+
SRF_PERCALL_SETUP()
1644+
</programlisting>
1645+
to properly set up for using the FuncCallContext struct and clearing
1646+
any previously returned data left over from the previous pass.
1647+
</para>
1648+
1649+
<para>
1650+
If your function has data to return, use
1651+
<programlisting>
1652+
SRF_RETURN_NEXT(funcctx, result)
1653+
</programlisting>
1654+
to send it and prepare for the next call. Finally, when your function
1655+
is finished returning data, use
1656+
<programlisting>
1657+
SRF_RETURN_DONE(funcctx)
1658+
</programlisting>
1659+
to clean up and end the SRF.
1660+
</para>
1661+
1662+
<para>
1663+
A complete pseudo-code example looks like the following:
1664+
<programlisting>
1665+
Datum
1666+
my_Set_Returning_Function(PG_FUNCTION_ARGS)
1667+
{
1668+
FuncCallContext *funcctx;
1669+
Datumresult;
1670+
1671+
[user defined declarations]
1672+
1673+
if(SRF_IS_FIRSTCALL())
1674+
{
1675+
[user defined code]
1676+
funcctx = SRF_FIRSTCALL_INIT();
1677+
[if returning composite]
1678+
[obtain slot]
1679+
funcctx->slot = slot;
1680+
[endif returning composite]
1681+
[user defined code]
1682+
}
1683+
[user defined code]
1684+
funcctx = SRF_PERCALL_SETUP();
1685+
[user defined code]
1686+
1687+
if (funcctx->call_cntr < funcctx->max_calls)
1688+
{
1689+
[user defined code]
1690+
[obtain result Datum]
1691+
SRF_RETURN_NEXT(funcctx, result);
1692+
}
1693+
else
1694+
{
1695+
SRF_RETURN_DONE(funcctx);
1696+
}
1697+
}
1698+
</programlisting>
1699+
</para>
1700+
1701+
<para>
1702+
An example of a simple composite returning SRF looks like:
1703+
<programlisting>
1704+
PG_FUNCTION_INFO_V1(testpassbyval);
1705+
Datum
1706+
testpassbyval(PG_FUNCTION_ARGS)
1707+
{
1708+
FuncCallContext *funcctx;
1709+
intcall_cntr;
1710+
intmax_calls;
1711+
TupleDesctupdesc;
1712+
TupleTableSlot *slot;
1713+
AttInMetadata *attinmeta;
1714+
1715+
/* stuff done only on the first call of the function */
1716+
if(SRF_IS_FIRSTCALL())
1717+
{
1718+
/* create a function context for cross-call persistence */
1719+
funcctx = SRF_FIRSTCALL_INIT();
1720+
1721+
/* total number of tuples to be returned */
1722+
funcctx->max_calls = PG_GETARG_UINT32(0);
1723+
1724+
/*
1725+
* Build a tuple description for a __testpassbyval tuple
1726+
*/
1727+
tupdesc = RelationNameGetTupleDesc("__testpassbyval");
1728+
1729+
/* allocate a slot for a tuple with this tupdesc */
1730+
slot = TupleDescGetSlot(tupdesc);
1731+
1732+
/* assign slot to function context */
1733+
funcctx->slot = slot;
1734+
1735+
/*
1736+
* Generate attribute metadata needed later to produce tuples from raw
1737+
* C strings
1738+
*/
1739+
attinmeta = TupleDescGetAttInMetadata(tupdesc);
1740+
funcctx->attinmeta = attinmeta;
1741+
}
1742+
1743+
/* stuff done on every call of the function */
1744+
funcctx = SRF_PERCALL_SETUP();
1745+
1746+
call_cntr = funcctx->call_cntr;
1747+
max_calls = funcctx->max_calls;
1748+
slot = funcctx->slot;
1749+
attinmeta = funcctx->attinmeta;
1750+
1751+
if (call_cntr < max_calls)/* do when there is more left to send */
1752+
{
1753+
char **values;
1754+
HeapTupletuple;
1755+
Datumresult;
1756+
1757+
/*
1758+
* Prepare a values array for storage in our slot.
1759+
* This should be an array of C strings which will
1760+
* be processed later by the appropriate "in" functions.
1761+
*/
1762+
values = (char **) palloc(3 * sizeof(char *));
1763+
values[0] = (char *) palloc(16 * sizeof(char));
1764+
values[1] = (char *) palloc(16 * sizeof(char));
1765+
values[2] = (char *) palloc(16 * sizeof(char));
1766+
1767+
snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
1768+
snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
1769+
snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));
1770+
1771+
/* build a tuple */
1772+
tuple = BuildTupleFromCStrings(attinmeta, values);
1773+
1774+
/* make the tuple into a datum */
1775+
result = TupleGetDatum(slot, tuple);
1776+
1777+
/* Clean up */
1778+
pfree(values[0]);
1779+
pfree(values[1]);
1780+
pfree(values[2]);
1781+
pfree(values);
1782+
1783+
SRF_RETURN_NEXT(funcctx, result);
1784+
}
1785+
else/* do when there is no more left */
1786+
{
1787+
SRF_RETURN_DONE(funcctx);
1788+
}
1789+
}
1790+
</programlisting>
1791+
with supporting SQL code of
1792+
<programlisting>
1793+
CREATE VIEW __testpassbyval AS
1794+
SELECT
1795+
0::INT4 AS f1,
1796+
0::INT4 AS f2,
1797+
0::INT4 AS f3;
1798+
1799+
CREATE OR REPLACE FUNCTION testpassbyval(int4, int4) RETURNS setof __testpassbyval
1800+
AS 'MODULE_PATHNAME','testpassbyval' LANGUAGE 'c' IMMUTABLE STRICT;
14621801
</programlisting>
14631802
</para>
14641803

14651804
<para>
1466-
While there are ways to construct new rows or modify
1467-
existing rows from within a C function, these
1468-
are far too complex to discuss in this manual.
1469-
Consult the backend source code for examples.
1805+
See contrib/tablefunc for more examples of Table Functions.
14701806
</para>
14711807
</sect2>
14721808

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp