CTE is not even required. a simple subquery does the job (tested with pg 9.3):
SELECT i, (f).* -- decompose here FROM ( SELECT i, (slow_func(i)) AS f -- do not decompose here FROM generate_series(1, 3) i ) sub;
Be sure not to decompose the composite result of the function in the subquery. Reserve this for an external request .
Of course, a well-known type is required. Doesn't work with anonymous posts.
Or what @Richard wrote , LATERAL JOIN works. The syntax could be simpler:
SELECT * FROM generate_series(1, 3) i, slow_func(i) f
LATERAL is used implicitly in Postgres 9.3 or later.- A function can stand by itself in a
FROM ; it does not have to be completed in an additional subselect. Imagine a table in place.
SQL Fiddle with EXPLAIN VERBOSE output for all options. You can see multiple evaluations of the function if this happens.
COST setting
As a rule (itβs not important for this particular request), make sure that you apply the high cost setting to your function, so the planner knows to avoid a more frequent assessment than necessary. How:
CREATE OR REPLACE FUNCTION slow_function(int) RETURNS result_t AS $func$
In the documentation:
Larger values ββcause the planner to try to avoid evaluating the function more often than necessary.
source share