Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wCF5O-001nGJ-2d for pgsql-hackers@arkaria.postgresql.org; Mon, 13 Apr 2026 11:04:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wCF5M-006NNZ-0q for pgsql-hackers@arkaria.postgresql.org; Mon, 13 Apr 2026 11:04:09 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wCF5L-006NNR-2p for pgsql-hackers@lists.postgresql.org; Mon, 13 Apr 2026 11:04:08 +0000 Received: from mail-qt1-x82f.google.com ([2607:f8b0:4864:20::82f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wCF5K-00000000oyR-3QGH for pgsql-hackers@lists.postgresql.org; Mon, 13 Apr 2026 11:04:08 +0000 Received: by mail-qt1-x82f.google.com with SMTP id d75a77b69052e-50b2ebca625so37243181cf.0 for ; Mon, 13 Apr 2026 04:04:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776078245; cv=none; d=google.com; s=arc-20240605; b=EOCwKgZT0xEXnRQE0a1Avb1vPJkGlsoHxnSks6sgECdEsUx7IcFkCWFag94bw2rF5K Wh9WvwzWaETTZ3qraZ8pAORbC6QDGG2T4f9JO5zoz2utWGXvDECKaP9D5hnEtHdWxIIe Dg8NOC3KoVyeDdXs6FyxBsbIkyjZcYVU85gKq86SOrGO5IVgwT+qrCyD90oC4J+PmX+d VWkEfyqOhXEVKwq0jeWHZ3ntwmhCINxsK9IcvmW3QAScPmNnOzli4qyEGCraIWKyGzhF y6zcQiTsNaE3Hq8OLHJ6N3E6O4IvxL4VJg4zcCWbfM7zI2f4+MaKhH1SgJkzRn+4dczi wsNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=Cog0W3LB6m0isEbhBRU4hgeIS8JTOaaSIe/s4xQhQOI=; fh=5q1h8LXrCTsm5+9cykWUMJ8DgtXscLxR3ORd9ITf8fY=; b=l2UDEAYjWyznjpjpnAEc0Xl6Qa8GYbpfVIM2aZLbwoRPO2ofcN584claBaOe7EhPZ4 3/HYglpyiQT7/7rTgLXV53jUbzJMlkDVdEnOTQjep+iVNjob1wss7P0zev8fcFnVf/2X F+n1k1JvgOY+FtD5kA9moKu/hNrgwWn6YoytrTo4knGCtLzV4tLKTifxGHx3nDts4npS 5H2CGX9K/DvSQFXSe3Wpq0ny0P9cxgV22SWKXB1tbt2ERcusqf1CmfZEzvoFNXHLjIrL MEo1y1+tLoYUYo6U96UaG3uzpd5u17IkCXychgm4tD01pHpqlLGm5CeDz5UMhX9O0qUc TPHw==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776078245; x=1776683045; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Cog0W3LB6m0isEbhBRU4hgeIS8JTOaaSIe/s4xQhQOI=; b=lyqN+tBsHVjGTP5mDo7PyBTElWkgc0RliMqF7G8vlktCfWHRIl5V33/pC0m26qG0NT cCttAdkqfvXlBqY2Z/l3UuJtJm5QQ7vQGC5uA+VBcItQHfNjYeFPfOTpYPXkTtQGKxPR mDVo08savHIQB5RZrMaO6dtdK0udaGSRxxASscatPZdFkH9yQDNOOU80Je5pQJpSF6EE +cktPujCnFqteZdepOvfzU8hO6jRW/MJbSuWhJlhSLIyYc2tSaPtejHfcsdK2Bv1z62o uwEoww8RfrvbWx7DGeYRuY10F5FCGvpsipZlU/Zrgn4wjdqmFsyaas6JXmzCW6L2SaCf Ln/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776078245; x=1776683045; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Cog0W3LB6m0isEbhBRU4hgeIS8JTOaaSIe/s4xQhQOI=; b=cjTiJXso+ExVGU97FoTLD9dA78h5QrAwB00rzX0uALh46sXP6FAgI8OiDiMQ3IVcLo SJM3p0n0nMH6hRtsxXmuGjlocCzw4zM7PdZq0UB/lB9OGyfrp8M3i+Rg1knzbdt62zI5 5a3ORm0lMWaeW/eBSztmozH2bpJHM3BkXWwKRWegQVZLfBonXwj+BJtark2+qLkSHipi OHvyivfktHcgoXRr3qb07yTDZ9KAoseajia5/KjPlYYkUPLwc5CDVWRb9XcX8Z76QNZ7 MXGT0kqbquir4YyAvTA5u4iL9IuIeOEQK7+LEGVfs3xnB4OEEyq1iTcW+qMxs9fTqqNK hj/w== X-Forwarded-Encrypted: i=1; AFNElJ9bH3HyRDjRBQDr60ipxEV6ADPTdlB47C90GNPldISh5GzoNpxLBkr8ViFXDoPXAe3kmJvjc6xZCFNM7U8h@lists.postgresql.org X-Gm-Message-State: AOJu0Yx51r+8rJt1oBfIA0dsFOKr2D5mRjXpZ9Kh3ivh/l3IoU2Yb74m bKtHuwqzzltQq3OPH9GiczLbdsI2IXp74dmGHQd4CDfO7arf1EXepjBZ3ntq16B8Abh5qKgnywU NeYd6OTnE71BVTS3Mb43vGzgzzS13d+Q= X-Gm-Gg: AeBDiev5/3SS6OSnNsGELztSqqApjzuZNy1UJWNcGOESQkDuC6cAt5dIHLx7uNbdZcG Z0HKd+LvYZILlfGp9gsU7BmktHhahxYszrioJ/kD/kySJVSYuXPE0ufvbZX6xxKqZmx6uw7AgSR V9JzApn1PYN1pNm1+xWGyjA+AgivmSrX7nNgX+Xkj/LDNMddvfhr8rkJ3Lwr8vjNJJ0gsHttGTl 5xECCgvRYzKJE6vdUak1gHq5UPtPtS72v7+v6f0XYkRxEVPYEwDKhGF8xX6W6HKWJ9Huj3SpHLq XXnSGMs= X-Received: by 2002:ac8:5a8f:0:b0:50d:a8bd:dc07 with SMTP id d75a77b69052e-50dc1b36aabmr231305841cf.35.1776078244726; Mon, 13 Apr 2026 04:04:04 -0700 (PDT) MIME-Version: 1.0 References: <22B4A33A-99F3-46F5-BE0C-426A9E1D9ABA@gmail.com> In-Reply-To: From: Dean Rasheed Date: Mon, 13 Apr 2026 12:03:53 +0100 X-Gm-Features: AQROBzBRpmJhoopKn8CZE6Fr347nqBCgcOpyznaUzF-AS6NqfSkWtUvyq3J0EKg Message-ID: Subject: Re: Bug: Rule actions see wrong values for generated columns (NEW.gen reads OLD value) To: Richard Guo Cc: Chao Li , SATYANARAYANA NARLAPURAM , PostgreSQL Hackers , Peter Eisentraut Content-Type: multipart/alternative; boundary="000000000000decae0064f557052" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000decae0064f557052 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, 13 Apr 2026, 09:20 Richard Guo, wrote: > On Mon, Apr 13, 2026 at 4:21=E2=80=AFPM Chao Li = 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 missin= g > 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 virtua= l > 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 > --000000000000decae0064f557052 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Mon, 13 Apr 2026, 09:20 Richard Guo, = <guofenglinux@gmail.com>= ; wrote:
On Mon,= Apr 13, 2026 at 4:21=E2=80=AFPM Chao Li <li.evan.chao@gmail.com= > wrote:
> I think the issue is that rewriteTargetListIU() removes generated colu= mns 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 re= ferencing 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 col= umns back when there are rules to fire. I tried the solution locally with s= ome quick and dirty code and it seems to fix both stored and virtual genera= ted 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 b= e 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=C2=A0expand_generat= ed_columns_internal().

R= egards,
Dean
--000000000000decae0064f557052--