#include "executor/spi.h" #include "fmgr.h" #include "funcapi.h" #include "miscadmin.h" #include "postgres.h" #include "access/heapam.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/trigger.h" #include "storage/ipc.h" #include "utils/date.h" #include "utils/memutils.h" #include "utils/syscache.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif /* CREATE OR REPLACE FUNCTION vpc() RETURNS setof record AS 'plbsh.dll', 'vpc' LANGUAGE 'C'; SELECT * FROM vpc() AS T(a INT, b TEXT); SELECT * FROM vpc() AS T(a INT, b TEXT) LIMIT 1; */ extern Datum vpc(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(vpc); Datum vpc(PG_FUNCTION_ARGS) { ReturnSetInfo* rsinfo; FuncCallContext *funcctx; int current = 0; rsinfo = (ReturnSetInfo*) fcinfo->resultinfo; if (!rsinfo) ereport(ERROR, (errmsg("Invalid ReturnSetInfo in SRF"))); if (!(rsinfo->allowedModes & SFRM_ValuePerCall)) ereport(ERROR, (errmsg("Function must support returning a SETOF composite type in SFRM_ValuePerCall mode"))); if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); funcctx->attinmeta = TupleDescGetAttInMetadata(rsinfo->expectedDesc); funcctx->user_fctx = (void*)(int*)palloc(sizeof(int)); *((int*)funcctx->user_fctx) = 0; MemoryContextSwitchTo(oldcontext); } rsinfo->returnMode = SFRM_ValuePerCall; rsinfo->setDesc = rsinfo->expectedDesc; funcctx = SRF_PERCALL_SETUP(); current = *((int*)funcctx->user_fctx); ereport(WARNING, (errmsg("## Call#%d", current))); if(current >= 10) { ereport(WARNING, (errmsg("## Last Call"))); SRF_RETURN_DONE(funcctx); } else { char buffer[100]; char* values[2]; HeapTuple tuple; Datum result; sprintf(buffer, "%d", current++); *((int*)funcctx->user_fctx) = current; values[0] = buffer; values[1] = buffer; tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); result = TupleGetDatum(slot, tuple); ereport(WARNING, (errmsg("## (return)", current))); SRF_RETURN_NEXT(funcctx, result); } }