Re: ON DELETE CASCADE with multiple paths

Lists: pgsql-bugs
From: Max Khon <mkhon(at)swsoft(dot)com>
To: pgsql-bugs(at)postgresql(dot)org
Subject: ON DELETE CASCADE with multiple paths
Date: 2007-05-17 12:55:44
Message-ID: 464C50D0.2010702@swsoft.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Hi!

Suppose the following schema:

create table foo(foo_id integer primary key);
create table bar(bar_id integer primary key, foo_id integer,
constraint bar_fk0 foreign key (foo_id) references foo(foo_id)
on delete cascade);
create table foobar(foobar_id serial primary key, foo_id integer, bar_id
integer);

alter table foobar add constraint foobar_fk1 foreign key (bar_id)
references bar(bar_id) on delete cascade;
alter table foobar add constraint foobar_fk0 foreign key (foo_id)
references bar(bar_id);

And data:

insert into foo(foo_id) values(1);
insert into bar(bar_id, foo_id) values(1, 1);
insert into foobar(foo_id, bar_id) values(1, 1);

The following statement does work:

delete from foo;

All is ok. The row in foobar is deleted because of ON DELETE CASCADE fk
constraints bar_fk0 and foobar_fk1.

After altering the schema:

alter table foobar drop constraint foobar_fk0;
alter table foobar drop constraint foobar_fk1;

alter table foobar add constraint foobar_fk0 foreign key (foo_id)
references bar(bar_id);
alter table foobar add constraint foobar_fk1 foreign key (bar_id)
references bar(bar_id) on delete cascade;

(note that constraints are now added in different order)

and the same data:

insert into foo(foo_id) values(1);
insert into bar(bar_id, foo_id) values(1, 1);
insert into foobar(foo_id, bar_id) values(1, 1);

"delete from foo" fails:

ERROR: update or delete on table "bar" violates foreign key constraint
"foobar_fk0" on table "foobar"
SQL state: 23503
Detail: Key (bar_id)=(1) is still referenced from table "foobar".
Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"

PostgreSQL version: any (I tested on 8.2.4 for Win32 and 8.1.3 for Linux)

--
Max Khon
PEM Platform Team Leader
SWsoft, Inc.
E-mail: mkhon(at)swsoft(dot)com
Web Site: http://swsoft.com/


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Max Khon <mkhon(at)swsoft(dot)com>
Cc: pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-17 14:50:15
Message-ID: 25725.1179413415@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Max Khon <mkhon(at)swsoft(dot)com> writes:
> "delete from foo" fails:

> ERROR: update or delete on table "bar" violates foreign key constraint
> "foobar_fk0" on table "foobar"
> SQL state: 23503
> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"

I see no bug here. There is no guarantee about the order in which
constraints are applied.

regards, tom lane


From: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Max Khon <mkhon(at)swsoft(dot)com>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-17 16:15:10
Message-ID: 20070517090941.X9014@megazone.bigpanda.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

On Thu, 17 May 2007, Tom Lane wrote:

> Max Khon <mkhon(at)swsoft(dot)com> writes:
> > "delete from foo" fails:
>
> > ERROR: update or delete on table "bar" violates foreign key constraint
> > "foobar_fk0" on table "foobar"
> > SQL state: 23503
> > Detail: Key (bar_id)=(1) is still referenced from table "foobar".
> > Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
>
> I see no bug here. There is no guarantee about the order in which
> constraints are applied.

Except that SQL92 at least does seem to say in 11.8 that "All rows that
are marked for deletion are effectively deleted at the end of the
SQL-statement, prior to the checking of any integrity constraints." I
think that likely makes our behavior wrong, but I'm not really sure how to
get there from what we have now.


From: Max Khon <mkhon(at)swsoft(dot)com>
To: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-18 08:39:18
Message-ID: 464D6636.3000809@swsoft.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Hi!

Stephan Szabo wrote:

>>> "delete from foo" fails:
>>> ERROR: update or delete on table "bar" violates foreign key constraint
>>> "foobar_fk0" on table "foobar"
>>> SQL state: 23503
>>> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
>>> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
>> I see no bug here. There is no guarantee about the order in which
>> constraints are applied.
>
> Except that SQL92 at least does seem to say in 11.8 that "All rows that
> are marked for deletion are effectively deleted at the end of the
> SQL-statement, prior to the checking of any integrity constraints." I
> think that likely makes our behavior wrong, but I'm not really sure how to
> get there from what we have now.

Just for the record: it works on Oracle 8i (and I assume it works on
later versions) and SQL Server 2005.

--
Max Khon
PEM Platform Team Leader
SWsoft, Inc.
E-mail: mkhon(at)swsoft(dot)com
Web Site: http://swsoft.com/


From: Max Khon <mkhon(at)swsoft(dot)com>
To: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-21 08:55:04
Message-ID: 46515E68.9040806@swsoft.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Stephan Szabo wrote:
> On Thu, 17 May 2007, Tom Lane wrote:
>
>> Max Khon <mkhon(at)swsoft(dot)com> writes:
>>> "delete from foo" fails:
>>> ERROR: update or delete on table "bar" violates foreign key constraint
>>> "foobar_fk0" on table "foobar"
>>> SQL state: 23503
>>> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
>>> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
>> I see no bug here. There is no guarantee about the order in which
>> constraints are applied.
>
> Except that SQL92 at least does seem to say in 11.8 that "All rows that
> are marked for deletion are effectively deleted at the end of the
> SQL-statement, prior to the checking of any integrity constraints." I
> think that likely makes our behavior wrong, but I'm not really sure how to
> get there from what we have now.

Is it sufficient to execute ON DELETE CASCADE and ON DELETE SET
NULL/DEFAULT triggers before other triggers?

Attached patch solves the problem for me.

--
Max Khon
PEM Platform Team Leader
SWsoft, Inc.
E-mail: mkhon(at)swsoft(dot)com
Web Site: http://swsoft.com/

Attachment Content-Type Size
patch-src-backend-commands-trigger.c text/plain 1.1 KB

From: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
To: Max Khon <mkhon(at)swsoft(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-21 15:52:56
Message-ID: 20070521084334.I64869@megazone.bigpanda.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

On Mon, 21 May 2007, Max Khon wrote:

> Stephan Szabo wrote:
> > On Thu, 17 May 2007, Tom Lane wrote:
> >
> >> Max Khon <mkhon(at)swsoft(dot)com> writes:
> >>> "delete from foo" fails:
> >>> ERROR: update or delete on table "bar" violates foreign key constraint
> >>> "foobar_fk0" on table "foobar"
> >>> SQL state: 23503
> >>> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
> >>> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
> >> I see no bug here. There is no guarantee about the order in which
> >> constraints are applied.
> >
> > Except that SQL92 at least does seem to say in 11.8 that "All rows that
> > are marked for deletion are effectively deleted at the end of the
> > SQL-statement, prior to the checking of any integrity constraints." I
> > think that likely makes our behavior wrong, but I'm not really sure how to
> > get there from what we have now.
>
> Is it sufficient to execute ON DELETE CASCADE and ON DELETE SET
> NULL/DEFAULT triggers before other triggers?

Hmm, I'm not sure. I'm not sure if that's sufficient and that it doesn't
add any holes, but we can check that. At least I think on set default
triggers we'd need to do something with the check performed from inside
the trigger.


From: Max Khon <mkhon(at)swsoft(dot)com>
To: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-22 08:29:50
Message-ID: 4652A9FE.5090804@swsoft.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

Stephan Szabo wrote:

>>>>> "delete from foo" fails:
>>>>> ERROR: update or delete on table "bar" violates foreign key constraint
>>>>> "foobar_fk0" on table "foobar"
>>>>> SQL state: 23503
>>>>> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
>>>>> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
>>>> I see no bug here. There is no guarantee about the order in which
>>>> constraints are applied.
>>> Except that SQL92 at least does seem to say in 11.8 that "All rows that
>>> are marked for deletion are effectively deleted at the end of the
>>> SQL-statement, prior to the checking of any integrity constraints." I
>>> think that likely makes our behavior wrong, but I'm not really sure how to
>>> get there from what we have now.
>> Is it sufficient to execute ON DELETE CASCADE and ON DELETE SET
>> NULL/DEFAULT triggers before other triggers?
>
> Hmm, I'm not sure. I'm not sure if that's sufficient and that it doesn't
> add any holes, but we can check that.

> At least I think on set default
> triggers we'd need to do something with the check performed from inside
> the trigger.

What's wrong with this check? Can you please elaborate?

btw does postgresql project have bugzilla or something like that? I
can't find it on http://postgresql.org/

--
Max Khon
PEM Platform Team Leader
SWsoft, Inc.
E-mail: mkhon(at)swsoft(dot)com
Web Site: http://swsoft.com/


From: Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com>
To: Max Khon <mkhon(at)swsoft(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: ON DELETE CASCADE with multiple paths
Date: 2007-05-22 14:25:52
Message-ID: 20070522071105.T22023@megazone.bigpanda.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-bugs

On Tue, 22 May 2007, Max Khon wrote:

> Stephan Szabo wrote:
>
> >>>>> "delete from foo" fails:
> >>>>> ERROR: update or delete on table "bar" violates foreign key constraint
> >>>>> "foobar_fk0" on table "foobar"
> >>>>> SQL state: 23503
> >>>>> Detail: Key (bar_id)=(1) is still referenced from table "foobar".
> >>>>> Context: SQL statement "DELETE FROM ONLY "public"."bar" WHERE "foo_id" = $1"
> >>>> I see no bug here. There is no guarantee about the order in which
> >>>> constraints are applied.
> >>> Except that SQL92 at least does seem to say in 11.8 that "All rows that
> >>> are marked for deletion are effectively deleted at the end of the
> >>> SQL-statement, prior to the checking of any integrity constraints." I
> >>> think that likely makes our behavior wrong, but I'm not really sure how to
> >>> get there from what we have now.
> >> Is it sufficient to execute ON DELETE CASCADE and ON DELETE SET
> >> NULL/DEFAULT triggers before other triggers?
> >
> > Hmm, I'm not sure. I'm not sure if that's sufficient and that it doesn't
> > add any holes, but we can check that.
>
> > At least I think on set default
> > triggers we'd need to do something with the check performed from inside
> > the trigger.
>
> What's wrong with this check? Can you please elaborate?

IIRC, at the end of those we call the function that performs the no action
check which does the basic constraint check to cover a hole where the row
might not actually change key values (which would elide the check caused
by the cascaded update that set default) but for which the referenced key
is gone. The problem is that given this report, we shouldn't check at the
end of the update cascade, but instead need to postpone that check until
any other referential actions have occured.

If we're forcing the referential actions to occur first, that might be
solvable by having on * set default actually have both the current set
default function and the no action function as separate triggers.

> btw does postgresql project have bugzilla or something like that? I
> can't find it on http://postgresql.org/

Not really, the -bugs list (and archive) is pretty much the current
archive.