Yes, a function and procedure are transactional(atomic) in PostgreSQL. A function and procedure are run in a transaction so if there is error, the transaction is rollbacked.
For example, you create my_func() function which sets 5 to my.var then can cause division by zero error as shown below:
CREATE FUNCTION my_func(value INTEGER) RETURNS INTEGER AS $$
BEGIN
SET my.var = 5; -- Here
RETURN 1/value;
END;
$$ LANGUAGE plpgsql;
First, you set 2 to my.var, then call my_func(1) then 5 is set to my.var successfully as shown below:
postgres=# SET my.var = 2;
SET
postgres=# SELECT my_func(1);
my_func
---------
1
(1 row)
postgres=# SELECT current_setting('my.var');
current_setting
-----------------
5
(1 row)
Now, you set 2 to my.var, then call my_func(0) then division by zero error occurs, then my.var is still 2 as shown below because my_func() function is rollbacked:
postgres=# SET my.var = 2;
SET
postgres=# SELECT my_func(0);
ERROR: division by zero
...
postgres=# SELECT current_setting('my.var');
current_setting
-----------------
2
(1 row)
And for example, you create my_proc() procedure which sets 5 to my.var then can cause division by zero error as shown below:
CREATE PROCEDURE my_proc(INOUT value INTEGER) AS $$
BEGIN
SET my.var = 5; -- Here
SELECT 1/value INTO value;
END;
$$ LANGUAGE plpgsql;
First, you set 2 to my.var, then call my_proc(1) then 5 is set to my.var successfully as shown below:
postgres=# SET my.var = 2;
SET
postgres=# CALL my_proc(1);
my_func
---------
1
(1 row)
postgres=# SELECT current_setting('my.var');
current_setting
-----------------
5
(1 row)
Now, you set 2 to my.var, then call my_proc(0) then division by zero error occurs, then my.var is still 2 as shown below because my_proc() procedure is rollbacked:
postgres=# SET my.var = 2;
SET
postgres=# CALL my_proc(0);
ERROR: division by zero
...
postgres=# SELECT current_setting('my.var');
current_setting
-----------------
2
(1 row)
TRUNCATEhas, or used to have, some somewhat funky transactional behaviour. I don't remember the specifics; search the pgsql-general archives.LANGUAGE SQL.TRUNCATEignores all savepoints and just destroys your table data outright