agora inbox for pgsql-bugs@postgresql.org
help / color / mirror / Atom feedFrom: 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