From: | "Sergey Konoplev" <gray(dot)ru(at)gmail(dot)com> |
---|---|
To: | pgsql-general(at)postgresql(dot)org |
Subject: | Referential integrity vulnerability in 8.3.3 |
Date: | 2008-07-15 11:42:17 |
Message-ID: | c3a7de1f0807150442oda619eao6d87fdbfbfdec12a@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Hello community
There is an oddity (or a bug) in situation with returning null before
delete trigger and referential integrity in PG 8.3.3. I tryed to find
a solution in Google and PG documentation and have noticed nothing
useful.
Let's start from tables creation.
CREATE TABLE table1
(
id serial NOT NULL,
field1 text,
CONSTRAINT table1_pk PRIMARY KEY (id)
);
CREATE TABLE table2
(
id serial NOT NULL,
table1_id integer,
CONSTRAINT table2_pk PRIMARY KEY (id),
CONSTRAINT table2_fk1 FOREIGN KEY (table1_id)
REFERENCES table1 (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
);
Well.. Second one refrences first one and has to be updated and
deleted cascaded. Next create before delete trigger on tabe2 allways
returning null.
CREATE OR REPLACE FUNCTION tr_stop()
RETURNS trigger AS
$BODY$begin
return null;
end;$BODY$
LANGUAGE 'plpgsql' VOLATILE;
CREATE TRIGGER tr_stop
BEFORE DELETE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE tr_stop();
Inserting three rows into table1
insert into table1 (id, field1) values (1, 'qqq');
insert into table1 (id, field1) values (2, 'www');
insert into table1 (id, field1) values (3, 'eee');
and refer to them from table2.
insert into table2 (id, table1_id) values (1, 1);
insert into table2 (id, table1_id) values (2, 2);
insert into table2 (id, table1_id) values (3, 3);
Now comming to a head. As I supposed earlier, deletion from table1 has
to be prevented by referential integrity when the trigger prevents
deletion of refered row from table2. But it doesn't.
delete from table1;
It deletes all rows from table1 and doesn't touch rows from table2.
select * from table1
id | field1
----+--------
(0 rows)
select * from table2 where not exists(select 1 from table1 where id =
table2.table1_id)
id | table1_id
----+-----------
1 | 1
2 | 2
3 | 3
(3 rows)
Will you explain me please why PG behave so cos IMHO it's a bit
illogical. Thanx.
p.s. Some info from pg_trigger below
select c.relname, t.* from pg_class c left join pg_trigger t on
t.tgrelid = c.oid
where relname in ('table1', 'table2') order by relname
relname | tgrelid | tgname | tgfoid |
tgtype | tgenabled | tgisconstraint | tgconstrname | tgconstrrelid |
tgconstraint | tgdeferrable | tginitdeferred | tgnargs | tgattr |
tgargs
---------+----------+-------------------------------+----------+--------+-----------+----------------+--------------+---------------+--------------+--------------+----------------+---------+--------+--------
table1 | 55880268 | RI_ConstraintTrigger_55880305 | 1646 |
9 | O | t | table2_fk1 | 55880296 |
55880302 | f | f | 0 | |
table1 | 55880268 | RI_ConstraintTrigger_55880306 | 1647 |
17 | O | t | table2_fk1 | 55880296 |
55880302 | f | f | 0 | |
table2 | 55880296 | tr_stop |
55881180 | 11 | O | f | |
0 | 0 | f | f | 0 |
|
table2 | 55880296 | RI_ConstraintTrigger_55880303 | 1644 |
5 | O | t | table2_fk1 | 55880268 |
55880302 | f | f | 0 | |
table2 | 55880296 | RI_ConstraintTrigger_55880304 | 1645 |
17 | O | t | table2_fk1 | 55880268 |
55880302 | f | f | 0 | |
(5 rows)
--
Regards,
Sergey Konoplev
From | Date | Subject | |
---|---|---|---|
Next Message | Richard Huxton | 2008-07-15 12:00:42 | Re: Referential integrity vulnerability in 8.3.3 |
Previous Message | Pavel Stehule | 2008-07-15 11:30:56 | Re: how to found a variable is in a aggregation or not? |