BUG #14149: when use LATERAL functions with IMMUTABLE called multiple times

Started by David Turoňalmost 10 years ago2 messagesbugs
Jump to latest
#1David Turoň
Turon.David@seznam.cz

The following bug has been logged on the website:

Bug reference: 14149
Logged by: David Turon
Email address: turon.david@seznam.cz
PostgreSQL version: 9.5.3
Operating system: CENTOS 6
Description:

Hello,

we found strange behavior LATERAL when we upgrade from 9.3.12 to 9.5.3,
simple example:

CREATE OR REPLACE FUNCTION f_imutable(OUT a int, out b int) AS $$
BEGIN
a := 1;
b := 2;
RAISE NOTICE 'call function f_imutable';
END;
$$ LANGUAGE plpgsql IMMUTABLE;

--execution on 9.3.12, for one row one call

SELECT (x.y).a, (x.y).b FROM generate_series(1,1), LATERAL (SELECT
f_imutable()) AS x(y);
NOTICE: call function f_imutable
a | b
---+---
1 | 2
(1 řádka)

--execution on 9.5.3 called 2x

SELECT (x.y).a, (x.y).b FROM generate_series(1,1), LATERAL (SELECT
f_imutable()) AS x(y);

NOTICE: call function f_imutable
NOTICE: call function f_imutable
a | b
---+---
1 | 2
(1 řádka)

I know, its little ugly written, but we don't except this behavior and after
upgrade we saw huge slowdown and we had to downgrade back to 9.3.12. For
VOLATILE fuctions works fine.

Thanks

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Turoň (#1)
Re: BUG #14149: when use LATERAL functions with IMMUTABLE called multiple times

turon.david@seznam.cz writes:

we found strange behavior LATERAL when we upgrade from 9.3.12 to 9.5.3,
simple example:

CREATE OR REPLACE FUNCTION f_imutable(OUT a int, out b int) AS $$
BEGIN
a := 1;
b := 2;
RAISE NOTICE 'call function f_imutable';
END;
$$ LANGUAGE plpgsql IMMUTABLE;

--execution on 9.3.12, for one row one call

SELECT (x.y).a, (x.y).b FROM generate_series(1,1), LATERAL (SELECT
f_imutable()) AS x(y);

--execution on 9.5.3 called 2x

I think you are confusing an implementation artifact of older versions
with a guaranteed behavior. Declaring a function IMMUTABLE (or STABLE)
says that it's okay if the generated plan calls the function more or fewer
times than naive analysis might suggest. 9.3 happened not to do so, for
this specific query, but 9.5 does.

Really the best fix for this is to mark a function VOLATILE if you can't
afford for the planner to rearrange the calls. In this particular case,
you might also consider rearranging the query so that the function is
called as a FROM item rather than a select-list item:

# SELECT x.a, x.b FROM generate_series(1,1), LATERAL f_imutable() as x;
NOTICE: call function f_imutable
a | b
---+---
1 | 2
(1 row)

but I wouldn't really want to promise that that won't ever change behavior
either. The argument for it is as much that it's a less messy notation
as anything else.

regards, tom lane

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs