Re: Using SETOF in plpgsql function

From: Jan Wieck <janwieck(at)Yahoo(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Jan Wieck <janwieck(at)Yahoo(dot)com>, hlefebvre <hlefebvre(at)lexbase(dot)net>, pgsql-sql(at)postgresql(dot)org
Subject: Re: Using SETOF in plpgsql function
Date: 2000-08-23 16:53:06
Message-ID: 200008231653.LAA00335@jupiter.greatbridge.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

Tom Lane wrote:
> Jan Wieck <janwieck(at)Yahoo(dot)com> writes:
> > hlefebvre wrote:
> >> I'd like to return a set of integer in an pl/pgsql function. How can I
> >> do that ?
>
> > You can't. Not with PL/pgSQL nor with any other PL or C. The
> > problem is nested deeper and requires the planned querytree
> > redesign to get solved.
>
> Not really. Coincidentally enough, I am just in the middle of removing
> execQual.c's hard-wired assumption that only SQL-language functions
> can return sets. (This is a side effect of fixing the function manager
> so that SQL functions can be called in all contexts, eg used as index
> functions.) If you want to fix plpgsql so that it retains state and
> can produce multiple elements of a set over repeated calls, the same
> way that SQL functions do, then it could be done today.

Not that easy. PL/pgSQL isn't a state machine. The
precompiled code is kind of a nested tree of statements. A
RETURN causes a controlled return() through all nested levels
of the PL executors C calls. This might close SPI calls in
execution as well. Imagine a code construct like

FOR rec IN SELECT * FROM customer LOOP
RETURN rec.cust_id AND RESUME;
END LOOP;

which would be the correct syntax for returning sets. What
happens in PL/pgSQL while execution is, that at the beginning
of the loop the SPI query for SELECT is performed, and then
the loop executed for all rows in the SPI result set. And of
course, you can have nested loops, why not.

Now you want to return the first value. If you really return
to the fmgr at this time, the connection to the SPI manager
must be closed, loosing the result set. So how to continue
later?

If we want to make it now for sets of scalar values (not
tuple sets), we could add another feature to the fmgr and the
PL handlers, which we need later anyway.

In the case of a call to a PL or C function returning a set,
the fmgr creates a temp table and calls the function which
fills the temp table with all the return values. Now fmgr
changes the execution trees func node in a way that it is
operating like an SQL function - holding a seqscan over the
temp table. After the last result is returned, the temp table
is removed. This'd work for tuple sets as well (so the temp
table then is our tuple-source).

Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================== JanWieck(at)Yahoo(dot)com #

In response to

Browse pgsql-sql by date

  From Date Subject
Next Message drfrog 2000-08-23 16:53:56 db benchmarks
Previous Message Jie Liang 2000-08-23 16:46:59 Re: Create table in functions