trigger to maintain relationships

From: David M <davidgm0(at)ucia(dot)gov>
To: pgsql-sql(at)postgresql(dot)org
Subject: trigger to maintain relationships
Date: 2002-12-11 17:07:47
Message-ID: 3DF770E3.1C4FABFD@ucia.gov
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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();

Responses

Browse pgsql-sql by date

  From Date Subject
Next Message David M 2002-12-11 17:35:54 Re: trigger to maintain relationships
Previous Message Jean-Luc Lachance 2002-12-11 16:57:19 Re: union query doubt: