Hello,
I have created a set-returning C function and a view that selects all
the returned rows. When I use SELECT * FROM theview, the returned rows
look fine. But if I use, e.g., SELECT count(*) FROM theview or SELECT
sum(a) FROM theview, I get a segmentation fault.
LOG: server process (PID 7099) was terminated by signal 11:
Segmentation fault
Is this a bug? SELECT count(*), sum(a) FROM thefunction() works fine.
I have created a small example that demonstrates the problem (see
below). If the C function only returns few rows, everything works. If
the function returns more rows (e.g., 5,000), I get the segmentation fault.
I have expericenced this on 8.4.0:
chr=# select version(); version
-------------------------------------------------------------------------------------------------------------PostgreSQL
8.4.0on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC)
4.1.2 20070115 (SUSE Linux), 64-bit
chr=# show work_mem ;work_mem
----------256MB
EXAMPLE:
create table demotbl(a int, b int, c int);
create function demosrf() returns setof demotbl language 'c' as
'/tmp/demo.so';
create view demoview as
select * from demotbl
union all
select * from demosrf();
The C code is shown below.
#include "postgres.h"
#include "tupdesc.h"
#include "funcapi.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(demosrf);
Datum
demosrf(PG_FUNCTION_ARGS)
{ ReturnSetInfo *rsinfo = (ReturnSetInfo *)fcinfo->resultinfo; TupleDesc tupdesc; Tuplestorestate *tupstore;
AttInMetadata*attinmeta; int numberOfAttributes; int i, j; Datum *values; bool *isnull; extern int work_mem;
if(rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Contextdoes not accept a set"))); if(!(rsinfo->allowedModes & SFRM_Materialize))ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Materialize not allowed")));
tupdesc = rsinfo->expectedDesc; tupstore = tuplestore_begin_heap(false, false, work_mem);
attinmeta = TupleDescGetAttInMetadata(tupdesc); numberOfAttributes = attinmeta->tupdesc->natts;
values = (Datum *)palloc(numberOfAttributes * sizeof(Datum)); isnull = (bool *)palloc(numberOfAttributes *
sizeof(bool));
// Create rows for(i = 0; i < 10000; i++) {for(j = 0; j < numberOfAttributes; j++) { isnull[j] = false;
values[j]= Int32GetDatum(i);}tuplestore_putvalues(tupstore, tupdesc, values, isnull); }
rsinfo->returnMode = SFRM_Materialize; rsinfo->setResult = tupstore; return (Datum)0;
}
Best regards,
Christian Thomsen