Conceptually this is lazy:
As a CASE expression, COALESCE evaluates only the arguments needed to determine the result; that is, the arguments to the right of the first non-empty argument are not evaluated.
https://www.postgresql.org/docs/9.6/static/functions-conditional.html
However, if the expression on the right is not mutable, then it does not matter if it was lazy or not, therefore, for the query planner, it would be possible to correctly evaluate the right argument if it was stable or unchanged, if that seemed like a reasonable optimization.
The obvious case is that with SELECT COALESCE(a, b) FROM table
it is likely to extract the fields a
and b
all the rows, rather than extract a
, and then, if necessary, extract b
.
About the only way to have any observable effect here if you wrote a mutable function and intentionally incorrectly designated it as stable
or immutable
. Then this could be estimated if the right-hand side of a coalesce
, where the left-hand side was not zero. (It is possible that the function was really stable, but, of course, but if it was stable, it would not have a side effect, and if it had no side effect, whether it happened or not, it would not be observable).
Given:
CREATE OR REPLACE FUNCTION immutable_func(arg integer) RETURNS integer AS $BODY$ BEGIN RAISE NOTICE 'Immutable function called with %', arg; RETURN arg; END; $BODY$ LANGUAGE plpgsql IMMUTABLE; WITH data AS ( SELECT 10 AS num UNION ALL SELECT 5 UNION ALL SELECT 20 ) select coalesce(num, immutable_func(2)) from data
The scheduler knows that it will have the same result for immutable_func(2)
for each row and calls it the only time for the entire request, giving us the message Immutable function called with 2
. Therefore, it was indeed evaluated, even if it is not included in the rule "the arguments to the right of the first non-empty argument are not evaluated". The payback is that in the case of (reasonably expected) multiple null num
it will still work only once.
That this is against the letter of the documented behavior is fine because we said that such optimization is valid. If this causes a problem, the error will be that the function marked immutable
not in the expected evaluation.
It may also be partial. With SELECT COALESCE(a, Some_Func(b)) FROM table
he will not evaluate Some_Func(b)
impatiently, but he will be able to get b
to do this.
At any time when this actually affects the observed behavior (without cheating), the rule is respected.