Project

General

Profile

1
----- Trigger function
2

    
3
-- Function: plantname_update_ancestors()
4

    
5
-- DROP FUNCTION plantname_update_ancestors();
6

    
7
CREATE OR REPLACE FUNCTION plantname_update_ancestors()
8
  RETURNS trigger AS
9
$BODY$
10
BEGIN
11
    -- Delete existing ancestors
12
    DELETE FROM plantname_ancestor WHERE plantname_id = new.plantname_id;
13
    
14
    IF new.parent_id IS NOT NULL THEN
15
        -- Copy parent's ancestors to this node's ancestors
16
        INSERT
17
        INTO plantname_ancestor
18
        (plantname_id, ancestor_id)
19
        SELECT
20
            new.plantname_id, ancestor_id
21
        FROM plantname_ancestor
22
        WHERE plantname_id = new.parent_id
23
        ;
24
    END IF;
25
    
26
    -- Add "ancestor" for this node
27
    /* This is useful for queries, because you don't have to separately test if
28
    the leaf node is the one you're looking for, in addition to that leaf node's
29
    ancestors. */
30
    INSERT
31
    INTO plantname_ancestor
32
    (plantname_id, ancestor_id)
33
    VALUES (new.plantname_id, new.plantname_id)
34
    ;
35
    
36
    -- Tell immediate children to update their ancestors lists, which will
37
    -- recursively tell all descendants
38
    UPDATE plantname
39
    SET plantname_id = plantname.plantname_id -- set to itself
40
    WHERE parent_id = plantname_id -- the plantname_id passed as param
41
    ;
42
    
43
    /* Note: We don't need an ON DELETE trigger to update the descendants'
44
    ancestors when a node is deleted, because the plantname.plantname_parent_id
45
    foreign key is set to ON DELETE CASCADE, which just removes all the
46
    descendants anyway. */
47
    
48
    RETURN new;
49
END;
50
$BODY$
51
  LANGUAGE plpgsql VOLATILE
52
  COST 100;
53
ALTER FUNCTION plantname_update_ancestors()
54
  OWNER TO bien;
55

    
56
----- Ancestors table
57

    
58
-- Table: plantname_ancestor
59

    
60
-- DROP TABLE plantname_ancestor;
61

    
62
CREATE TABLE plantname_ancestor
63
(
64
  plantname_id integer NOT NULL,
65
  ancestor_id integer NOT NULL,
66
  CONSTRAINT plantname_ancestor_pkey PRIMARY KEY (plantname_id , ancestor_id ),
67
  CONSTRAINT plantname_ancestor_ancestor_id FOREIGN KEY (ancestor_id)
68
      REFERENCES plantname (plantname_id) MATCH SIMPLE
69
      ON UPDATE CASCADE ON DELETE CASCADE,
70
  CONSTRAINT plantname_ancestor_plantname_id FOREIGN KEY (plantname_id)
71
      REFERENCES plantname (plantname_id) MATCH SIMPLE
72
      ON UPDATE CASCADE ON DELETE CASCADE
73
)
74
WITH (
75
  OIDS=FALSE
76
);
77
ALTER TABLE plantname_ancestor
78
  OWNER TO bien;
79

    
80
-- Index: fki_plantname_ancestor_ancestor_id
81

    
82
-- DROP INDEX fki_plantname_ancestor_ancestor_id;
83

    
84
CREATE INDEX fki_plantname_ancestor_ancestor_id
85
  ON plantname_ancestor
86
  USING btree
87
  (ancestor_id );
88

    
89
-- Index: fki_plantname_ancestor_plantname_id
90

    
91
-- DROP INDEX fki_plantname_ancestor_plantname_id;
92

    
93
CREATE INDEX fki_plantname_ancestor_plantname_id
94
  ON plantname_ancestor
95
  USING btree
96
  (plantname_id );
97

    
98
----- Trigger
99

    
100
-- Trigger: plantname_update_ancestors on plantname
101

    
102
-- DROP TRIGGER plantname_update_ancestors ON plantname;
103

    
104
CREATE TRIGGER plantname_update_ancestors
105
  AFTER INSERT OR UPDATE
106
  ON plantname
107
  FOR EACH ROW
108
  EXECUTE PROCEDURE plantname_update_ancestors();
(4-4/15)