agora inbox for pgsql-bugs@postgresql.org  
help / color / mirror / Atom feed
From: PG Bug reporting form <noreply@postgresql.org>
To: pgsql-bugs@lists.postgresql.org
Cc: hackerzheng666@gmail.com
Subject: BUG #19632: RULE rewriting crashes with XX000 when RETURNING old/new references a system column
Date: Wed, 19 Aug 2026 03:52:11 +0000
Message-ID: <19632-9155d9baec763c8c@postgresql.org> (raw)

The following bug has been logged on the website:

Bug reference:      19632
Logged by:          Zheng Hacker
Email address:      hackerzheng666@gmail.com
PostgreSQL version: 19beta3
Operating system:   Linux x86_64
Description:        

PostgreSQL version: 20devel (commit bdbf662, 2026-08-19)
  OS: Linux x86_64
  
  When a DML query with RETURNING old.<system_column> or
  RETURNING new.<system_column> (PG 20 new syntax) is rewritten
  through a RULE, the query rewriter cannot find replacement
  targetlist entries for system columns, hitting elog(ERROR) in
  rewriteManip.c.
  
  Reproducer:
  
  CREATE TABLE t (a int);
  INSERT INTO t VALUES (1);
  CREATE RULE t_del AS ON DELETE TO t
    DO INSTEAD UPDATE t SET a = -1 WHERE a = OLD.a RETURNING *;
    
  -- All of these crash with XX000:
  DELETE FROM t WHERE a = 1 RETURNING old.tableoid;
  -- ERROR: XX000: could not find replacement targetlist entry for attno -6
  -- LOCATION: ReplaceVarFromTargetList, rewriteManip.c:1884
  
  DELETE FROM t WHERE a = 1 RETURNING old.ctid;     -- attno -1
  DELETE FROM t WHERE a = 1 RETURNING new.tableoid;  -- attno -6
  
  -- Without the RULE, the same RETURNING clause works correctly:
  DROP RULE t_del ON t;
  DELETE FROM t WHERE a = 1 RETURNING old.tableoid;  -- works fine
  
  Root cause: src/backend/rewrite/rewriteManip.c, function
  ReplaceVarFromTargetList (line 1884). When the rewriter processes
  the RULE's action to replace Vars, it iterates over the action's
  target list looking for an entry with matching resno. System
  columns have negative attribute numbers (e.g. tableoid = -6), but
  the RULE's RETURNING target list only contains user-defined columns
  (with positive resnos), so no match is found.
  
  The PG 20 old/new RETURNING syntax (var->varreturningtype !=
  VAR_RETURNING_DEFAULT) is handled AFTER the targetlist entry lookup
  succeeds (lines 1894-1910), so the code never reaches that logic
  for system columns.
  
  Affects all system columns (tableoid, ctid, xmin, cmin, xmax)
  through any RULE that uses DO INSTEAD.

  Found by automated SQL fuzzing.
  Credit: Zheng Wang, Yanjie Zhao, Yiyang Liu








view thread (9+ messages)  latest in thread

Message-ID: <19632-9155d9baec763c8c@postgresql.org>
Permalink:  ../19632-9155d9baec763c8c@postgresql.org/
Also on:    postgresql.org/message-id/19632-9155d9baec763c8c@postgresql.org

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: pgsql-bugs@postgresql.org
  Cc: noreply@postgresql.org, pgsql-bugs@lists.postgresql.org, hackerzheng666@gmail.com
  Subject: Re: BUG #19632: RULE rewriting crashes with XX000 when RETURNING old/new references a system column
  In-Reply-To: <19632-9155d9baec763c8c@postgresql.org>

* 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