Thread: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
PG Bug reporting form
Date:
The following bug has been logged on the website: Bug reference: 17696 Logged by: Roman Garcia Email address: yzerno@gmail.com PostgreSQL version: 13.2 Operating system: linux ubuntu Description: Executing the following simple script: BEGIN; CREATE table foo (id integer primary key); CREATE TABLE bar(id integer, foo_id integer); insert into foo (id) values (1); insert into bar(id,foo_id) values (1, 2); alter table bar add constraint foo_fkey foreign key (foo_id) references foo(id) deferrable initially deferred; results in a constraint violation error at the constraint creation line: " ERROR: insert or update on table "bar" violates foreign key constraint "foo_fkey" DETAIL: Key (foo_id)=(2) is not present in table "foo". " I would have expected to get this error message later, at transaction commit (if no foo with id 2 have been inserted before then) instead of getting it at constraint creation, since the point of having an deferrable initially deferred constraint is to move the constraint check when the transaction is commited. I found no indication of this behaviour in the documentation, only an example of the opposite case: if there exists an already defined deferrable initially deferred constraint, but we set it to immediate during transaction with SET CONSTRAINTS, then it is checked immediately, which should be expected.
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
"David G. Johnston"
Date:
On Thu, Nov 24, 2022 at 9:36 AM PG Bug reporting form <noreply@postgresql.org> wrote:
The following bug has been logged on the website:
Bug reference: 17696
Logged by: Roman Garcia
Email address: yzerno@gmail.com
PostgreSQL version: 13.2
Operating system: linux ubuntu
Description:
Executing the following simple script:
BEGIN;
CREATE table foo (id integer primary key);
CREATE TABLE bar(id integer, foo_id integer);
insert into foo (id) values (1);
insert into bar(id,foo_id) values (1, 2);
alter table bar add constraint foo_fkey foreign key (foo_id) references
foo(id) deferrable initially deferred;
results in a constraint violation error at the constraint creation line:
" ERROR: insert or update on table "bar" violates foreign key constraint
"foo_fkey" DETAIL: Key (foo_id)=(2) is not present in table "foo". "
I would have expected to get this error message later, at transaction commit
(if no foo with id 2 have been inserted before then) instead of getting it
at constraint creation, since the point of having an deferrable initially
deferred constraint is to move the constraint check when the transaction is
commited.
I found no indication of this behaviour in the documentation, only an
example of the opposite case: if there exists an already defined deferrable
initially deferred constraint, but we set it to immediate during transaction
with SET CONSTRAINTS, then it is checked immediately, which should be
expected.
Not sure about the documentation but when you add a constraint to a table (DDL) it is immediately validated. The deferrable behavior only applies when executing DML (insert/update/delete).
You cannot add that constraint to the table until you've ensured that all existing data already conforms to said constraint.
David J.
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Roman Garcia
Date:
Maybe I should have created this report as a possible evolution then ? As I understand it, the whole point of deferrable initially deferred is for it to be checked at transaction commit, not just for insert/update/delete, but as a general concept for the constraint.
Roman
Roman
Le jeu. 24 nov. 2022 à 17:51, David G. Johnston <david.g.johnston@gmail.com> a écrit :
On Thu, Nov 24, 2022 at 9:36 AM PG Bug reporting form <noreply@postgresql.org> wrote:The following bug has been logged on the website:
Bug reference: 17696
Logged by: Roman Garcia
Email address: yzerno@gmail.com
PostgreSQL version: 13.2
Operating system: linux ubuntu
Description:
Executing the following simple script:
BEGIN;
CREATE table foo (id integer primary key);
CREATE TABLE bar(id integer, foo_id integer);
insert into foo (id) values (1);
insert into bar(id,foo_id) values (1, 2);
alter table bar add constraint foo_fkey foreign key (foo_id) references
foo(id) deferrable initially deferred;
results in a constraint violation error at the constraint creation line:
" ERROR: insert or update on table "bar" violates foreign key constraint
"foo_fkey" DETAIL: Key (foo_id)=(2) is not present in table "foo". "
I would have expected to get this error message later, at transaction commit
(if no foo with id 2 have been inserted before then) instead of getting it
at constraint creation, since the point of having an deferrable initially
deferred constraint is to move the constraint check when the transaction is
commited.
I found no indication of this behaviour in the documentation, only an
example of the opposite case: if there exists an already defined deferrable
initially deferred constraint, but we set it to immediate during transaction
with SET CONSTRAINTS, then it is checked immediately, which should be
expected.Not sure about the documentation but when you add a constraint to a table (DDL) it is immediately validated. The deferrable behavior only applies when executing DML (insert/update/delete).You cannot add that constraint to the table until you've ensured that all existing data already conforms to said constraint.David J.
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
"David G. Johnston"
Date:
On Thu, Nov 24, 2022 at 10:12 AM Roman Garcia <yzerno@gmail.com> wrote:
Maybe I should have created this report as a possible evolution then ? As I understand it, the whole point of deferrable initially deferred is for it to be checked at transaction commit, not just for insert/update/delete, but as a general concept for the constraint.
I don't see any benefit for the effort making it work for DDL. How exactly were you expecting to benefit from having the constraint deferred during the transaction in which you created it?
But maybe you have a suggestion for the documentation to make this distinction more clear?
David J.
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Alvaro Herrera
Date:
On 2022-Nov-24, David G. Johnston wrote: > On Thu, Nov 24, 2022 at 10:12 AM Roman Garcia <yzerno@gmail.com> wrote: > > > Maybe I should have created this report as a possible evolution then ? As > > I understand it, the whole point of deferrable initially deferred is for it > > to be checked at transaction commit, not just for insert/update/delete, but > > as a general concept for the constraint. > > I don't see any benefit for the effort making it work for DDL. Yeah ... I agree that this scenario seems rather pointless, but I don't see any hard argument for making it not work, other than development effort. If Roman or somebody would like to submit a patch to implement it, I don't see why we wouldn't accept it (pending review process, ofc). -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "Crear es tan difícil como ser libre" (Elsa Triolet)
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Tom Lane
Date:
Alvaro Herrera <alvherre@alvh.no-ip.org> writes: > On 2022-Nov-24, David G. Johnston wrote: >> I don't see any benefit for the effort making it work for DDL. > Yeah ... I agree that this scenario seems rather pointless, but I don't > see any hard argument for making it not work, other than development > effort. There would need to be a side-eye on whether it breaks pg_dump scripts being run in single-transaction mode. Verifications of deferred fkey constraints would all be delayed till the final COMMIT, which at the very least is not what pg_dump is expecting. I think it'd pose a problem for parallel restores, in which restoration of such constraints could no longer be parallelized. I don't think we have any cases in which a subsequent view creation would actually fail, but I can believe that a subsequent matview-population query would run much more slowly than expected because the fkey relationship couldn't be used yet for plan optimization. On the whole I share David's guess that the cost/benefit ratio of making this happen is unattractive. I might feel impelled to do it anyway if somebody could show that the SQL spec requires it ... but I bet you'll search for that in vain, because I doubt that the SQL spec requires transactional DDL at all. (There are too many influential implementations that would have a problem with that.) regards, tom lane
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Vik Fearing
Date:
On 11/25/22 03:55, Tom Lane wrote: > On the whole I share David's guess that the cost/benefit ratio of > making this happen is unattractive. I might feel impelled to do > it anyway if somebody could show that the SQL spec requires it ... > but I bet you'll search for that in vain, because I doubt that the > SQL spec requires transactional DDL at all. (There are too many > influential implementations that would have a problem with that.) The spec does require transactional DDL (SQL:2016 4.41.1 General description of SQL-transactions) but does not allow mixing of DDL and DML in the same transaction. What happens when you do that is implementation-defined. So in this case it would not really matter when the new constraint is verified because the user would have no opportunity to fix the data anyway. -- Vik Fearing
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Jaime Casanova
Date:
On Thu, Nov 24, 2022 at 11:36 AM PG Bug reporting form <noreply@postgresql.org> wrote: > > The following bug has been logged on the website: > > Bug reference: 17696 > Logged by: Roman Garcia > Email address: yzerno@gmail.com > PostgreSQL version: 13.2 > Operating system: linux ubuntu > Description: > > Executing the following simple script: > > BEGIN; > CREATE table foo (id integer primary key); > CREATE TABLE bar(id integer, foo_id integer); > insert into foo (id) values (1); > insert into bar(id,foo_id) values (1, 2); > alter table bar add constraint foo_fkey foreign key (foo_id) references > foo(id) deferrable initially deferred; > > results in a constraint violation error at the constraint creation line: > " ERROR: insert or update on table "bar" violates foreign key constraint > "foo_fkey" DETAIL: Key (foo_id)=(2) is not present in table "foo". " > > I would have expected to get this error message later, at transaction commit > (if no foo with id 2 have been inserted before then) instead of getting it > at constraint creation, since the point of having an deferrable initially > deferred constraint is to move the constraint check when the transaction is > commited. > BTW, you can make this work as you expect if you mark the FK as NOT VALID: alter table bar add constraint foo_fkey foreign key (foo_id) references foo(id) deferrable initially deferred NOT VALID; -- Jaime Casanova Director de Servicios Profesionales SYSTEMGUARDS
Re: BUG #17696: Creation of deferrable initially deferred constraint breaks before transaction commit
From
Jaime Casanova
Date:
On Fri, Nov 25, 2022 at 7:44 PM Jaime Casanova <jcasanov@systemguards.com.ec> wrote: > > On Thu, Nov 24, 2022 at 11:36 AM PG Bug reporting form > <noreply@postgresql.org> wrote: > > > > The following bug has been logged on the website: > > > > Bug reference: 17696 > > Logged by: Roman Garcia > > Email address: yzerno@gmail.com > > PostgreSQL version: 13.2 > > Operating system: linux ubuntu > > Description: > > > > Executing the following simple script: > > > > BEGIN; > > CREATE table foo (id integer primary key); > > CREATE TABLE bar(id integer, foo_id integer); > > insert into foo (id) values (1); > > insert into bar(id,foo_id) values (1, 2); > > alter table bar add constraint foo_fkey foreign key (foo_id) references > > foo(id) deferrable initially deferred; > > > > results in a constraint violation error at the constraint creation line: > > " ERROR: insert or update on table "bar" violates foreign key constraint > > "foo_fkey" DETAIL: Key (foo_id)=(2) is not present in table "foo". " > > > > I would have expected to get this error message later, at transaction commit > > (if no foo with id 2 have been inserted before then) instead of getting it > > at constraint creation, since the point of having an deferrable initially > > deferred constraint is to move the constraint check when the transaction is > > commited. > > > > BTW, you can make this work as you expect if you mark the FK as NOT VALID: > > alter table bar add constraint foo_fkey foreign key (foo_id) references > foo(id) deferrable initially deferred NOT VALID; > well, not exactly as you wish because you need to VALIDATE the constraint but you can choose to do it just before the COMMIT --