Thread: c-function returns multiple rows

c-function returns multiple rows

From
Kirill Krasnosselov
Date:
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




Re: c-function returns multiple rows

From
Stephan Szabo
Date:
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.



Re: c-function returns multiple rows

From
Tom Lane
Date:
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

Re: c-function returns multiple rows

From
Joe Conway
Date:
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