trigger to maintain relationships - Mailing list pgsql-sql

From David M
Subject trigger to maintain relationships
Date
Msg-id 3DF770E3.1C4FABFD@ucia.gov
Whole thread Raw
List pgsql-sql
I am maintaining a set of hierarchical data that looks a lot like a
tree.  (And my SQL is very rusty.  And I'm new to postgres.)

Questions:
-------------
1.)  Is the following a reasonable solution?  Is there a
postgres-specific way to handle this better?  Is there a good generic
SQL way to handle this?
2.)  Can I write pure "SQL" triggers to handle this?  Am I getting close
in my first cut (below)?
3.)  Any other ideas/suggestions?


I have one table with essentially the nodes of a tree:

nodes
------
node_id     integer
parent_id   integer references nodes(node_id)
...and other descriptive columns...

I want an easy way to find all the elements of a subtree.  Not being
able to think of a good declarative solution, I was thinking about
cheating and maintaining an ancestors table:

ancestors
-----------
node_id        integer
ancestor_id   integer references nodes(node_id)

I figured I could populate the ancestors table via trigger(s) on the
nodes table.  Then I should be able to find a whole subtree of node X
with something like:

select *
from nodes
where node_id in (   select node_id   from ancestors   where ancestor_id = X)

Here's my best guess so far at the triggers (but, obviously, no luck so
far):

--insert trigger
create function pr_tr_i_nodes() returns opaque
as '   insert into ancestors   select NEW.node_id, ancestor_id   from ancestors   where node_id = NEW.parent_id;'
language sql;
create trigger tr_i_nodes after insert   on nodes for each row   execute procedure pr_tr_i_nodes();

--delete trigger
create function pr_tr_d_nodes() returns opaque
as '   delete from ancestors   where node_id = OLD.parent_id;'
language sql;
create trigger tr_d_nodes after insert   on nodes for each row   execute procedure pr_tr_d_nodes();

--update trigger
create function pr_tr_u_nodes() returns opaque
as '   delete from ancestors   where node_id = OLD.parent_id;
   insert into ancestors   select NEW.node_id, ancestor_id   from ancestors   where node_id = NEW.parent_id;'
language sql;
create trigger tr_u_nodes after insert   on nodes for each row   execute procedure pr_tr_u_nodes();

I realize the update trigger could be handled a multitude of ways and
that my first guess may be pretty lousy.  But I figured the
insert/update triggers would be pretty straightforward.  Am I missing
something basic?  I also tried things like (following the one example in
the reference manual):

--insert trigger
create function pr_tr_i_nodes() returns opaque
as '   insert into ancestors   select NEW.node_id, ancestor_id   from ancestors   where node_id = NEW.parent_id;
   return NEW;'
language 'plpgsql';
create trigger tr_i_nodes after insert   on nodes for each row   execute procedure pr_tr_i_nodes();




pgsql-sql by date:

Previous
From: Jean-Luc Lachance
Date:
Subject: Re: union query doubt:
Next
From: David M
Date:
Subject: Re: trigger to maintain relationships