diff options
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 20 | ||||
-rw-r--r-- | doc/src/sgml/spi.sgml | 91 | ||||
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 155 |
3 files changed, 98 insertions, 168 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 196fdc6efdd..0cdbdcfb7b5 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ <!-- Documentation of the system catalogs, directed toward PostgreSQL developers - $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.84 2004/02/15 21:01:38 tgl Exp $ + $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.85 2004/04/01 21:28:43 tgl Exp $ --> <chapter id="catalogs"> @@ -810,24 +810,6 @@ </row> <row> - <entry><structfield>attisset</structfield></entry> - <entry><type>bool</type></entry> - <entry></entry> - <entry> - If true, this attribute is a set. In that case, what is really - stored in the attribute is the OID of a row in the - <structname>pg_proc</structname> catalog. The - <structname>pg_proc</structname> row contains the query - string that defines this set, i.e., the query to run to get - the set. So the <structfield>atttypid</structfield> (see - above) refers to the type returned by this query, but the - actual length of this attribute is the length (size) of an - <type>oid</type>. --- At least this is the theory. All this - is probably quite broken these days. - </entry> - </row> - - <row> <entry><structfield>attalign</structfield></entry> <entry><type>char</type></entry> <entry></entry> diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index c87a136bdd4..4018c2e3e1b 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.33 2004/03/17 01:05:10 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.34 2004/04/01 21:28:43 tgl Exp $ --> <chapter id="spi"> @@ -1953,8 +1953,7 @@ char * SPI_getrelname(Relation <parameter>rel</parameter>) allocations made by <function>palloc</function>, <function>repalloc</function>, or SPI utility functions (except for <function>SPI_copytuple</function>, - <function>SPI_copytupledesc</function>, - <function>SPI_copytupleintoslot</function>, + <function>SPI_returntuple</function>, <function>SPI_modifytuple</function>, and <function>SPI_palloc</function>) are made in this context. When a procedure disconnects from the SPI manager (via @@ -2169,7 +2168,9 @@ HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>) <para> <function>SPI_copytuple</function> makes a copy of a row in the - upper executor context. + upper executor context. This is normally used to return a modified + row from a trigger. In a function declared to return a composite + type, use <function>SPI_returntuple</function> instead. </para> </refsect1> @@ -2200,21 +2201,21 @@ HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>) <!-- *********************************************** --> -<refentry id="spi-spi-copytupledesc"> +<refentry id="spi-spi-returntuple"> <refmeta> - <refentrytitle>SPI_copytupledesc</refentrytitle> + <refentrytitle>SPI_returntuple</refentrytitle> </refmeta> <refnamediv> - <refname>SPI_copytupledesc</refname> - <refpurpose>make a copy of a row descriptor in the upper executor context</refpurpose> + <refname>SPI_returntuple</refname> + <refpurpose>prepare to return a tuple as a Datum</refpurpose> </refnamediv> - <indexterm><primary>SPI_copytupledesc</primary></indexterm> + <indexterm><primary>SPI_returntuple</primary></indexterm> <refsynopsisdiv> <synopsis> -TupleDesc SPI_copytupledesc(TupleDesc <parameter>tupdesc</parameter>) +HeapTupleHeader SPI_returntuple(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>) </synopsis> </refsynopsisdiv> @@ -2222,63 +2223,16 @@ TupleDesc SPI_copytupledesc(TupleDesc <parameter>tupdesc</parameter>) <title>Description</title> <para> - <function>SPI_copytupledesc</function> makes a copy of a row - descriptor in the upper executor context. + <function>SPI_returntuple</function> makes a copy of a row in + the upper executor context, returning it in the form of a rowtype Datum. + The returned pointer need only be converted to Datum via PointerGetDatum + before returning. </para> - </refsect1> - - <refsect1> - <title>Arguments</title> - - <variablelist> - <varlistentry> - <term><literal>TupleDesc <parameter>tupdesc</parameter></literal></term> - <listitem> - <para> - row descriptor to be copied - </para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>Return Value</title> - - <para> - the copied row descriptor; <symbol>NULL</symbol> only if - <parameter>tupdesc</parameter> is <symbol>NULL</symbol> - </para> - </refsect1> -</refentry> - -<!-- *********************************************** --> - -<refentry id="spi-spi-copytupleintoslot"> - <refmeta> - <refentrytitle>SPI_copytupleintoslot</refentrytitle> - </refmeta> - - <refnamediv> - <refname>SPI_copytupleintoslot</refname> - <refpurpose>make a copy of a row and descriptor in the upper executor context</refpurpose> - </refnamediv> - - <indexterm><primary>SPI_copytupleintoslot</primary></indexterm> - - <refsynopsisdiv> -<synopsis> -TupleTableSlot * SPI_copytupleintoslot(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>) -</synopsis> - </refsynopsisdiv> - - <refsect1> - <title>Description</title> <para> - <function>SPI_copytupleintoslot</function> makes a copy of a row in - the upper executor context, returning it in the form of a filled-in - <type>TupleTableSlot</type> structure. + Note that this should be used for functions that are declared to return + composite types. It is not used for triggers; use + <function>SPI_copytuple</> for returning a modified row in a trigger. </para> </refsect1> @@ -2299,7 +2253,8 @@ TupleTableSlot * SPI_copytupleintoslot(HeapTuple <parameter>row</parameter>, Tup <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> <listitem> <para> - row descriptor to be copied + descriptor for row (pass the same descriptor each time for most + effective caching) </para> </listitem> </varlistentry> @@ -2310,9 +2265,9 @@ TupleTableSlot * SPI_copytupleintoslot(HeapTuple <parameter>row</parameter>, Tup <title>Return Value</title> <para> - <type>TupleTableSlot</type> containing the copied row and - descriptor; <symbol>NULL</symbol> only if - <parameter>row</parameter> or <parameter>rowdesc</parameter> are + <type>HeapTupleHeader</type> pointing to copied row; + <symbol>NULL</symbol> only if + <parameter>row</parameter> or <parameter>rowdesc</parameter> is <symbol>NULL</symbol> </para> </refsect1> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index c8f71296857..4b06aefd362 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.80 2004/03/09 16:57:47 neilc Exp $ +$PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.81 2004/04/01 21:28:43 tgl Exp $ --> <sect1 id="xfunc"> @@ -1623,7 +1623,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid #include "executor/executor.h" /* for GetAttributeByName() */ bool -c_overpaid(TupleTableSlot *t, /* the current row of emp */ +c_overpaid(HeapTupleHeader t, /* the current row of emp */ int32 limit) { bool isnull; @@ -1647,7 +1647,7 @@ PG_FUNCTION_INFO_V1(c_overpaid); Datum c_overpaid(PG_FUNCTION_ARGS) { - TupleTableSlot *t = (TupleTableSlot *) PG_GETARG_POINTER(0); + HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); int32 limit = PG_GETARG_INT32(1); bool isnull; int32 salary; @@ -1666,7 +1666,8 @@ c_overpaid(PG_FUNCTION_ARGS) <function>GetAttributeByName</function> is the <productname>PostgreSQL</productname> system function that returns attributes out of the specified row. It has - three arguments: the argument of type <type>TupleTableSlot*</type> passed into + three arguments: the argument of type <type>HeapTupleHeader</type> passed + into the function, the name of the desired attribute, and a return parameter that tells whether the attribute is null. <function>GetAttributeByName</function> returns a <type>Datum</type> @@ -1675,14 +1676,22 @@ c_overpaid(PG_FUNCTION_ARGS) </para> <para> + There is also <function>GetAttributeByNum</function>, which selects + the target attribute by column number instead of name. + </para> + + <para> The following command declares the function <function>c_overpaid</function> in SQL: <programlisting> CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean AS '<replaceable>DIRECTORY</replaceable>/funcs', 'c_overpaid' - LANGUAGE C; + LANGUAGE C STRICT; </programlisting> + + Notice we have used <literal>STRICT</> so that we did not have to + check whether the input arguments were NULL. </para> </sect2> @@ -1700,38 +1709,25 @@ CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean </para> <para> - The support for returning composite data types (or rows) starts - with the <structname>AttInMetadata</> structure. This structure - holds arrays of individual attribute information needed to create - a row from raw C strings. The information contained in the - structure is derived from a <structname>TupleDesc</> structure, - but it is stored to avoid redundant computations on each call to - a set-returning function (see next section). In the case of a - function returning a set, the <structname>AttInMetadata</> - structure should be computed once during the first call and saved - for reuse in later calls. <structname>AttInMetadata</> also - saves a pointer to the original <structname>TupleDesc</>. -<programlisting> -typedef struct AttInMetadata -{ - /* full TupleDesc */ - TupleDesc tupdesc; - - /* array of attribute type input function finfo */ - FmgrInfo *attinfuncs; - - /* array of attribute type typelem */ - Oid *attelems; - - /* array of attribute typmod */ - int32 *atttypmods; -} AttInMetadata; -</programlisting> + There are two ways you can build a composite data value (henceforth + a <quote>tuple</>): you can build it from an array of Datum values, + or from an array of C strings that can be passed to the input + conversion functions of the tuple's column datatypes. In either + case, you first need to obtain or construct a <structname>TupleDesc</> + descriptor for the tuple structure. When working with Datums, you + pass the <structname>TupleDesc</> to <function>BlessTupleDesc</>, + and then call <function>heap_formtuple</> for each row. When working + with C strings, you pass the <structname>TupleDesc</> to + <function>TupleDescGetAttInMetadata</>, and then call + <function>BuildTupleFromCStrings</> for each row. In the case of a + function returning a set of tuples, the setup steps can all be done + once during the first call of the function. </para> <para> - To assist you in populating this structure, several functions and a macro - are available. Use + Several helper functions are available for setting up the initial + <structname>TupleDesc</>. If you want to use a named composite type, + you can fetch the information from the system catalogs. Use <programlisting> TupleDesc RelationNameGetTupleDesc(const char *relname) </programlisting> @@ -1741,36 +1737,43 @@ TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases) </programlisting> to get a <structname>TupleDesc</> based on a type OID. This can be used to get a <structname>TupleDesc</> for a base or - composite type. Then + composite type. When writing a function that returns + <structname>record</>, the expected <structname>TupleDesc</> + must be passed in by the caller. + </para> + + <para> + Once you have a <structname>TupleDesc</>, call +<programlisting> +TupleDesc BlessTupleDesc(TupleDesc tupdesc) +</programlisting> + if you plan to work with Datums, or <programlisting> AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc) </programlisting> - will return a pointer to an <structname>AttInMetadata</>, - initialized based on the given - <structname>TupleDesc</>. <structname>AttInMetadata</> can be - used in conjunction with C strings to produce a properly formed - row value (internally called tuple). + if you plan to work with C strings. If you are writing a function + returning set, you can save the results of these functions in the + <structname>FuncCallContext</> structure --- use the + <structfield>tuple_desc</> or <structfield>attinmeta</> field + respectively. </para> <para> - To return a tuple you must create a tuple slot based on the - <structname>TupleDesc</>. You can use + When working with Datums, use <programlisting> -TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc) +HeapTuple heap_formtuple(TupleDesc tupdesc, Datum *values, char *nulls) </programlisting> - to initialize this tuple slot, or obtain one through other (user provided) - means. The tuple slot is needed to create a <type>Datum</> for return by the - function. The same slot can (and should) be reused on each call. + to build a <structname>HeapTuple</> given user data in Datum form. </para> <para> - After constructing an <structname>AttInMetadata</> structure, + When working with C strings, use <programlisting> HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) </programlisting> - can be used to build a <structname>HeapTuple</> given user data - in C string form. <literal>values</literal> is an array of C strings, one for - each attribute of the return row. Each C string should be in + to build a <structname>HeapTuple</> given user data + in C string form. <literal>values</literal> is an array of C strings, + one for each attribute of the return row. Each C string should be in the form expected by the input function of the attribute data type. In order to return a null value for one of the attributes, the corresponding pointer in the <parameter>values</> array @@ -1779,24 +1782,12 @@ HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) </para> <para> - Building a tuple via <function>TupleDescGetAttInMetadata</> and - <function>BuildTupleFromCStrings</> is only convenient if your - function naturally computes the values to be returned as text - strings. If your code naturally computes the values as a set of - <type>Datum</> values, you should instead use the underlying - function <function>heap_formtuple</> to convert the - <type>Datum</type> values directly into a tuple. You will still need - the <structname>TupleDesc</> and a <structname>TupleTableSlot</>, - but not <structname>AttInMetadata</>. - </para> - - <para> Once you have built a tuple to return from your function, it must be converted into a <type>Datum</>. Use <programlisting> -TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple) +HeapTupleGetDatum(HeapTuple tuple) </programlisting> - to get a <type>Datum</> given a tuple and a slot. This + to convert a <structname>HeapTuple</> into a valid Datum. This <type>Datum</> can be returned directly if you intend to return just a single row, or it can be used as the current return value in a set-returning function. @@ -1851,8 +1842,8 @@ typedef struct /* * OPTIONAL pointer to result slot * - * slot is for use when returning tuples (i.e., composite data types) - * and is not needed when returning base data types. + * This is obsolete and only present for backwards compatibility, viz, + * user-defined SRFs that use the deprecated TupleDescGetSlot(). */ TupleTableSlot *slot; @@ -1868,9 +1859,9 @@ typedef struct * OPTIONAL pointer to struct containing attribute type input metadata * * attinmeta is for use when returning tuples (i.e., composite data types) - * and is not needed when returning base data types. It - * is only needed if you intend to use BuildTupleFromCStrings() to create - * the return tuple. + * and is not used when returning base data types. It is only needed + * if you intend to use BuildTupleFromCStrings() to create the return + * tuple. */ AttInMetadata *attinmeta; @@ -1883,6 +1874,18 @@ typedef struct * of the SRF. */ MemoryContext multi_call_memory_ctx; + + /* + * OPTIONAL pointer to struct containing tuple description + * + * tuple_desc is for use when returning tuples (i.e. composite data types) + * and is only needed if you are going to build the tuples with + * heap_formtuple() rather than with BuildTupleFromCStrings(). Note that + * the TupleDesc pointer stored here should usually have been run through + * BlessTupleDesc() first. + */ + TupleDesc tuple_desc; + } FuncCallContext; </programlisting> </para> @@ -1956,8 +1959,6 @@ my_set_returning_function(PG_FUNCTION_ARGS) <replaceable>user code</replaceable> <replaceable>if returning composite</replaceable> <replaceable>build TupleDesc, and perhaps AttInMetadata</replaceable> - <replaceable>obtain slot</replaceable> - funcctx->slot = slot; <replaceable>endif returning composite</replaceable> <replaceable>user code</replaceable> MemoryContextSwitchTo(oldcontext); @@ -1998,7 +1999,6 @@ testpassbyval(PG_FUNCTION_ARGS) int call_cntr; int max_calls; TupleDesc tupdesc; - TupleTableSlot *slot; AttInMetadata *attinmeta; /* stuff done only on the first call of the function */ @@ -2018,12 +2018,6 @@ testpassbyval(PG_FUNCTION_ARGS) /* Build a tuple description for a __testpassbyval tuple */ tupdesc = RelationNameGetTupleDesc("__testpassbyval"); - /* allocate a slot for a tuple with this tupdesc */ - slot = TupleDescGetSlot(tupdesc); - - /* assign slot to function context */ - funcctx->slot = slot; - /* * generate attribute metadata needed later to produce tuples from raw * C strings @@ -2039,7 +2033,6 @@ testpassbyval(PG_FUNCTION_ARGS) call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; - slot = funcctx->slot; attinmeta = funcctx->attinmeta; if (call_cntr < max_calls) /* do when there is more left to send */ @@ -2049,7 +2042,7 @@ testpassbyval(PG_FUNCTION_ARGS) Datum result; /* - * Prepare a values array for storage in our slot. + * Prepare a values array for building the returned tuple. * This should be an array of C strings which will * be processed later by the type input functions. */ @@ -2066,7 +2059,7 @@ testpassbyval(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ - result = TupleGetDatum(slot, tuple); + result = HeapTupleGetDatum(tuple); /* clean up (this is not really necessary) */ pfree(values[0]); |