Hi
 
I'm attempting to program a simple SRF function but it constantly crashes 
(details and code below).
 
Any idea why?
 
Thanks!
 
-Itai
-------------------------------------------------------------
Environment
-------------------------------------------------------------
Ubunto: 14.04.2 (server)
PG Ver: PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 
4.8.2-19ubuntu1) 4.8.2, 64-bit
Install: deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main
Dev: postgresql-server-dev-9.4 (9.4.1-1.pgdg14.04+1)
-------------------------------------------------------------
Execution
-------------------------------------------------------------
select * from pg_srf();
INFO:  ----------- data source -----------
INFO:  value: 1203000000
INFO:  is_even: 1
INFO:  value: 1203000001
INFO:  is_even: 0
...
INFO:  value: 1203003998
INFO:  is_even: 1
INFO:  value: 1203003999
INFO:  is_even: 0
INFO:  ----------- data context -----------
INFO:  call_cntr: 0
INFO:  value: 1203000000
INFO:  is_even: 1
INFO:  call_cntr: 1
INFO:  value: 1203000001
INFO:  is_even: 0
INFO:  call_cntr: 2
server closed the connection unexpectedly
 This probably means the server terminated abnormally
 before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!> 
-------------------------------------------------------------
pg_srf.h
-------------------------------------------------------------
#ifndef PGSRF_H
#define PGSRF_H
#include "fmgr.h"
// using int as bool due to a different issue (one prob. at a time)
typedef struct Number_tag
{
 int value;
 int is_even;
} Number;
typedef struct NumberList_tag
{
 int length;
 Number ** pp_numbers;
} NumberList;
extern Datum pg_srf(PG_FUNCTION_ARGS);
#endif
-------------------------------------------------------------
pg_srf.c
-------------------------------------------------------------
#include <postgres.h>
#include <access/htup_details.h>
#include <catalog/pg_type.h>
#include <funcapi.h>
#include "pg_srf.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(pg_srf);
Datum
pg_srf(PG_FUNCTION_ARGS)
{
 int call_cntr, i, length, base_num;
 Number * num;
 NumberList * list;
 HeapTuple rettuple;
 FuncCallContext *funcctx;
 MemoryContext oldcontext;
 if (SRF_IS_FIRSTCALL())
 {
  length = 4000;
  base_num = 1203000000;
  list = (NumberList *)palloc(sizeof(NumberList));
  list->pp_numbers = (Number **)palloc(sizeof(Number*) * length);
  list->length = length;
  i = 0;
  for (; i < length; i++)
  {
   num = (Number *)palloc(sizeof(Number));
   num->value = base_num + i;
   num->is_even = ((base_num + i) % 2 == 0) ? 1 : 0;
   list->pp_numbers[i] = num;
  }
  ereport(INFO, (errmsg("----------- data source -----------")));
  i = 0;
  for (; i < length; i++)
  {
   ereport(INFO, (errmsg("value: %d", list->pp_numbers[i]->value)));
   ereport(INFO, (errmsg("is_even: %d", list->pp_numbers[i]->is_even)));   
  }
  
  funcctx = SRF_FIRSTCALL_INIT();
  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
  funcctx->user_fctx = list;
  funcctx->max_calls = list->length;
  if (get_call_result_type(fcinfo, NULL, &funcctx->tuple_desc) != 
TYPEFUNC_COMPOSITE)
   ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
   errmsg("check if sql function definition returns SETOF record")));

  BlessTupleDesc(funcctx->tuple_desc);
  MemoryContextSwitchTo(oldcontext);
 }
 funcctx = SRF_PERCALL_SETUP();
 list = funcctx->user_fctx;
 call_cntr = funcctx->call_cntr;
 if (call_cntr < funcctx->max_calls)
 {
  Datum retvals[2];
  bool retnulls[2];
  
  if (call_cntr == 0) 
  {
   ereport(INFO, (errmsg("----------- data context -----------")));
  }
  ereport(INFO, (errmsg("call_cntr: %d", call_cntr)));
  ereport(INFO, (errmsg("value: %d", list->pp_numbers[call_cntr]->value)));
  retvals[0] = Int32GetDatum(list->pp_numbers[call_cntr]->value);
  ereport(INFO, (errmsg("is_even: %d", list->pp_numbers[call_cntr]->is_even)));
  retvals[1] = Int32GetDatum(list->pp_numbers[call_cntr]->is_even);
  retnulls[0] = false;
  retnulls[1] = false;
  rettuple = heap_form_tuple(funcctx->tuple_desc, retvals, retnulls);
  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(rettuple));
 }
 else
 {
  SRF_RETURN_DONE(funcctx);
 }
}
-------------------------------------------------------------
Makefile
-------------------------------------------------------------
MODULES = pg_srf
OBJS = pg_srf.o
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
-------------------------------------------------------------
SQL
-------------------------------------------------------------
CREATE OR REPLACE FUNCTION
  pg_srf(OUT value integer, OUT is_even integer)
RETURNS 
 SETOF record
AS
  'pg_srf.so', 'pg_srf'
LANGUAGE
  C
STRICT
IMMUTABLE;
                                          

Reply via email to