/* To get the namedplace trigger, just search and replace "plantname" with "namedplace". */ ----- Trigger function -- Function: plantname_update_ancestors() -- DROP FUNCTION plantname_update_ancestors(); CREATE OR REPLACE FUNCTION plantname_update_ancestors() RETURNS trigger AS $BODY$ BEGIN -- Delete existing ancestors DELETE FROM plantname_ancestor WHERE plantname_id = new.plantname_id; IF new.parent_id IS NOT NULL THEN -- Copy parent's ancestors to this node's ancestors INSERT INTO plantname_ancestor (plantname_id, ancestor_id) SELECT new.plantname_id, ancestor_id FROM plantname_ancestor WHERE plantname_id = new.parent_id ; END IF; -- Add "ancestor" for this node /* This is useful for queries, because you don't have to separately test if the leaf node is the one you're looking for, in addition to that leaf node's ancestors. */ INSERT INTO plantname_ancestor (plantname_id, ancestor_id) VALUES (new.plantname_id, new.plantname_id) ; -- Tell immediate children to update their ancestors lists, which will -- recursively tell all descendants UPDATE plantname SET plantname_id = plantname_id -- need at least one SET statement WHERE parent_id = new.plantname_id -- the plantname_id passed as param ; /* Note: We don't need an ON DELETE trigger to update the descendants' ancestors when a node is deleted, because the plantname.plantname_parent_id foreign key is set to ON DELETE CASCADE, which just removes all the descendants anyway. */ RETURN new; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION plantname_update_ancestors() OWNER TO bien; ----- Ancestors table -- Table: plantname_ancestor -- DROP TABLE plantname_ancestor; CREATE TABLE plantname_ancestor ( plantname_id integer NOT NULL, ancestor_id integer NOT NULL, CONSTRAINT plantname_ancestor_pkey PRIMARY KEY (plantname_id , ancestor_id ), CONSTRAINT plantname_ancestor_ancestor_id FOREIGN KEY (ancestor_id) REFERENCES plantname (plantname_id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT plantname_ancestor_plantname_id FOREIGN KEY (plantname_id) REFERENCES plantname (plantname_id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ) WITH ( OIDS=FALSE ); ALTER TABLE plantname_ancestor OWNER TO bien; -- Index: fki_plantname_ancestor_ancestor_id -- DROP INDEX fki_plantname_ancestor_ancestor_id; CREATE INDEX fki_plantname_ancestor_ancestor_id ON plantname_ancestor USING btree (ancestor_id ); -- Index: fki_plantname_ancestor_plantname_id -- DROP INDEX fki_plantname_ancestor_plantname_id; CREATE INDEX fki_plantname_ancestor_plantname_id ON plantname_ancestor USING btree (plantname_id ); ----- Trigger -- Trigger: plantname_update_ancestors on plantname -- DROP TRIGGER plantname_update_ancestors ON plantname; CREATE TRIGGER plantname_update_ancestors AFTER INSERT OR UPDATE ON plantname FOR EACH ROW EXECUTE PROCEDURE plantname_update_ancestors();