public inbox for [email protected]  
help / color / mirror / Atom feed
From: Richard Guo <[email protected]>
To: Dean Rasheed <[email protected]>
Cc: Chao Li <[email protected]>
Cc: SATYANARAYANA NARLAPURAM <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Cc: Peter Eisentraut <[email protected]>
Subject: Re: Bug: Rule actions see wrong values for generated columns (NEW.gen reads OLD value)
Date: Tue, 14 Apr 2026 12:27:39 +0900
Message-ID: <CAMbWs49DcHqOtd_BzuFcr9Va+tD-2fNs8bGsbH_Zy2bXUTNM1g@mail.gmail.com> (raw)
In-Reply-To: <CAEZATCWYqyJJJcMNEj-LEvCSwog2H_HS61hTROZLKYuaiy5YTg@mail.gmail.com>
References: <CAHg+QDexGTmCZzx=73gXkY2ZADS6LRhpnU+-8Y_QmrdTS6yUhA@mail.gmail.com>
	<CAMbWs4-SJ6B26ciFu_K_2M1ObDA=GirV87N1BKeAtSRmQGATUA@mail.gmail.com>
	<[email protected]>
	<CAMbWs48=QrLy8gZprTfCmEtzoaUku54JXvAcnoRSo+OC8vUpwA@mail.gmail.com>
	<CAEZATCWYqyJJJcMNEj-LEvCSwog2H_HS61hTROZLKYuaiy5YTg@mail.gmail.com>

On Mon, Apr 13, 2026 at 8:04 PM Dean Rasheed <[email protected]> wrote:
> On Mon, 13 Apr 2026, 09:20 Richard Guo, <[email protected]> wrote:
>> 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.

> 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().

I considered it, but I'm afraid it doesn't work directly, because
replace_rte_variables_mutator returns the callback's replacement node
without recursing into its children.

Take Satya's repro as an example.  If we add the generation expression
for gen to the UPDATE's targetlist, the list would be:

    TargetEntry 1: resno=2, expr=Const(100)       -- a = 100
    TargetEntry 2: resno=3, expr=Var(3, 2) * 2    -- gen = NEW.a * 2

When ReplaceVarsFromTargetList processes Var(3, 3) (NEW.gen) in the
rule action, it finds resno=3 and substitutes Var(3, 2) * 2.  However,
replace_rte_variables_mutator returns this replacement directly to its
caller; it does not recurse into the replacement's children to look
for further matching Vars.  So the inner Var(3, 2) (NEW.a) is never
processed, even though resno=2 with Const(100) is right there in the
targetlist.  The Var(3, 2) survives into the planner and would cause
problems.

It could be made to work by pre-resolving the generation expressions'
base column Vars before adding them to the UPDATE's targetlist.  For
each generated column, we'd call ReplaceVarsFromTargetList on the
generation expression to resolve its base column Vars, then add the
fully resolved expression to the targetlist.  But this seems to add
code complexity.  And I'm not sure about the performance difference
between these two approaches.  I expect that rule action trees are
typically small.

- Richard





view thread (16+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Bug: Rule actions see wrong values for generated columns (NEW.gen reads OLD value)
  In-Reply-To: <CAMbWs49DcHqOtd_BzuFcr9Va+tD-2fNs8bGsbH_Zy2bXUTNM1g@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox