I'm currently confused on the exact timing of IMMEDIATE constraint checks. Hopefully, the following example captures my confusion:
create table a (
id int primary key
);
create table b (
id int primary key,
a_id int not null references a
);
/* violates foreign key constraint "b_a_id_fkey" */
with t1 as (insert into b values (100, 200) returning id, a_id)
select * from t1;
/* ERROR: expensive_exception_thrower */
with t1 as (insert into b values (100, 200) returning id, a_id)
select * from t1 where expensive_exception_thrower(t1.a_id) = true;
In the second query, despite referencing t1, expensive_exception_thrower
will throw its exception first, which result in the fkey exception being swallowed. Of course, there are workarounds, but I'd like to understand the exact definition of "statement" when the Postgres manual says IMMEDIATE constraints are checked immediately after each statement. The manual uses the term "statement" in a way that would indicate that the with clause is a statement, or at least "sub-statement."
This is PG version 14.3.
;
. `A CTE is not a statement. Foreign key constraints that are IMMEDIATE are checked after each statement. The difference with DEFERRED constraints is that those are checked at the end of the transaction.