Re: functions returning records - Mailing list pgsql-hackers

From mlw
Subject Re: functions returning records
Date
Msg-id 3B39C208.C5B8BBEF@mohawksoft.com
Whole thread Raw
In response to AW: AW: functions returning records  (Zeugswetter Andreas SB <ZeugswetterA@wien.spardat.at>)
Responses Re: Re: functions returning records
List pgsql-hackers
Zeugswetter Andreas SB wrote:
> 
> > >>  For the result from foo() you must somewhere define attributes (names).
> > >> Where? In CREATE FUNCTION statement? Possible must be:
> > >>
> > >>  select name1, name2 from foo() where name1 > 10;
> > >
> > > Yes, optimal would imho also be if the foo() somehow had access to the
> > > where restriction, so it could only produce output, that the
> > > higher level is interested in, very cool. This would be extremely
> > > useful for me. Very hard to implement, or even find an appropriate
> > > interface for though.
> >
> > You could easily implement it *in* the function foo IMHO. Since the
> > function does some black magic to create the result set to begin with, you
> > can change it to use parameters:
> >
> > select name1, name2 from foo(10, NULL, NULL) where name1 > 10;
> 
> Yes, but this is only an answer to a limited scope of the problem at hand,
> and the user who types the select (or uses a warehouse tool) needs substantial
> additional knowledge on how to efficiently construct such a query.
> 
> In my setup the function would be hidden by a view.

I have done a lot of playing around with this sort of thing to get my search
engine working.

While functions returning rows would be cool, and something I'd like to see. I
think the functionality, if not the syntax, you are looking for is already in
postgres 7.1.x. Here is an example: (Actual code at bottom of message)

select n1, n2 from (select foo1(10) as n1, foo2() as n2) as fubar ;

The trick seems to be, to have the first function return a 'setof' results.
Have the foo2() function return the next column of foo1()'s current result. 

Here is the output:

markw=# select foo1(10) as n1, foo2() as n2;n1 | n2
----+---- 1 |  1 2 |  2 3 |  3 4 |  4 5 |  5 6 |  6 7 |  7 8 |  8 9 |  910 | 10
(10 rows)

Or you can create a synthetic table at query time, called fubar:

markw=# select * from (select foo1(10) as n1, foo2() as n2) as fubar;n1 | n2
----+---- 1 |  1 2 |  2 3 |  3 4 |  4 5 |  5 6 |  6 7 |  7 8 |  8 9 |  910 | 10
(10 rows)


Now, I'm not sure if it is documented that the first function gets called
first, or that next functions get called after each result of a result "setof"
but it seem logical that they should, and I would like to lobby that this
becomes an "official" behavior of the function manager and the execution
processing.


<<<<<<<<<<<<< code >>>>>>>>>>>>>>


static int count;
static int curr;
Datum foo1(PG_FUNCTION_ARGS);
Datum foo2(PG_FUNCTION_ARGS);
Datum foo1(PG_FUNCTION_ARGS)
{       if(!fcinfo->resultinfo)       {               elog(ERROR, "Not called with fcinfo");
PG_RETURN_NULL();      }       if(!count)       {               count = PG_GETARG_INT32(0);               curr = 1;
 }       else               curr++;       if(curr <= count)       {               ReturnSetInfo *rsi = (ReturnSetInfo
*)fcinfo->resultinfo;              rsi->isDone = ExprMultipleResult;               PG_RETURN_INT32(curr);       }
else      {               ReturnSetInfo *rsi ;               curr=0;               count=0;               rsi =
(ReturnSetInfo*)fcinfo->resultinfo;               rsi->isDone = ExprEndResult ;       }       PG_RETURN_NULL();
 
}
Datum foo2(PG_FUNCTION_ARGS)
{       if(curr <= count)               PG_RETURN_INT32(curr);       else               PG_RETURN_INT32(42);
}

SQL:

create function  foo1( int4)       returns setof int4       as '/usr/local/lib/templ.so', 'foo1'       language 'c' ;
create function  foo2()       returns int4       as '/usr/local/lib/templ.so', 'foo2'       language 'c' ;


pgsql-hackers by date:

Previous
From: Alex Pilosov
Date:
Subject: Re: AW: AW: AW: functions returning records
Next
From: Zeugswetter Andreas SB
Date:
Subject: AW: functions returning records