Re: BEFORE trigger can cause undetected partition constraint violation

From: Amit Langote <Langote_Amit_f8(at)lab(dot)ntt(dot)co(dot)jp>
To: Robert Haas <robertmhaas(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Amit Langote <amitlangote09(at)gmail(dot)com>, "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: BEFORE trigger can cause undetected partition constraint violation
Date: 2017-06-02 04:51:35
Message-ID: aedbdf23-67cc-683d-90e7-cff5f4e709c4@lab.ntt.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 2017/06/02 10:36, Robert Haas wrote:
> On Thu, Jun 1, 2017 at 6:05 PM, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:
>> Without having checked the code, I imagine the reason for this is
>> that BEFORE triggers are fired after tuple routing occurs.
>
> Yep.
>
>> Re-ordering that seems problematic, because what if you have different
>> triggers on different partitions? We'd have to forbid that, probably
>> by saying that only the parent table's BEFORE ROW triggers are fired,
>> but that seems not very nice.
>
> The parent hasn't got any triggers; that's forbidden.
>
>> The alternative is to forbid BEFORE triggers on partitions to alter
>> the routing result, probably by rechecking the partition constraint
>> after trigger firing.
>
> That's what we need to do. Until we do tuple routing, we don't know
> which partition we're addressing, so we don't know which triggers
> we're firing. So the only way to prevent this is to recheck. Which I
> think is supposed to work already, but apparently doesn't.

That has to do with the assumption written down in the following portion
of a comment in InitResultRelInfo():

/*
* If partition_root has been specified, that means we are building the
* ResultRelInfo for one of its leaf partitions. In that case, we need
* *not* initialize the leaf partition's constraint, but rather the
* partition_root's (if any).

which, as it turns out, is wrong. It completely disregards the fact that
BR triggers are executed after tuple-routing and can change the row.

Attached patch makes InitResultRelInfo() *always* initialize the
partition's constraint, that is, regardless of whether insert/copy is
through the parent or directly on the partition. I'm wondering if
ExecInsert() and CopyFrom() should check if it actually needs to execute
the constraint? I mean it's needed if there exists BR insert triggers
which may change the row, but not otherwise. The patch currently does not
implement that check.

Thanks,
Amit

Attachment Content-Type Size
0001-Check-the-partition-constraint-even-after-tuple-rout.patch text/plain 6.2 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Erik Rijkers 2017-06-02 05:11:38 Re: logical replication - still unstable after all these months
Previous Message Andres Freund 2017-06-02 03:03:26 Re: walsender & parallelism