Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Heikki Linnakangas <heikki(at)enterprisedb(dot)com>, Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
Cc: pgsql-bugs(at)postgresql(dot)org, pgsql-patches(at)postgresql(dot)org
Subject: Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table
Date: 2007-08-14 19:07:20
Message-ID: 10277.1187118440@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs pgsql-patches

I wrote:
> Heikki Linnakangas <heikki(at)enterprisedb(dot)com> writes:
>> I'm not sure what to do about this. We could change the order the
>> triggers are fired to breadth-first. If all the setnull triggers were
>> executed first, there would be no problem. But that seems like a pretty
>> big change, and I'm afraid it might have other unintended consequences.

> I think it's not so much that they should be "breadth first" as that the
> updates generated by the triggers shouldn't count as their own
> sub-statements. The trigger events generated by those updates need to
> go at the end of the outer statement's trigger queue.

Actually, Heikki's description is isomorphic to mine ...

I coded this up (patch attached, sans regression test additions) and
it seems to work: Pavel's and Heikki's test cases do what is expected.
The regression tests pass modulo this diff:

*** ./expected/foreign_key.out Tue Jul 17 13:45:28 2007
--- ./results/foreign_key.out Tue Aug 14 14:39:38 2007
***************
*** 646,652 ****
UPDATE PKTABLE set ptest2=5 where ptest2=2;
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
DETAIL: Key (ftest1,ftest2,ftest3)=(1,-1,3) is not present in table "pktable".
- CONTEXT: SQL statement "UPDATE ONLY "public"."fktable" SET "ftest2" = DEFAULT WHERE $1 OPERATOR(pg_catalog.=) "ftest1" AND $2 OPERATOR(pg_catalog.=) "ftest2" AND $3 OPERATOR(pg_catalog.=) "ftest3""
-- Try to update something that will set default
UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2;
UPDATE PKTABLE set ptest2=10 where ptest2=4;
--- 646,651 ----

which is happening because the error is no longer detected while we are
inside the first RI trigger's UPDATE command, but only while handling
triggers queued for the outer query. This is a little bit annoying IMHO
because the connection of the error message to the original query isn't
very obvious, and seeing the RI update query might help make it a bit
clearer. OTOH the RI update query is ugly enough that I'm not sure the
average user would be helped by the CONTEXT line. In any case it seems
difficult to avoid this change.

Another problem is that, because the indirectly-fired RI triggers are
ultimately run in a context where their target table is not the direct
target of the current query, trigger.c doesn't have any rangetable entry
to connect them to (this is why the patch has to touch trigger.c, as it
formerly considered that an error case). This has a performance cost
(extra heap_opens) that is probably usually negligible, but maybe not
always. Also, as the patch stands EXPLAIN ANALYZE would fail to report
the runtime of such triggers separately --- they'd be included in the
bottom-line total runtime but not listed by themselves. (In current
code they aren't listed separately either ... but they'd be charged to
the parent trigger that caused them to be fired, which is better than
nothing.)

I am tempted to try to fix these last two problems by having
afterTriggerInvokeEvents() dynamically add tables to the executor's
range table when it's told to fire triggers for tables that aren't
already listed there. That's getting a bit hairy for a back-patchable
fix though. I'm thinking of trying that in HEAD but applying this
patch as-is to 8.0 through 8.2. (Note that 7.x doesn't exhibit the
bug, mainly because it never tried to fire any triggers earlier than
end-of-interactive-command.)

Comments?

regards, tom lane

Attachment Content-Type Size
unknown_filename text/plain 13.3 KB

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2007-08-14 19:12:55 Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table
Previous Message Heikki Linnakangas 2007-08-14 18:55:38 Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table

Browse pgsql-patches by date

  From Date Subject
Next Message Tom Lane 2007-08-14 19:12:55 Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table
Previous Message Heikki Linnakangas 2007-08-14 18:55:38 Re: ON DELETE SET NULL clauses do error when more than two columns are referenced to one table