/*
 * =====================================================================================
 *
 *       Filename:  test.c
 *
 *    Description:  function returning multiple row
 *        Version:  1.0
 *        Created:  02/10/2014 02:52:22 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Amul Sul
 *
 * =====================================================================================
 */

#include "postgres.h"
#include "funcapi.h"
#include "executor/spi.h"

#define sql "select * from temp limit 4"

Datum show_eudc(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(show_eudc);

Datum
show_eudc(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	int call_cntr;
	int max_calls;
	
	HeapTupleHeader  values[4];

	/*  Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		MemoryContext oldcontext;

		int ret, i;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		
		/*  create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();
		funcctx->max_calls = 2;

		/*  switch to memory context appropriate for multiple function calls */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();

		ret = SPI_exec(sql, 0);
		
		if (ret == SPI_OK_SELECT) {
			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			for(i=0; i < 4; i++)
				values[i] = SPI_returntuple(tuptable->vals[i], tupdesc);
		}
	
		/*  Build a tuple descriptor for our result type */
		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					errmsg("function returning record called in context "
							"that cannot accept type record")));
		}

		MemoryContextSwitchTo(oldcontext);

	}/* End if(SRF_IS_FIRSTCALL) */

	/*  stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;

	if (call_cntr < max_calls) {

		elog(NOTICE, "call_cntr : %d", call_cntr);

		SRF_RETURN_NEXT(funcctx, values[call_cntr]);
	} else {
		/*  Do when there is no more left. */
		SPI_finish();
		SRF_RETURN_DONE(funcctx);
	} 
	
}/* end show_res */ 
