| From: | Ewan Young <kdbase(dot)hack(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Cc: | Peter Eisentraut <peter(at)eisentraut(dot)org>, pj(at)illuminatedcomputing(dot)com |
| Subject: | FOR PORTION OF silently ignored on views with DO INSTEAD rules |
| Date: | 2026-09-03 04:19:49 |
| Message-ID: | CAON2xHO5FJ1jC87cQhGg+KMG5QR7ZaifJwN24rPjMqCGYn-hzA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi,
An UPDATE/DELETE ... FOR PORTION OF against a view that has an
unqualified DO INSTEAD rule silently ignores the FOR PORTION OF clause
and modifies (or deletes) the whole temporal row instead of just the
requested portion -- no error, no warning:
CREATE TABLE t (id int, valid_at daterange, name text);
INSERT INTO t VALUES (1, '[2020-01-01,2021-01-01)', 'a');
CREATE VIEW v AS SELECT * FROM t;
CREATE RULE v_upd AS ON UPDATE TO v DO INSTEAD
UPDATE t SET name = NEW.name WHERE id = OLD.id;
UPDATE v FOR PORTION OF valid_at FROM '2020-06-01' TO '2020-07-01'
SET name = 'b';
SELECT * FROM t;
id | valid_at | name
----+-------------------------+------
1 | [2020-01-01,2021-01-01) | b -- whole row changed
The same statement on the base table (or a plain auto-updatable view)
correctly splits the row three ways. DELETE is worse: DELETE ... FOR
PORTION OF through such a view removes the entire row.
The cause is that an unqualified INSTEAD rule replaces the original
query with the rule's action during rewriting, so rewriteTargetView()
-- the path that carries the query's forPortionOf through a view -- is
never reached, and the rule action has forPortionOf = NULL. This is
the exact analog of the INSTEAD OF trigger case that dfce19c2300
("Forbid FOR PORTION OF on views with INSTEAD OF triggers") already
rejects with a feature-not-supported error (5b5e99047ab on
REL_19_STABLE); the DO INSTEAD rule sibling was left unguarded.
The attached patch rejects FOR PORTION OF when an unqualified INSTEAD
rule fires on a view, using the same error as the trigger case. A
DO ALSO rule does not replace the query, so FOR PORTION OF keeps working
on the automatically-updatable path; the tests cover that as well as the
UPDATE and DELETE INSTEAD-rule cases. make check passes. The patch
is against master; the same code (and the same behavior) is present on
REL_19_STABLE.
--
Regards,
Ewan Young
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Reject-FOR-PORTION-OF-on-views-with-instead-rules.patch | application/octet-stream | 7.7 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Antonin Houska | 2026-09-03 04:42:06 | Re: REPACK (ANALYZE) within transaction block segfaults |
| Previous Message | Fujii Masao | 2026-09-03 04:19:30 | Re: Stabilize recovery conflict stats checks in 031_recovery_conflict.pl |