Thread: c-function returns multiple rows
Hello, I have the following problem ( at PostgreSQL 7.3.3 on Red Hat Linux 7.1) with c-functions returning multiple rows. Here is a transcript of the test example: ////////////////////////////////////////// #include <stdlib.h> #include "postgres.h" #include "fmgr.h" #include "nodes/execnodes.h" PG_FUNCTION_INFO_V1(dc_ftx); Datum dc_ftx(PG_FUNCTION_ARGS) { ReturnSetInfo* rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi->isDone = ExprEndResult; PG_RETURN_NULL(); } cd /dot/users/kirill/test_pg_functions gcc -I/dot/dc4/postgres/postgresql-7.3.3/src/include/ -fpic -c dc_ftx.c gcc -shared -o dc_ftx.so dc_ftx.o psql mydb mydb=# create function dc_ftx(int4) RETURNS SETOF INT4 as '/dot/users/kirill/test_pg_functions/dc_ftx.so' language 'C'; CREATE mydb=# select dc_ftx(10); /////////////////////////////////////////// In my opinion this function call shall returns a empty table, but this call does not end. I suppose that (rsi->isDone = ExprEndResult) has no effect. Please help me. Kirill Krasnosselov
On Fri, 22 Aug 2003, Kirill Krasnosselov wrote: > Hello, I have the following problem ( at PostgreSQL 7.3.3 on Red Hat > Linux 7.1) with c-functions returning multiple rows. > > Here is a transcript of the test example: > > ////////////////////////////////////////// > > #include <stdlib.h> > #include "postgres.h" > #include "fmgr.h" > #include "nodes/execnodes.h" > > > PG_FUNCTION_INFO_V1(dc_ftx); > Datum > dc_ftx(PG_FUNCTION_ARGS) > { ReturnSetInfo* rsi = (ReturnSetInfo *)fcinfo->resultinfo; > rsi->isDone = ExprEndResult; > PG_RETURN_NULL(); > } Looking at the docs, I'd think that should be: #include "postgres.h" #include "funcapi.h" PG_FUNCTION_INFO_V1(dc_ftx); Datum dc_ftx(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); } funcctx = SRF_PERCALL_SETUP(); SRF_RETURN_DONE(funcctx); } since I don't see a mention that creating the call context is optional, but I'm not a particular expert in the C interfact.
Kirill Krasnosselov <kirill@digicol.de> writes: > PG_FUNCTION_INFO_V1(dc_ftx); > Datum > dc_ftx(PG_FUNCTION_ARGS) > { ReturnSetInfo* rsi = (ReturnSetInfo *)fcinfo->resultinfo; > rsi->isDone = ExprEndResult; > PG_RETURN_NULL(); > } This looks like it should work, but you're living dangerously by not checking that you're being called the way you expect. You should have something like if (!fcinfo->resultinfo || !IsA(fcinfo->resultinfo,ReturnSetInfo)) elog(ERROR, ...); in there before trying to dereference the pointer. > In my opinion this function call shall returns a empty table, > but this call does not end. Try attaching to the backend with a debugger to see what it's doing. regards, tom lane
Tom Lane wrote: > This looks like it should work, but you're living dangerously > by not checking that you're being called the way you expect. > You should have something like > > if (!fcinfo->resultinfo || !IsA(fcinfo->resultinfo,ReturnSetInfo)) > elog(ERROR, ...); > > in there before trying to dereference the pointer. > >>In my opinion this function call shall returns a empty table, >>but this call does not end. > Works here on 7.3.4 (actually 7.3 stable branch after 7.3.4 was released): extern Datum dc_ftx(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(dc_ftx); Datum dc_ftx(PG_FUNCTION_ARGS) { ReturnSetInfo* rsi; if (!fcinfo->resultinfo || !IsA(fcinfo->resultinfo,ReturnSetInfo)) elog(ERROR, "called in unsupported context"); rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi->isDone = ExprEndResult; PG_RETURN_NULL(); } regression=# select version(); version -------------------------------------------------------------------- PostgreSQL 7.3.4 on i386-redhat-linux-gnu, compiled by GCC i386-redhat-linux-gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) (1 row) regression=# select dc_ftx(10); dc_ftx -------- (0 rows) What do you mean by "call does not end". Does it eventually crash? Joe