Re: [BUG] ON CONFLICT DO UPDATE SET x = EXCLUDED.<virtual-generated-column> errors or silently writes NULL

From: SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>
To: Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: [BUG] ON CONFLICT DO UPDATE SET x = EXCLUDED.<virtual-generated-column> errors or silently writes NULL
Date: 2026-04-20 00:55:26
Message-ID: CAHg+QDfk7PrpV7eso7DLqn=fCt1ts9axDsUmu6-RZrWost-oDg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

HI,

On Sat, Apr 18, 2026 at 11:14 AM Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com>
wrote:

> On Thu, 16 Apr 2026 at 21:49, SATYANARAYANA NARLAPURAM
> <satyanarlapuram(at)gmail(dot)com> wrote:
> >
> > Virtual generated column (bgc) behavior for plain and partitioned tables
> is different
> > when EXCLUDED.<vgc> references inside for INSERT ... ON CONFLICT DO
> UPDATE.
> > For plain table it errors out with the message "unexpected virtual
> generated column reference"
> > and for partitioned tables, it silently writes NULL (wrong data).
>
> Nice catch!
>
> > I tried fixing this by replacing build_tlist_index with
> build_tlist_index_other_vars . This fix
> > works because build_tlist_index_other_vars only indexes plain-Var TEs of
> exclRelTlist and
> > leaves has_non_vars = false, so fix_join_expr skips whole-subtree
> matching and never collapses
> > the VGC-expanded (EXCLUDED.a * 10) in onConflictSet back into a
> Var(INNER_VAR, vgc_attno).
>
> This doesn't quite work in all cases -- if the generated expression is
> simply a Var, then it is found in the indexed tlist without the
> non_var matching code, leading to the same problem. For example,
> modifying your original test case to this:
>
> CREATE TABLE t (id int PRIMARY KEY,
> c int GENERATED ALWAYS AS (a) VIRTUAL, a int);
>
> Admittedly, that's a rather silly example, but we really ought to have
> a fix that works for all cases.
>

Agreed.

>
> Looking more closely, I think the right fix is to not expand virtual
> generated columns in the targetlist of EXCLUDED (exclRelTlist), so
> then they will not be found as matching expressions in the setrefs.c
> code.
>
> I also noticed that there are already a couple of places in the
> planner that claim that exclRelTlist contains only Vars, so this
> approach makes that claim true (though I don't think those other
> places represented actual bugs).
>
> Attached is a v2 patch doing it that way, with the same tests, which all
> pass.
>

Reran the failing tests and they all passed. Additionally ran the
regression tests.
Patch looks good to me.

>
> Regards,
> Dean
>

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Alexander Lakhin 2026-04-20 01:00:01 Re: Typos in the code and README
Previous Message wenhui qiu 2026-04-20 00:49:25 Re: Clean up remove_rel_from_query() after self-join elimination commit