Re: Bug: Rule actions see wrong values for generated columns (NEW.gen reads OLD value)

Dean Rasheed <dean.a.rasheed@gmail.com>

From: Dean Rasheed <dean.a.rasheed@gmail.com>
To: Richard Guo <guofenglinux@gmail.com>
Cc: Chao Li <li.evan.chao@gmail.com>, SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>, Peter Eisentraut <peter@eisentraut.org>
Date: 2026-04-13T11:03:53Z
Lists: pgsql-hackers
On Mon, 13 Apr 2026, 09:20 Richard Guo, <guofenglinux@gmail.com> wrote:

> On Mon, Apr 13, 2026 at 4:21 PM Chao Li <li.evan.chao@gmail.com> wrote:
> > I think the issue is that rewriteTargetListIU() removes generated
> columns from the target list, as described by this comment:
>
> > Later, when the rule action is rewritten, ReplaceVarsFromTargetList()
> cannot find a target list entry for NEW.gen. For UPDATE rules, the missing
> NEW column is handled with REPLACEVARS_CHANGE_VARNO, so it falls back to
> referencing the original target relation row, which gives the old value.
>
> I came to the same conclusion.
>
> > One possible fix is to build a new target list that adds generated
> columns back when there are rules to fire. I tried the solution locally
> with some quick and dirty code and it seems to fix both stored and virtual
> generated columns for me.
>
> I think a simpler fix might be to expand generated column references
> in the NEW relation to their generation expressions before
> ReplaceVarsFromTargetList resolves NEW references, so that the base
> column Vars within the expressions can be correctly resolved.
> Something like attached.
>
> - Richard
>

One thing about that approach is that it leads to 2 full rewrites of the
rule action using ReplaceVarsFromTargetList(). I think that could be
avoided by using including generated column expressions in the targetlist
passed to ReplaceVarsFromTargetList() by rewriteRuleAction(). I haven't
tried it, but I imagine it could reuse some code
from expand_generated_columns_internal().

Regards,
Dean

>

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Fix incorrect NEW references to generated columns in rule rewriting