SRF in SFRM_ValuePerCall mode

Started by dv @ nabbleover 17 years ago6 messages
#1dv @ nabble
dvnabble@gmail.com
1 attachment(s)

Hi all,

I am working on implementation of custom "C" SRF for our team. The SRF uses
SFRM_ValuePerCall mode. I know that sometimes even in SFRM_ValuePerCall mode
all the rows returned from SRF are "materialized" (for performing JOINs, for
example). But it looks like even in cases when SELECT is very simple and
it's obvious that no more rows will be read from the SRF, SRF is being
iterated till it returns SRF_RETURN_DONE(...). So, in case when the SRF
returns 1000 rows but the SELECT is querying only the first one (with LIMIT
1), all 1000 iterations will be performed and 999 rows will be created,
allocated, returned and thrown away.

Is there a way to avoid unnecessary calls of SRF in this case? Is it a
"feature"?

In the attachment you can find the simplest example of SRF function working
in SFRM_ValuePerCall mode.
I have created it while researching the issue. After building it, use the
following SQLs:

-- this creates the test function
CREATE OR REPLACE FUNCTION vpc() RETURNS setof record
AS 'plbsh.dll', 'vpc' LANGUAGE 'C';

-- this returns 10 rows
SELECT * FROM vpc() AS T(a INT, b TEXT);

-- this returns 1 row, but performs 10 calls
SELECT * FROM vpc() AS T(a INT, b TEXT) LIMIT 1;

Regards,
Denis

Attachments:

vpc.c.txttext/plain; format=flowed; name=vpc.c.txt; reply-type=originalDownload
#2Heikki Linnakangas
heikki@enterprisedb.com
In reply to: dv @ nabble (#1)
Re: SRF in SFRM_ValuePerCall mode

dv @ nabble wrote:

I am working on implementation of custom "C" SRF for our team. The SRF uses
SFRM_ValuePerCall mode. I know that sometimes even in SFRM_ValuePerCall
mode
all the rows returned from SRF are "materialized" (for performing JOINs,
for
example).

Yep, they are unfortunately always materialized. Back when set returning
functions were implemented, the original patch did actually support true
"value per call" mode, where the whole result set was not materialized.
However, it was dropped because of some issues I can't remember off the
top of my head. The value-per-call API was committed, so that it was
already in place when someone gets around to implement the backend
support for it.

However, no-one has bothered to do that to this date. Hannu Krosing
showed some interest in it recently, though:
http://archives.postgresql.org/pgsql-hackers/2008-04/msg00345.php. I
would love to see it happen.

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Heikki Linnakangas (#2)
Re: SRF in SFRM_ValuePerCall mode

"Heikki Linnakangas" <heikki@enterprisedb.com> writes:

dv @ nabble wrote:

I am working on implementation of custom "C" SRF for our team. The SRF uses
SFRM_ValuePerCall mode. I know that sometimes even in SFRM_ValuePerCall
mode
all the rows returned from SRF are "materialized" (for performing JOINs,
for
example).

Yep, they are unfortunately always materialized. Back when set returning
functions were implemented, the original patch did actually support true
"value per call" mode, where the whole result set was not materialized.
However, it was dropped because of some issues I can't remember off the
top of my head. The value-per-call API was committed, so that it was
already in place when someone gets around to implement the backend
support for it.

That's a rather revisionist view of history ;-) Value-per-call mode has
always been there, just not in nodeFunctionscan.c.

If you're not joining to the function result, and you don't need the
ability to determine its result type on the fly, you could declare it
as returning a specific rowtype and then call it in the targetlist:

select vpc();

regards, tom lane

#4dv @ nabble
dvnabble@gmail.com
In reply to: Heikki Linnakangas (#2)
Re: SRF in SFRM_ValuePerCall mode

OK,

Thank you for the explanation, I hope this will be implemented in future.
We will try and find a workaround to this issue until then.

Denis

----- Original Message -----
From: "Heikki Linnakangas" <heikki@enterprisedb.com>
To: "dv @ nabble" <dvnabble@gmail.com>
Cc: "pgsql-hackers list" <pgsql-hackers@postgresql.org>
Sent: Monday, April 28, 2008 1:56 PM
Subject: Re: [HACKERS] SRF in SFRM_ValuePerCall mode

Show quoted text

dv @ nabble wrote:

I am working on implementation of custom "C" SRF for our team. The SRF
uses
SFRM_ValuePerCall mode. I know that sometimes even in SFRM_ValuePerCall
mode
all the rows returned from SRF are "materialized" (for performing JOINs,
for
example).

Yep, they are unfortunately always materialized. Back when set returning
functions were implemented, the original patch did actually support true
"value per call" mode, where the whole result set was not materialized.
However, it was dropped because of some issues I can't remember off the
top of my head. The value-per-call API was committed, so that it was
already in place when someone gets around to implement the backend support
for it.

However, no-one has bothered to do that to this date. Hannu Krosing showed
some interest in it recently, though:
http://archives.postgresql.org/pgsql-hackers/2008-04/msg00345.php. I would
love to see it happen.

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com

#5dv @ nabble
dvnabble@gmail.com
In reply to: Tom Lane (#3)
Re: SRF in SFRM_ValuePerCall mode

----- Original Message -----
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: "Heikki Linnakangas" <heikki@enterprisedb.com>
Cc: "dv @ nabble" <dvnabble@gmail.com>; "pgsql-hackers list"
<pgsql-hackers@postgresql.org>
Sent: Monday, April 28, 2008 5:07 PM
Subject: Re: [HACKERS] SRF in SFRM_ValuePerCall mode

"Heikki Linnakangas" <heikki@enterprisedb.com> writes:

dv @ nabble wrote:

I am working on implementation of custom "C" SRF for our team. The SRF
uses
SFRM_ValuePerCall mode. I know that sometimes even in SFRM_ValuePerCall
mode
all the rows returned from SRF are "materialized" (for performing JOINs,
for
example).

Yep, they are unfortunately always materialized. Back when set returning
functions were implemented, the original patch did actually support true
"value per call" mode, where the whole result set was not materialized.
However, it was dropped because of some issues I can't remember off the
top of my head. The value-per-call API was committed, so that it was
already in place when someone gets around to implement the backend
support for it.

That's a rather revisionist view of history ;-) Value-per-call mode has
always been there, just not in nodeFunctionscan.c.

If you're not joining to the function result, and you don't need the
ability to determine its result type on the fly, you could declare it
as returning a specific rowtype and then call it in the targetlist:

select vpc();

You mean make the function return the only row?
This is not the functionality we need. What we want is to create a SETOF
function that will
emulate a table and query this "table" with WHERE filter and LIMIT clauses
to limit the row
count we want to return. We might pass the filter and the limit to the
function, but we want to
implement it in more natural way.

Thanks,
Denis

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: dv @ nabble (#5)
Re: SRF in SFRM_ValuePerCall mode

"dv @ nabble" <dvnabble@gmail.com> writes:

From: "Tom Lane" <tgl@sss.pgh.pa.us>

If you're not joining to the function result, and you don't need the
ability to determine its result type on the fly, you could declare it
as returning a specific rowtype and then call it in the targetlist:

select vpc();

You mean make the function return the only row?

No, I'm pointing out that ValuePerCall SRFs can be called from the
targetlist.

regards, tom lane