Re: Table Function API doc patch

Поиск
Список
Период
Сортировка
Искать
От
Bruce Momjian
Тема
Re: Table Function API doc patch
Дата
Msg-id
200207160603.g6G631208215@candle.pha.pa.us
Ответ на
Список
Дерево обсуждения
Re: Table Function API doc patch Joe Conway <mail@joeconway.com>
Re: Table Function API doc patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Table Function API doc patch Bruce Momjian <pgman@candle.pha.pa.us>

Your patch has been added to the PostgreSQL unapplied patches list at:

	http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Joe Conway wrote:
> 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 other 
> day. It also refers to "see contrib/tablefunc for more examples", which 
> is next on my list of things to finish and submit.
> 
> If there are no objections, please apply.
> 
> Thanks,
> 
> Joe

[ text/html is unsupported, treating like TEXT/PLAIN ]

> Index: doc/src/sgml/xfunc.sgml
> ===================================================================
> RCS file: /opt/src/cvs/pgsql/doc/src/sgml/xfunc.sgml,v
> retrieving revision 1.52
> diff -c -r1.52 xfunc.sgml
> *** doc/src/sgml/xfunc.sgml	20 Jun 2002 16:57:00 -0000	1.52
> --- doc/src/sgml/xfunc.sgml	10 Jul 2002 22:53:23 -0000
> ***************
> *** 1461,1472 ****
>   LANGUAGE C;
>   
>       
>   
>       
> !      While there are ways to construct new rows or modify  
> !      existing rows from within a C function, these
> !      are far too complex to discuss in this manual.
> !      Consult the backend source code for examples.
>       
>      
>   
> --- 1461,1808 ----
>   LANGUAGE C;
>   
>       
> +    
> + 
> +    
> +     Table Function API
> + 
> +     
> +      The Table Function API assists in the creation of a user defined
> +      C Language table functions ().
> +      Table functions are functions that produce a set of rows, made up of
> +      either base (scalar) data types, or composite (multi-column) data types.
> +      The API is split into two main components: support for returning
> +      composite data types, and support for returning multiple rows
> +      (set returning functions or SRFs).
> +     
> + 
> +     
> +      The Table Function API relies on macros and functions to suppress most
> +      of the complexity of building composite data types and return multiple
> +      results.  In addition to the version-1 conventions discussed elsewhere,
> +      a table function always requires the following:
> + 
> + #include "funcapi.h"
> + 
> +     
> + 
> +     
> +      The Table Function API support for returning composite data types
> +      (or tuples) starts with the AttInMetadata struct. This struct holds
> +      arrays of individual attribute information needed to create a tuple from
> +      raw C strings. It also requires a copy of the TupleDesc. The information
> +      carried here is derived from the TupleDesc, but it is stored here to
> +      avoid redundant cpu cycles on each call to a Table Function.
> + 
> + typedef struct
> + {
> + 	/* full TupleDesc */
> + 	TupleDesc	   tupdesc;
> + 
> + 	/* pointer to array of attribute "type"in finfo */
> + 	FmgrInfo	   *attinfuncs;
> + 
> + 	/* pointer to array of attribute type typelem */
> + 	Oid			   *attelems;
> + 
> + 	/* pointer to array of attribute type typtypmod */
> + 	int4		   *atttypmods;
> + 
> + }	AttInMetadata;
> + 
> +      To assist you in populating this struct, several functions and a macro
> +      are available. Use
> + 
> + TupleDesc RelationNameGetTupleDesc(char *relname)
> + 
> +      to get a TupleDesc based on the function's return type relation, or
> + 
> + TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
> + 
> +      to get a TupleDesc based on the function's type oid. This can be used to
> +      get a TupleDesc for a base (scalar), or composite (relation) type. Then
> + 
> + AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
> + 
> +      will return a pointer to an AttInMetadata struct, initialized based on
> +      the function's TupleDesc. AttInMetadata is be used in conjunction with
> +      C strings to produce a properly formed tuple. The metadata is stored here
> +      for use across calls to avoid redundant work.
> +     
> + 
> +     
> +      In order to return a tuple you must create a tuple slot based on the
> +      TupleDesc. You can use
> + 
> + TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc)
> + 
> +      to initialize this tuple slot, or obtain one through other (user provided)
> +      means. The tuple slot is needed to create a Datum for return by the
> +      function.
> +     
> + 
> +     
> +      If desired,
> + 
> + HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
> + 
> +      can be used to build a HeapTuple given user data in C string form.
> +      "values" is an array of C strings, one for each attribute of the return
> +      tuple. The C strings should be in the form expected by the "in" function
> +      of the attribute data type. For more information on this requirement,
> +      see the individual data type "in" functions in the source code
> +      (e.g. textin() for data type TEXT). In order to return a NULL value for
> +      one of the attributes, the corresponding pointer in the "values" array
> +      should be set to NULL.
> +     
> + 
> +     
> +      Finally, in order to return a tuple using the SRF portion of the API
> +      (described below), the tuple must be converted into a Datum. Use
> + 
> + TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple)
> + 
> +      to get a Datum given a tuple and a slot.
> +     
> + 
> +     
> +      The Table Function API support for set returning functions starts with
> +      the FuncCallContext struct. This struct holds function context for
> +      SRFs using fcinfo->flinfo->fn_extra to hold a pointer to it across calls.
> + 
> + typedef struct
> + {
> + 	/*
> + 	 * Number of times we've been called before.
> + 	 * 
> + 	 * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
> + 	 * incremented for you every time SRF_RETURN_NEXT() is called.
> + 	 */
> + 	uint32			call_cntr;
> + 
> + 	/*
> + 	 * OPTIONAL maximum number of calls
> + 	 *
> + 	 * max_calls is here for convenience ONLY and setting it is OPTIONAL.
> + 	 * If not set, you must provide alternative means to know when the
> + 	 * function is done.
> + 	 */
> + 	uint32			max_calls;
> + 
> + 	/*
> + 	 * OPTIONAL pointer to result slot
> + 	 * 
> + 	 * slot is for use when returning tuples (i.e. composite data types)
> + 	 * and is not needed when returning base (i.e. scalar) data types.
> + 	 */
> + 	TupleTableSlot *slot;
> + 
> + 	/*
> + 	 * OPTIONAL pointer to misc user provided context info
> + 	 * 
> + 	 * user_fctx is for use as a pointer to your own struct to retain
> + 	 * arbitrary context information between calls for your function.
> + 	 */
> + 	void		   *user_fctx;
> + 
> + 	/*
> + 	 * OPTIONAL pointer to struct containing arrays of attribute type input
> + 	 * metainfo
> + 	 * 
> + 	 * attinmeta is for use when returning tuples (i.e. composite data types)
> + 	 * and is not needed when returning base (i.e. scalar) data types. It
> + 	 * is ONLY needed if you intend to use BuildTupleFromCStrings() to create
> + 	 * the return tuple.
> + 	 */
> + 	AttInMetadata	   *attinmeta;
> + 
> + 	/*
> + 	 * memory context used to initialize structure
> + 	 *
> + 	 * fmctx is set by SRF_FIRSTCALL_INIT() for you, and used by
> + 	 * SRF_RETURN_DONE() for cleanup. It is primarily for internal use
> + 	 * by the API.
> + 	 */
> + 	MemoryContext	fmctx;
> + 
> + }	FuncCallContext;
> + 
> +      To assist you in populating this struct, several functions and macros
> +      are available. Use
> + 
> + SRF_IS_FIRSTCALL()
> + 
> +      to determine if your function has been called for the first or a
> +      subsequent time. On the first call (only) use
> + 
> + SRF_FIRSTCALL_INIT()
> + 
> +      to initialize the FuncCallContext struct. On every function call,
> +      including the first, use
> + 
> + SRF_PERCALL_SETUP()
> + 
> +      to properly set up for using the FuncCallContext struct and clearing
> +      any previously returned data left over from the previous pass.
> +     
> + 
> +     
> +      If your function has data to return, use
> + 
> + SRF_RETURN_NEXT(funcctx, result)
> + 
> +      to send it and prepare for the next call. Finally, when your function
> +      is finished returning data, use
> + 
> + SRF_RETURN_DONE(funcctx)
> + 
> +      to clean up and end the SRF.
> +     
> + 
> +     
> +      A complete pseudo-code example looks like the following:
> + 
> + Datum
> + my_Set_Returning_Function(PG_FUNCTION_ARGS)
> + {
> + 	FuncCallContext	   *funcctx;
> + 	Datum				result;
> + 
> + 	[user defined declarations]
> + 
> + 	if(SRF_IS_FIRSTCALL())
> + 	{
> + 		[user defined code]
> + 		funcctx = SRF_FIRSTCALL_INIT();
> + 		[if returning composite]
> + 			[obtain slot]
> + 			funcctx->slot = slot;
> + 		[endif returning composite]
> + 		[user defined code]
> + 	}
> + 	[user defined code]
> + 	funcctx = SRF_PERCALL_SETUP();
> + 	[user defined code]
> + 
> + 	if (funcctx->call_cntr < funcctx->max_calls)
> + 	{
> + 		[user defined code]
> + 		[obtain result Datum]
> + 		SRF_RETURN_NEXT(funcctx, result);
> + 	}
> + 	else
> + 	{
> + 		SRF_RETURN_DONE(funcctx);
> + 	}
> + }
> + 
> +     
> + 
> +     
> +      An example of a simple composite returning SRF looks like:
> + 
> + PG_FUNCTION_INFO_V1(testpassbyval);
> + Datum
> + testpassbyval(PG_FUNCTION_ARGS)
> + {
> + 	FuncCallContext	   *funcctx;
> + 	int					call_cntr;
> + 	int					max_calls;
> + 	TupleDesc			tupdesc;
> + 	TupleTableSlot	   *slot;
> + 	AttInMetadata	   *attinmeta;
> + 
> + 	/* stuff done only on the first call of the function */
> +  	if(SRF_IS_FIRSTCALL())
> +  	{
> + 		/* create a function context for cross-call persistence */
> +  		funcctx = SRF_FIRSTCALL_INIT();
> + 
> + 		/* total number of tuples to be returned */
> + 		funcctx->max_calls = PG_GETARG_UINT32(0);
> + 
> + 		/*
> + 		 * 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
> + 		 */
> + 		attinmeta = TupleDescGetAttInMetadata(tupdesc);
> + 		funcctx->attinmeta = attinmeta;
> +     }
> + 
> + 	/* stuff done on every call of the function */
> +  	funcctx = SRF_PERCALL_SETUP();
> + 
> + 	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 */
> +  	{
> + 		char	   **values;
> + 		HeapTuple	tuple;
> + 		Datum		result;
> + 
> + 		/*
> + 		 * Prepare a values array for storage in our slot.
> + 		 * This should be an array of C strings which will
> + 		 * be processed later by the appropriate "in" functions.
> + 		 */
> + 		values = (char **) palloc(3 * sizeof(char *));
> + 		values[0] = (char *) palloc(16 * sizeof(char));
> + 		values[1] = (char *) palloc(16 * sizeof(char));
> + 		values[2] = (char *) palloc(16 * sizeof(char));
> + 
> + 		snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
> + 		snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
> + 		snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));
> + 
> + 		/* build a tuple */
> + 		tuple = BuildTupleFromCStrings(attinmeta, values);
> + 
> + 		/* make the tuple into a datum */
> + 		result = TupleGetDatum(slot, tuple);
> + 
> + 		/* Clean up */
> + 		pfree(values[0]);
> + 		pfree(values[1]);
> + 		pfree(values[2]);
> + 		pfree(values);
> + 
> +  		SRF_RETURN_NEXT(funcctx, result);
> +  	}
> +  	else	/* do when there is no more left */
> +  	{
> +  		SRF_RETURN_DONE(funcctx);
> +  	}
> + }
> + 
> +      with supporting SQL code of
> + 
> + CREATE VIEW __testpassbyval AS
> +   SELECT
> +     0::INT4 AS f1,
> +     0::INT4 AS f2,
> +     0::INT4 AS f3;
> + 
> + CREATE OR REPLACE FUNCTION testpassbyval(int4, int4) RETURNS setof __testpassbyval
> +   AS 'MODULE_PATHNAME','testpassbyval' LANGUAGE 'c' IMMUTABLE STRICT;
> + 
> +     
>   
>       
> !      See contrib/tablefunc for more examples of Table Functions.
>       
>      
>   

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
В списке pgsql-patches по дате отправления
От: Bruce Momjian
Дата:
Сообщение: Re: psql: fix memory leak
От: Bruce Momjian
Дата:
Сообщение: Re: several minor cleanups
FAQ