Thread: Foreign key constaint can be broken

Foreign key constaint can be broken

From
Mark Kazemier
Date:
Dear,

I found a way to break a foreign key constraint in PostgreSQL. I discussed
this bug on a dutch discussion board and multiple people tried this on
multiple versions.

When I create the following tables:


CREATE TABLE a
(
id SERIAL NOT NULL,
foo CHAR(100) NOT NULL,
PRIMARY KEY(id)
);

CREATE TABLE b
(
id INT NOT NULL,
bar CHAR(20) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY(id) REFERENCES a(id) ON DELETE CASCADE
);

and add the following rule to table b:

CREATE OR REPLACE RULE delete_b AS ON DELETE
TO b
DO INSTEAD
DELETE FROM a WHERE OLD.id = id;

When you try to delete a row on table b:
DELETE FROM b WHERE id = 1;
The record from table a disappears, but the record in table b is still
there. Of course this is a very stupid construction, but I would expect some
kind of error / warning message instead. Now it is possible to corrupt your
data.

Best regards,
Mark Kazemier

Re: Foreign key constaint can be broken

From
Tom Lane
Date:
Mark Kazemier <mark.kazemier@gmail.com> writes:
> I found a way to break a foreign key constraint in PostgreSQL
> [ ie, make a rule that defeats an ON DELETE CASCADE operation ]

This isn't a bug, it's just the way things work.  Rules (and triggers)
apply to the commands that implement foreign key updates, so a poorly
written rule can make those queries do the wrong thing.  The rule can
make your regular queries do the wrong thing too, so it's not like you'd
be fine if it were done some other way.  There are a number of real
applications that would be broken if rules/triggers *didn't* apply to
FK queries --- for example, using a trigger to implement logging --- so
we've concluded this is the most useful way for it to be done.

            regards, tom lane

Re: Foreign key constaint can be broken

From
Fabien COELHO
Date:
>> I found a way to break a foreign key constraint in PostgreSQL
>> [ ie, make a rule that defeats an ON DELETE CASCADE operation ]
>
> This isn't a bug, it's just the way things work.  Rules (and triggers)
> apply to the commands that implement foreign key updates, so a poorly
> written rule can make those queries do the wrong thing.  The rule can
> make your regular queries do the wrong thing too, so it's not like you'd
> be fine if it were done some other way.  There are a number of real
> applications that would be broken if rules/triggers *didn't* apply to
> FK queries --- for example, using a trigger to implement logging --- so
> we've concluded this is the most useful way for it to be done.

It may suggest that a rule may have a optionnal specifier to tell the
context in which it should be applied, for instance :

   CREATE RULE ... ON [ ALL | INTERNAL | EXTERNAL ] UPDATE TO ...

Where "INTERNAL" would tag foreign key stuff while "EXTERNAL" would be
only the user stuff.

I'm not sure it would not add to the confusion, though.

--
Fabien.