IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value.
I have read the documentation about Immutable functions in Postgres but still confused about the following examples as to classify them as Immutable or not! All three are different cases and are as follows:
- Function having
raise notice
inside them
CREATE OR REPLACE FUNCTION text_equals(text, text)
RETURNS boolean AS $$
BEGIN
RAISE NOTICE 'Comparing two texts';
RETURN $1 = $2;
END;
$$ LANGUAGE plpgsql;
- Function calling another Immutable function.
- Function returning
current_user
inside it
CREATE OR REPLACE FUNCTION fun()
RETURNS TEXT AS $$
DECLARE
current_user_text TEXT;
BEGIN
current_user_text := 'Current user is ' || current_user;
RETURN current_user_text;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
Third point above, I guess can’t be an immutable function but just wanted to check when function is a security definer which user gets printed out
2
Answers
No, Your function is not immutable.
This has nothing to do with current user or security definer etc. It has everything to do with returning an indeterminant value. If the returned value can be calculated given only the input parameters, the function is immutable.
In this regard, the question would likely have been clearer, and basically asked the same question, if instead the function returned
current_timestamp
.Functions that raise notices based on anything other than the parameters should not marked immutable, because:
so the same result will not be produced.
Yes, yes, no, (but there’s a trick*):
raise
all you want. Function volatility is about warranting results based on inputs.current_user
produces results that in no way depend on its arguments. The doc puts it shortly:*The trick is that to an extent, it’s all up to you. You can declare something as
immutable
even though it’s clearly not. Thing is, PostgreSQL double-checks before things like function inlining and will disregard your declaration of immutability if it catches you lying.You’ll also get very unexpected results if it runs with your lie for optimisation purposes and swaps out your function call for a constant that it got from it earlier – if the result was supposed to change based on some circumstances, it suddenly won’t.
You can test these claims: demo at db<>fiddle
Here, the function got folded to a constant. PostgreSQL doesn’t really care whether it was really immutable or not, it just got one value from it, trusted your declaration that the result isn’t supposed to change if it gives the same argument over and over, so it just kept returning that first result, instead of calling it multiple times:
Here there was some level of verification, because f3 is a sql function declared as
immutable
: it checked whether it calls non-immutables, then inlined it. Again, f2 is plgpsql so it’s trusted to be immutable (and it’s not inlineable), f1 and f3 are also verified for inlining:With the current user thing, you keep giving the same arguments and getting different results: