Thread: Return setof values from C-function
Dear Colleagues !
--
Best regards,
Sincerely yours,
Yuriy Rusinov.
I have to return setof values from C-function
I wrote
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
AttInMetadata *attinmeta;
unsigned long il;
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
funcctx->max_calls = num;
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")));
attinmeta = 0;//TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = 0;//attinmeta;
MemoryContextSwitchTo(oldcontext);
funcctx->tuple_desc = BlessTupleDesc( tupdesc );
elog (INFO, "1st row");
}
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
attinmeta = funcctx->attinmeta;
HeapTuple tuple;
if (call_cntr < max_calls)
{
elog (INFO, "Rows");
unsigned long il = call_cntr;
Datum * hvalues = (Datum *)palloc (2*sizeof(Datum));
double val = gsl_histogram_get (gHist, il);
hvalues[0] = UInt32GetDatum (il);
hvalues[1] = Float8GetDatum (val);
bool * nulls = palloc( 2 * sizeof( bool ) );
elog (INFO, "%lu", il);
tuple = heap_form_tuple( tupdesc, hvalues, nulls);
elog (INFO, "%lu", il);
//BuildTupleFromCStrings (attinmeta, hvalues);
pfree (nulls);
pfree (hvalues);
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum( tuple ) );
}
else
{
SRF_RETURN_DONE(funcctx);
}
as written in documentation, but my function drops on
tuple = heap_form_tuple( tupdesc, hvalues, nulls);
Could you tell me, are there any errors ?
Best regards,
Sincerely yours,
Yuriy Rusinov.
On Tue, Dec 10, 2013 at 1:30 AM, Yuriy Rusinov <yrusinov@gmail.com> wrote: > Dear Colleagues ! > > I have to return setof values from C-function > > I wrote > > FuncCallContext *funcctx; > int call_cntr; > int max_calls; > AttInMetadata *attinmeta; > unsigned long il; > if (SRF_IS_FIRSTCALL()) > { > MemoryContext oldcontext; > funcctx = SRF_FIRSTCALL_INIT(); > oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); > funcctx->max_calls = num; > 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"))); > attinmeta = 0;//TupleDescGetAttInMetadata(tupdesc); > funcctx->attinmeta = 0;//attinmeta; > MemoryContextSwitchTo(oldcontext); > funcctx->tuple_desc = BlessTupleDesc( tupdesc ); > elog (INFO, "1st row"); > } > funcctx = SRF_PERCALL_SETUP(); > call_cntr = funcctx->call_cntr; > max_calls = funcctx->max_calls; > attinmeta = funcctx->attinmeta; > HeapTuple tuple; > if (call_cntr < max_calls) > { > elog (INFO, "Rows"); > unsigned long il = call_cntr; > Datum * hvalues = (Datum *)palloc (2*sizeof(Datum)); > double val = gsl_histogram_get (gHist, il); > hvalues[0] = UInt32GetDatum (il); > hvalues[1] = Float8GetDatum (val); > bool * nulls = palloc( 2 * sizeof( bool ) ); > > elog (INFO, "%lu", il); > tuple = heap_form_tuple( tupdesc, hvalues, nulls); > elog (INFO, "%lu", il); > //BuildTupleFromCStrings (attinmeta, hvalues); > pfree (nulls); > pfree (hvalues); > SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum( tuple ) ); > } > else > { > SRF_RETURN_DONE(funcctx); > } > as written in documentation, but my function drops on > tuple = heap_form_tuple( tupdesc, hvalues, nulls); > Could you tell me, are there any errors ? Where is 'tupdesc' coming from. Don't you need to copy it from the function context? merlin
I have added code
Oid * oids = (Oid *)palloc (2*sizeof (Oid));
oids[0] = INT8OID;
oids[1] = FLOAT8OID;
if (get_call_result_type(fcinfo, oids, &tupdescRes) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));
create type hist_point as (inum bigint, bin float8);
and
create or replace function histogram (varchar, float8, float8, int4) returns setof hist_point
as '$libdir/libfloader.so', 'histogram' language 'c' strict security definer;
but the result does not obtained.
On Tue, Dec 10, 2013 at 7:33 PM, Merlin Moncure <mmoncure@gmail.com> wrote:
Where is 'tupdesc' coming from. Don't you need to copy it from theOn Tue, Dec 10, 2013 at 1:30 AM, Yuriy Rusinov <yrusinov@gmail.com> wrote:
> Dear Colleagues !
>
> I have to return setof values from C-function
>
> I wrote
>
> FuncCallContext *funcctx;
> int call_cntr;
> int max_calls;
> AttInMetadata *attinmeta;
> unsigned long il;
> if (SRF_IS_FIRSTCALL())
> {
> MemoryContext oldcontext;
> funcctx = SRF_FIRSTCALL_INIT();
> oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
> funcctx->max_calls = num;
> 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")));
> attinmeta = 0;//TupleDescGetAttInMetadata(tupdesc);
> funcctx->attinmeta = 0;//attinmeta;
> MemoryContextSwitchTo(oldcontext);
> funcctx->tuple_desc = BlessTupleDesc( tupdesc );
> elog (INFO, "1st row");
> }
> funcctx = SRF_PERCALL_SETUP();
> call_cntr = funcctx->call_cntr;
> max_calls = funcctx->max_calls;
> attinmeta = funcctx->attinmeta;
> HeapTuple tuple;
> if (call_cntr < max_calls)
> {
> elog (INFO, "Rows");
> unsigned long il = call_cntr;
> Datum * hvalues = (Datum *)palloc (2*sizeof(Datum));
> double val = gsl_histogram_get (gHist, il);
> hvalues[0] = UInt32GetDatum (il);
> hvalues[1] = Float8GetDatum (val);
> bool * nulls = palloc( 2 * sizeof( bool ) );
>
> elog (INFO, "%lu", il);
> tuple = heap_form_tuple( tupdesc, hvalues, nulls);
> elog (INFO, "%lu", il);
> //BuildTupleFromCStrings (attinmeta, hvalues);
> pfree (nulls);
> pfree (hvalues);
> SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum( tuple ) );
> }
> else
> {
> SRF_RETURN_DONE(funcctx);
> }
> as written in documentation, but my function drops on
> tuple = heap_form_tuple( tupdesc, hvalues, nulls);
> Could you tell me, are there any errors ?
function context?
merlin
Best regards,
Sincerely yours,
Yuriy Rusinov.
On Tue, Dec 10, 2013 at 9:44 AM, Yuriy Rusinov <yrusinov@gmail.com> wrote: > I have added code > > Oid * oids = (Oid *)palloc (2*sizeof (Oid)); > oids[0] = INT8OID; > oids[1] = FLOAT8OID; > if (get_call_result_type(fcinfo, oids, &tupdescRes) != > TYPEFUNC_COMPOSITE) > ereport(ERROR, > (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), > errmsg("function returning record called in context " > "that cannot accept type record"))); > > and try to obtain tupdescRes from get_call_result_type function, before > this I do > > create type hist_point as (inum bigint, bin float8); > and > create or replace function histogram (varchar, float8, float8, int4) returns > setof hist_point > as '$libdir/libfloader.so', 'histogram' language 'c' strict security > definer; > > but the result does not obtained. what error are you getting? Also, I think you are not properly initializing NULLs array -- that could be your issue. merlin
I have received an error
The connection to the server was lost. Attempting reset: Failed
This problem was solved using by C-strings instead of Datum
such as
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
AttInMetadata *attinmeta;
unsigned long il;
TupleDesc tupdescRes;
gsl_histogram * gHist;
if (SRF_IS_FIRSTCALL())
{
size_t nr_rand = strlen ( VARDATA (PG_GETARG_VARCHAR_P(0)));
char * sql = (char *) palloc (nr_rand+1);
// strncpy (sql, (char *)PG_GETARG_VARCHAR_P(0), nr_rand);
snprintf (sql, nr_rand+1, "%s", VARDATA (PG_GETARG_VARCHAR_P (0)));
float8 xmin = PG_GETARG_FLOAT8 (1);
float8 xmax = PG_GETARG_FLOAT8 (2);
unsigned int num = PG_GETARG_UINT32(3);
//float8 * result = (float8 *) (palloc (sizeof(float8)));
//*result= 5.0;
gHist = gsl_histogram_alloc (num);
elog (INFO, "query = %s\n", sql);
gsl_histogram_set_ranges_uniform (gHist, (double)xmin, (double)xmax);
// Datum d = PointerGetDatum (gHist);
SPI_connect ();
int retVal = SPI_execute (sql, true, 0);
if (retVal != SPI_OK_SELECT)
{
elog (ERROR, "Cannot load values");
SPI_finish ();
PG_RETURN_NULL();
}
elog (INFO, "%d\n", retVal);
unsigned long int nproc = SPI_processed;
elog (INFO, "number of points is %lu, number of bins is %u", nproc, num);
// SPI_finish ();
// pfree (sql);
// PG_RETURN_NULL();
int i=0;
TupleDesc tupdesc = SPI_tuptable->tupdesc;
for (; i< nproc; i++)
{
HeapTuple tuple = SPI_tuptable->vals[i];
int ncolbuf = 1;
char * x_str = SPI_getvalue (tuple, tupdesc, ncolbuf);
if (!x_str)
continue;
double x= atof (x_str);
//elog (INFO, "value=%f", x);
int res = gsl_histogram_increment (gHist, x);
if (res != 0)
{
elog (NOTICE, "Range error, value is %lf, min value is %lf, max value %lf", x, gsl_histogram_min(gHist), gsl_histogram_max (gHist) );
continue;
}
}
SPI_finish ();
pfree (sql);
elog (INFO, "Reading was completed\n");
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
funcctx->max_calls = num;
Oid * oids = (Oid *)palloc (2*sizeof (Oid));
oids[0] = INT8OID;
oids[1] = FLOAT8OID;
if (get_call_result_type(fcinfo, oids, &tupdescRes) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));
attinmeta = TupleDescGetAttInMetadata(tupdescRes);
funcctx->attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
//funcctx->tuple_desc = BlessTupleDesc( tupdescRes );
pfree (oids);
elog (INFO, "1st row");
}
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
elog (INFO, "number of rows = %d, number of columns are %d", max_calls, tupdescRes->natts );
attinmeta = funcctx->attinmeta;
HeapTuple tuple;
if (call_cntr < max_calls)
{
elog (INFO, "Rows");
il = call_cntr;
//Datum * hvalues = (Datum *)palloc (2*sizeof(Datum));
char ** svals = (char **) palloc (2*sizeof (char*));
svals [0] = (char *) palloc(5 * sizeof(char));
svals [1] = (char *) palloc(20 * sizeof(char));
double val = gsl_histogram_get (gHist, il);
snprintf (svals[0], 5, "%lu", il);
snprintf (svals[1], 20, "%lf", val);
//hvalues[0] = UInt32GetDatum (il);
//hvalues[1] = Float8GetDatum (val);
bool * nulls = palloc( 2 * sizeof( bool ) );
elog (INFO, "%lu", il);
tuple = BuildTupleFromCStrings (attinmeta, svals);//heap_form_tuple( tupdescRes, hvalues, nulls);
elog (INFO, "%lu", il);
Datum result = HeapTupleGetDatum(tuple);
pfree (nulls);
pfree (svals[1]);
pfree (svals[0]);
pfree (svals);
//pfree (hvalues);
SRF_RETURN_NEXT(funcctx, result);//HeapTupleGetDatum( tuple ) );
}
else
{
SRF_RETURN_DONE(funcctx);
}
Thanks a lot.
Yuriy Rusinov