Function is called multiple times in subselect

From: Chris Campbell <chris(at)bignerdranch(dot)com>
To: PostgreSQL Bugs List <pgsql-bugs(at)postgresql(dot)org>, Don Marco <mark(at)bignerdranch(dot)com>, Aaron Hillegass <aaron(at)bignerdranch(dot)com>
Subject: Function is called multiple times in subselect
Date: 2004-03-12 01:29:10
Message-ID: 40511266.7050009@bignerdranch.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

pgsql-bugs:

I wrote a plpgsql function that does a fairly expensive calculation on
its input, and want to peform a query that:

1. Selects certain rows from a table, then
2. Calls my function on the selected rows

So I wrote a query and used a subselect to first select the rows, and
then used the outer select to call my function on each of the selected
rows and return the result.

I referenced the result of my inner select's calculation multiple times
in the outer select, and found that my function is called once for *each
reference* to its result in the outer select, rather than once for each
row of the inner select.

Here's a simple example:

CREATE FUNCTION square_it(INTEGER) RETURNS INTEGER AS '
DECLARE
i ALIAS FOR $1;
BEGIN
RAISE NOTICE ''square_it(%)'', i;
RETURN (i * i);
END;
' LANGUAGE 'plpgsql';

CREATE TABLE foo (i INTEGER);

INSERT INTO foo (i) VALUES (1);
INSERT INTO foo (i) VALUES (2);
INSERT INTO foo (i) VALUES (3);
INSERT INTO foo (i) VALUES (4);

SELECT query.i,
query.squared AS test1,
query.squared + 1 AS test2,
query.squared + 2 AS test3,
query.squared + 3 AS test4
FROM (
SELECT i,
square_it(i) AS squared
FROM foo
) query;

When I run it, I expect to see 4 lines of output, and I expect that
square_it() will have been called 4 times (once for each row). However,
it is actually called *4 times for each row* because I reference
"query.squared" 4 times in the outer select.

NOTICE: square_it(1)
NOTICE: square_it(1)
NOTICE: square_it(1)
NOTICE: square_it(1)
NOTICE: square_it(2)
NOTICE: square_it(2)
NOTICE: square_it(2)
NOTICE: square_it(2)
NOTICE: square_it(3)
NOTICE: square_it(3)
NOTICE: square_it(3)
NOTICE: square_it(3)
NOTICE: square_it(4)
NOTICE: square_it(4)
NOTICE: square_it(4)
NOTICE: square_it(4)
i | test1 | test2 | test3 | test4
---+-------+-------+-------+-------
1 | 1 | 2 | 3 | 4
2 | 4 | 5 | 6 | 7
3 | 9 | 10 | 11 | 12
4 | 16 | 17 | 18 | 19
(4 rows)

I don't think this should be happening (PostgreSQL 7.4.1). I think it
should be saving the result of the calculation in the resulting rows
from the innery query. In my case, that means my query takes 4 times
longer than it should. And when it's a query that takes a nontrivial
amount of time to execute, that's harsh. Any ideas?

Here's the query plan:

QUERY PLAN

-------------------------------------------------------------------------------------------------
Seq Scan on foo (cost=0.00..37.50 rows=1000 width=4) (actual
time=3.203..4.384 rows=4 loops=1)
Total runtime: 4.742 ms

Thanks!

- Chris

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2004-03-12 04:02:21 Re: Function is called multiple times in subselect
Previous Message Tom Lane 2004-03-11 23:41:06 Re: BUG #1096: pg_restore cannot restore large objects with other oid columns