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: v1-0001-Reject-FOR-PORTION-OF-on-views-with-instead-rules.patch
Description: Binary data

Reply via email to