Re: BUG #16644: null value for defaults in OLD variable for trigger

Поиск
Список
Период
Сортировка
От Amit Langote
Тема Re: BUG #16644: null value for defaults in OLD variable for trigger
Дата
Msg-id CA+HiwqH7ys=WmnbGm+wgQwt0WzvQ-R-Qn4vdE01Q_QsX7cyFsw@mail.gmail.com
обсуждение исходный текст
Ответ на Re: BUG #16644: null value for defaults in OLD variable for trigger  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: BUG #16644: null value for defaults in OLD variable for trigger  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
On Wed, Sep 30, 2020 at 11:21 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> After tracing through it, what I find is that:
>
> 1. Where ExecBRUpdateTriggers fetches the "trigtuple" (line 2695
> of trigger.c, in HEAD) what it gets is a raw copy of the old
> on-disk tuple, with natts = 1.  That gets passed to the trigger
> function as OLD, but it reads correctly because it's being decoded
> with the relation's tupdesc, which has the needed info to fill in
> attrmissing columns.
>
> 2. When the trigger does "return OLD", trigtuple is what gets
> passed back, and it gets jammed into the slot that ExecUpdate
> passed to ExecBRUpdateTriggers.  *That slot does not have any
> attrmissing info*.  Thus, subsequent examination of the slot,
> in particular by ExecConstraints, concludes that the recently-
> added column is NULL.
>
> I've not tried to find where is the difference between 11 and
> 12 that makes it fail or not fail.  It's likely some innocent
> seeming aspect of the slot management hacking that Andres
> was doing around that time.  It's a bit odd though, because
> AFAICS the slot in question is going to be the result slot
> of the JunkFilter used by ExecModifyTable, and I'd rather have
> expected that that slot would never have had any constraints,
> in any version.

In v11, GetTupleForTrigger() expands the HeapTuple, with this:

    /*
     * While this is not necessary anymore after 297d627e, as a defense
     * against C code that has not recompiled for minor releases after the
     * fix, continue to expand the tuple.
     */
    if (HeapTupleHeaderGetNatts(tuple.t_data) < relation->rd_att->natts)
        result = heap_expand_tuple(&tuple, relation->rd_att);
    else
        result = heap_copytuple(&tuple);
    ReleaseBuffer(buffer);

So the tuple that gets slammed into JunkFilter's result slot is an
expanded copy of the on-disk tuple, so it doesn't matter that its
TupleDesc doesn't have constraints (constr) initialized.

In v12 and further, I see that the tuple fetched by
GetTupleForTrigger() is slammed into JunkFilter's result slot
unexpanded and it remains so through ExecConstraint().

> I think we can band-aid this immediate problem by forcing
> trigger.c to materialize the "old" tuples it fetches from disk
> (or whatever needs to be done to substitute missing values into
> them).

Maybe something like the attached?

--
Amit Langote
EDB: http://www.enterprisedb.com

Вложения

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: BUG #16683: explain plan format xml produces invalid xml
Следующее
От: Tom Lane
Дата:
Сообщение: Re: BUG #16644: null value for defaults in OLD variable for trigger