This explains the issue quite clearly to me, but I'm still a bit in the dark as to what scenarios I should have in mind when I think of statement side-effects in postgres. Does "side-effects" mean that a statement writes to tables or files? Or what other scenarios should I have in mind? I'm wary of making a similar mistake in future.
In this regard, would it make sense to try and warn users of some possible mistakes in function definitions? I'm aware of discussions such as https://postgrespro.com/list/thread-id/1752462 and I'm not proposing that, but perhaps issuing a warning at compile time if there's an INSERT or RAISE in a non-volatile function. Or would adding some more examples to the docs (https://www.postgresql.org/docs/current/xfunc-volatility.html) suffice?
Joel Mukuthu <jom@upright.co> writes: > CREATE FUNCTION raise_exception_immutable(IN err_message text) > RETURNS void > LANGUAGE 'plpgsql' > IMMUTABLE > AS $BODY$ > BEGIN > RAISE EXCEPTION > USING MESSAGE = err_message; > END; > $BODY$;
A function with side-effects (like raising an error) isn't really immutable [1]. We do fudge that a bit, since hardly anything could be marked immutable if there were a strict rule about it --- but when the primary point of the function is to cause that side-effect, you can't fudge it.
> 4. This raises an exception that was surprising to me:
> SELECT raise_exception_immutable('foo') WHERE false; > -- ERROR: foo > -- CONTEXT: PL/pgSQL function raise_exception_immutable(text) line 3 at > RAISE
The allegedly-immutable function is evaluated during constant folding.
> 5. This does not raises an exception, that was also surprising to me:
> SELECT raise_exception_immutable(format('foo')) WHERE false;
format() isn't immutable, only stable; so constant-folding can't reach the error.