BUG #16153: foreign key update should probably move dependent rows in the case of tuple rerouting

Started by PG Bug reporting formover 6 years ago3 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 16153
Logged by: Arne Roland
Email address: a.roland@index.de
PostgreSQL version: 12.1
Operating system: debian
Description:

--instead of simply deleting them silently
create table a (id serial, primary key (id)) partition by range (id);
create table b (id serial, primary key (id)) partition by range (id);
alter table b add constraint a_fk foreign key (id) references a (id) on
delete cascade;
create table a1 partition of a for values from (1) to (2);
create table a2 partition of a for values from (2) to (3);
create table b1 partition of b for values from (1) to (2);
create table b2 partition of b for values from (2) to (3);

insert into a (id) values (1);
insert into b (id) values (1);

update a set id=2;

select * from b;

Regards
Arne

#2Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: PG Bug reporting form (#1)
Re: BUG #16153: foreign key update should probably move dependent rows in the case of tuple rerouting

On 2019-Dec-05, PG Bug reporting form wrote:

foreign key update should probably move dependent rows in the case of
tuple rerouting
instead of simply deleting them silently

Hmm.

create table a (id serial, primary key (id)) partition by range (id);
create table b (id serial, primary key (id)) partition by range (id);
alter table b add constraint a_fk foreign key (id) references a (id) on
delete cascade;
create table a1 partition of a for values from (1) to (2);
create table a2 partition of a for values from (2) to (3);
create table b1 partition of b for values from (1) to (2);
create table b2 partition of b for values from (2) to (3);

insert into a (id) values (1);
insert into b (id) values (1);

update a set id=2;

select * from b;

This seems to be a side-effect of how tuple updates work across
partitions. My bet is that it's seen as just a deletion, which deletes
the referencing tuple because of the ON DELETE CASCADE; then the other
row is inserted and nothing else needs to happen.

You don't have ON UPDATE CASCADE in your example, so my expectation
would be that this should raise an error, per NO ACTION. But if you
were to add ON UPDATE CASCADE, then yeah the referencing row should be
moved too somehow.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#3Arne Roland
A.Roland@index.de
In reply to: Alvaro Herrera (#2)
Re: BUG #16153: foreign key update should probably move dependent rows in the case of tuple rerouting

Hello,

sorry, apparently I didn't sent my answer to the list.

This seems to be a side-effect of how tuple updates work across partitions. My bet is that it's seen as just a deletion, which deletes the referencing tuple because of the ON DELETE CASCADE; then the other row is inserted and nothing else needs to happen. You don't have ON UPDATE CASCADE in your example, so my expectation would be that this should raise an error, per NO ACTION. But if you were to add ON UPDATE CASCADE, then yeah the referencing row should be moved too somehow.

I completely agree. Without looking to deep not sure whether moving a dependent row is a new feature, or the easiest way to fix the bug. Silently deleting feels like a bug.

The way this logic works should be changed. This doesn't only affect the dependent tuples, but obviously triggers on the same table as well. I'm somehow surprised this didn't surface earlier.

Regards
Arne

________________________________
From: Alvaro Herrera <alvherre@2ndquadrant.com>
Sent: Thursday, December 12, 2019 1:52:29 PM
To: Arne Roland; pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #16153: foreign key update should probably move dependent rows in the case of tuple rerouting

On 2019-Dec-05, PG Bug reporting form wrote:

foreign key update should probably move dependent rows in the case of
tuple rerouting
instead of simply deleting them silently

Hmm.

create table a (id serial, primary key (id)) partition by range (id);
create table b (id serial, primary key (id)) partition by range (id);
alter table b add constraint a_fk foreign key (id) references a (id) on
delete cascade;
create table a1 partition of a for values from (1) to (2);
create table a2 partition of a for values from (2) to (3);
create table b1 partition of b for values from (1) to (2);
create table b2 partition of b for values from (2) to (3);

insert into a (id) values (1);
insert into b (id) values (1);

update a set id=2;

select * from b;

This seems to be a side-effect of how tuple updates work across
partitions. My bet is that it's seen as just a deletion, which deletes
the referencing tuple because of the ON DELETE CASCADE; then the other
row is inserted and nothing else needs to happen.

You don't have ON UPDATE CASCADE in your example, so my expectation
would be that this should raise an error, per NO ACTION. But if you
were to add ON UPDATE CASCADE, then yeah the referencing row should be
moved too somehow.

--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services