PostgresBuild2021 is currently ongoing and as usual, I had questions after my talk I could not immediately answer. One of the best ways to learn, is to present a topic. There are for sure questions you never thought about. The topic of my talk was “An introduction to server side programming” and I wanted to give people easy examples about how to write procedures and functions in PostgreSQL. It was not about control structures like IF/THEN/ELSE/CASE/LOOP but more about the general concepts like parameters, returning values, using exceptions, or giving more information about your functions and procedures to the optimizer.
Question 1: Can I use setof with in parameters?
The example in the talk is this one:

This is a simple function returning a setof t2, that is, all the rows in the table t2 at once. Can we use setof as a in parameters as well? Let’s try:
postgres=# create table t ( a int, b text ); CREATE TABLE postgres=# create function f ( a setof t ) returns void as $$ select 1; $$ language sql; ERROR: functions cannot accept set arguments
The answer is: No.
Question 2: When I commit inside a loop, does that generate a new transaction ID with each commit?
The example in the talk is this one:

It doesn’t really matter if the commit is executed in a loop or like in the example above: Do we get a new transaction ID for each commit or not? Let’s try:
postgres=# create table t ( a xid );
CREATE TABLE
postgres=# create procedure p() as
$$
begin
insert into t values (pg_current_xact_id()::xid);
commit;
begin
insert into t values (pg_current_xact_id()::xid);
commit;
end;
end;
$$ language plpgsql;
CREATE PROCEDURE
postgres=# call p();
CALL
postgres=# select * from t;
a
-----
719
720
(2 rows)
The answer is: Yes. The same, of course, applies for loops:
postgres=# drop procedure p();
DROP PROCEDURE
postgres=# truncate t;
TRUNCATE TABLE
postgres=# create or replace procedure p() as
$$
begin
for i in 1..10
loop
insert into t values (pg_current_xact_id()::xid);
end loop;
end;
$$ language plpgsql;
CREATE PROCEDURE
postgres=# call p();
CALL
postgres=# select * from t;
a
-----
724
724
724
724
724
724
724
724
724
724
(10 rows)
postgres=# call p();
CALL
postgres=# select * from t;
a
-----
724
724
724
724
724
724
724
724
724
724
726
727
728
729
730
731
732
733
734
735
(20 rows)
postgres=# create or replace procedure p() as
$$
begin
for i in 1..10
loop
insert into t values (pg_current_xact_id()::xid);
commit;
end loop;
end;
$$ language plpgsql;
CREATE PROCEDURE
The answer, again is: Yes.
More to come as soon as I have the whole list of all the questions.