Re: rules, triggers and views - Mailing list pgsql-hackers

From Andrew - Supernews
Subject Re: rules, triggers and views
Date
Msg-id slrncr790e.sjo.andrew+nonews@trinity.supernews.net
Whole thread Raw
In response to rules, triggers and views  (elein <elein@varlena.com>)
Responses Re: rules, triggers and views
List pgsql-hackers
On 2004-12-05, elein <elein@varlena.com> wrote:
> We're working on DBI-link which is an access method of sorts
> using existing tools.
>
> We want an empty local table foo with
>     1. a _RETURN RULE
>     2. an update TRIGGER
>     3. a delete TRIGGER
>     4. an insert TRIGGER

Use two tables. One has rules, the other has the trigger. (Neither store
any data.) Here's a working example (tested on 7.4.5):

-- declare the table which we're going to be manipulating. This never
-- actually stores anything (it becomes a view).
create table realtable (id integer, value text);

-- This is where the data comes from (hardcoded for example purposes)
create or replace function datasource() returns setof realtable as ' declare   v realtable; begin   v.id:=1;
v.value:=''foo'';return next v;   v.id:=2; v.value:=''bar''; return next v;   v.id:=3; v.value:=''baz''; return next v;
 raise notice ''datasource() returned 3 rows'';   return; end;
 
' language plpgsql;

-- This is where the updates etc. go to. It must return NULL, because we
-- want to suppress the actual row insertion.
create or replace function datasink() returns trigger as ' begin   raise notice ''datasink(): % % % % %'',
 NEW.opcode,NEW.o_id,NEW.o_value,NEW.n_id,NEW.n_value;   return NULL; end;
 
' language plpgsql;

-- This is a dummy table that we use for attaching the trigger to.
-- It's a real table, but it never contains data. Note that it stores
-- two copies of the data from "realtable" plus an opcode.
create table shadowtable (opcode "char",                         o_id integer, o_value text,
n_idinteger, n_value text);
 

-- attach the trigger
create trigger shadow_trigger before insert on shadowtable for each row execute procedure datasink();

-- Rules. We convert all modifications on realtable into inserts on
-- shadowtable.
create rule "_RETURN" as  on select to realtable  do instead select * from datasource();
create rule ins_rule as  on insert to realtable  do instead insert into shadowtable values ('i',NEW.*);
create rule upd_rule as  on update to realtable  do instead insert into shadowtable values ('u',OLD.*,NEW.*);
create rule del_rule as  on delete to realtable  do instead insert into shadowtable values ('d',OLD.*);

Now we see it in action:

test=> update realtable set value = 'quux' where id=3;
NOTICE:  datasource() returned 3 rows
NOTICE:  datasink(): u 3 baz 3 quux
UPDATE 0
test=> delete from realtable where value='bar';
NOTICE:  datasource() returned 3 rows
NOTICE:  datasink(): d 2 bar <NULL> <NULL>
DELETE 0
test=> delete from realtable;                  
NOTICE:  datasource() returned 3 rows
NOTICE:  datasink(): d 1 foo <NULL> <NULL>
NOTICE:  datasink(): d 2 bar <NULL> <NULL>
NOTICE:  datasink(): d 3 baz <NULL> <NULL>
DELETE 0
test=> insert into realtable values (4,'zoom');
NOTICE:  datasink(): i 4 zoom <NULL> <NULL>
INSERT 0 0

(Unfortunately, all the update operations return 0 rows affected. Not sure
there's any fix for that.)

-- 
Andrew, Supernews
http://www.supernews.com - individual and corporate NNTP services


pgsql-hackers by date:

Previous
From: elein
Date:
Subject: Re: rules, triggers and views
Next
From: "Marc G. Fournier"
Date:
Subject: Re: WIN1252 encoding - backend or not?