HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Delete rule on view does not execute every statement

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
deleterulestatementeveryviewdoesnotexecute

Problem

When I have more than one statements in a rule on a view, the second one is not executed in case the first one deletes the original entry. Even when the second statement does not have anything to do with the original entry at all.

Here is a simple example. Tables are reach and rp (reachpoint) and in reach we have an id that can be referenced to rp.

CREATE TABLE test_delete_rule.reach
(
  id integer NOT NULL,
  rp integer
);

CREATE TABLE test_delete_rule.rp
(
  id integer NOT NULL
);

INSERT INTO test_delete_rule.reach (id, rp) VALUES (1,10);
INSERT INTO test_delete_rule.reach (id, rp) VALUES (2,20);
INSERT INTO test_delete_rule.reach (id, rp) VALUES (3,30);
INSERT INTO test_delete_rule.reach (id, rp) VALUES (4,40);
INSERT INTO test_delete_rule.rp (id) VALUES (10);
INSERT INTO test_delete_rule.rp (id) VALUES (20);
INSERT INTO test_delete_rule.rp (id) VALUES (30);
INSERT INTO test_delete_rule.rp (id) VALUES (40);


And there is a view on reach called vw_reach:

CREATE VIEW test_delete_rule.vw_reach AS 
    select * from test_delete_rule.reach


And on this view is a rule, deleting the reach and the referenced rp:

CREATE OR REPLACE RULE reach_on_delete AS
  ON DELETE TO test_delete_rule.vw_reach 
  DO INSTEAD 
  ( 
    DELETE FROM test_delete_rule.reach
    WHERE reach.id = old.id;

    DELETE FROM test_delete_rule.rp
    WHERE rp.id = old.rp;
  );


When we delete now an entry from the vw_reach

delete from test_delete_rule.vw_reach where id = 2


The entry with id 2 from reach is deleted, but not the entry with 20 from rp.

When I have the same rule on the table with DO ALSO ir works:

CREATE OR REPLACE RULE reach_on_delete AS
    ON DELETE TO test_delete_rule.reach  
    DO ALSO 
    (
       DELETE FROM test_delete_rule.rp
       WHERE rp.id = old.rp;
    );


So according the response here https://stackoverflow.com/questions/5534927/how-to-write-a-delete-rule-on-a-view the second statement is not executed becau

Solution

Quote from the manual


Caution


In many cases, tasks that could be performed by rules on INSERT/UPDATE/DELETE are better done with triggers. Triggers are notationally a bit more complicated, but their semantics are much simpler to understand.

(Emphasis mine)

I think this is one of the many cases where this is better done with a trigger:

create or replace function delete_reach() 
  returns trigger
as
$
begin
  DELETE FROM reach
  WHERE reach.id = old.id;

  DELETE FROM rp
  WHERE rp.id = old.rp;
  return old;
end;  
$
language plpgsql;

create trigger delete_reach_trigger 
   instead of delete 
   on vw_reach
   for each row
   execute procedure delete_reach();


Online example: https://rextester.com/KMEDTV61929

Code Snippets

create or replace function delete_reach() 
  returns trigger
as
$$
begin
  DELETE FROM reach
  WHERE reach.id = old.id;

  DELETE FROM rp
  WHERE rp.id = old.rp;
  return old;
end;  
$$
language plpgsql;

create trigger delete_reach_trigger 
   instead of delete 
   on vw_reach
   for each row
   execute procedure delete_reach();

Context

StackExchange Database Administrators Q#227360, answer score: 2

Revisions (0)

No revisions yet.