Project

General

Profile

« Previous | Next » 

Revision 5549

schemas/tree_cross-links.sql: Updated for new taxonconcept_update_ancestors() trigger

View differences:

schemas/tree_cross-links.sql
1
/* To get the place trigger, just search and replace taxonconcept with place. */
1
/* To get the place trigger, replace taxonconcept with place and remove
2
references to matched_concept_id. */
2 3

  
3
----- Trigger function
4
----- Functions
4 5

  
5
-- Function: taxonconcept_update_ancestors()
6
-- Function: taxonconcept_update_ancestors(taxonconcept, integer)
6 7

  
7
-- DROP FUNCTION taxonconcept_update_ancestors();
8
-- DROP FUNCTION taxonconcept_update_ancestors(taxonconcept, integer);
8 9

  
9
CREATE OR REPLACE FUNCTION taxonconcept_update_ancestors()
10
  RETURNS trigger AS
10
CREATE OR REPLACE FUNCTION taxonconcept_update_ancestors(new taxonconcept, old_parent_id integer DEFAULT NULL::integer)
11
  RETURNS void AS
11 12
$BODY$
13
DECLARE
14
    -- Use matched_concept_id's ancestors instead if available
15
    parent_id_ taxonconcept.taxonconcept_id%TYPE :=
16
        COALESCE(new.matched_concept_id, new.parent_id);
12 17
BEGIN
13
    -- Delete existing ancestors
14
    DELETE FROM taxonconcept_ancestor
15
    WHERE taxonconcept_id = new.taxonconcept_id;
16
    
17
    IF new.parent_id IS NOT NULL THEN
18
        -- Copy parent's ancestors to this node's ancestors
19
        INSERT
20
        INTO taxonconcept_ancestor
21
        (taxonconcept_id, ancestor_id)
22
        SELECT
23
            new.taxonconcept_id, ancestor_id
24
        FROM taxonconcept_ancestor
25
        WHERE taxonconcept_id = new.parent_id
26
        ;
18
    IF parent_id_ IS DISTINCT FROM old_parent_id THEN
19
        DECLARE
20
            -- These include the parent itself
21
            old_ancestors integer[] := (
22
                SELECT array_agg(ancestor_id) FROM taxonconcept_ancestor
23
                WHERE taxonconcept_id = old_parent_id
24
            );
25
            new_ancestors integer[] := (
26
                SELECT array_agg(ancestor_id) FROM taxonconcept_ancestor
27
                WHERE taxonconcept_id = parent_id_
28
            );
29
            descendant_id integer;
30
        BEGIN
31
            FOR descendant_id IN -- also includes self
32
                SELECT taxonconcept_id
33
                FROM taxonconcept_ancestor
34
                WHERE ancestor_id = new.taxonconcept_id
35
            LOOP
36
                -- Delete old parent's ancestors
37
                DELETE FROM taxonconcept_ancestor
38
                WHERE taxonconcept_id = descendant_id
39
                AND ancestor_id = ANY (old_ancestors)
40
                ;
41
                
42
                -- Add new parent's ancestors
43
                INSERT INTO taxonconcept_ancestor
44
                (taxonconcept_id, ancestor_id)
45
                SELECT descendant_id, unnest(new_ancestors)
46
                ;
47
            END LOOP;
48
        END;
27 49
    END IF;
28 50
    
29
    -- Add "ancestor" for this node
30
    /* This is useful for queries, because you don't have to separately test if
31
    the leaf node is the one you're looking for, in addition to that leaf node's
32
    ancestors. */
51
    /* Note: We don't need an ON DELETE trigger to update the descendants'
52
    ancestors when a node is deleted, because the taxonconcept.parent_id foreign
53
    key is ON DELETE CASCADE, which just removes all the descendants anyway. */
54
END;
55
$BODY$
56
  LANGUAGE plpgsql VOLATILE
57
  COST 100;
58
ALTER FUNCTION taxonconcept_update_ancestors(taxonconcept, integer)
59
  OWNER TO bien;
60

  
61
-- Function: taxonconcept_update_ancestors_on_insert()
62

  
63
-- DROP FUNCTION taxonconcept_update_ancestors_on_insert();
64

  
65
CREATE OR REPLACE FUNCTION taxonconcept_update_ancestors_on_insert()
66
  RETURNS trigger AS
67
$BODY$
68
BEGIN
69
    /* Add "ancestor" for this node. This is useful for queries, because you
70
    don't have to separately test if the leaf node is the one you're looking
71
    for, in addition to that leaf node's ancestors. */
33 72
    INSERT
34 73
    INTO taxonconcept_ancestor
35 74
    (taxonconcept_id, ancestor_id)
36 75
    VALUES (new.taxonconcept_id, new.taxonconcept_id)
37 76
    ;
38 77
    
39
    -- Tell immediate children to update their ancestors lists, which will
40
    -- recursively tell all descendants
41
    UPDATE taxonconcept
42
    SET taxonconcept_id = taxonconcept_id -- need at least one SET statement
43
    -- Add COALESCE() to enable using taxonconcept_unique index for lookup
44
    WHERE COALESCE(parent_id, 2147483647) = new.taxonconcept_id
45
    AND taxonconcept_id != new.taxonconcept_id -- avoid infinite recursion
46
    ;
78
    PERFORM taxonconcept_update_ancestors(new);
47 79
    
48
    /* Note: We don't need an ON DELETE trigger to update the descendants'
49
    ancestors when a node is deleted, because the taxonconcept.parent_id foreign
50
    key is ON DELETE CASCADE, which just removes all the descendants anyway. */
80
    RETURN new;
81
END;
82
$BODY$
83
  LANGUAGE plpgsql VOLATILE
84
  COST 100;
85
ALTER FUNCTION taxonconcept_update_ancestors_on_insert()
86
  OWNER TO bien;
87

  
88
-- Function: taxonconcept_update_ancestors_on_update()
89

  
90
-- DROP FUNCTION taxonconcept_update_ancestors_on_update();
91

  
92
CREATE OR REPLACE FUNCTION taxonconcept_update_ancestors_on_update()
93
  RETURNS trigger AS
94
$BODY$
95
BEGIN
96
    PERFORM taxonconcept_update_ancestors(new,
97
        COALESCE(old.matched_concept_id, old.parent_id));
51 98
    
52 99
    RETURN new;
53 100
END;
54 101
$BODY$
55 102
  LANGUAGE plpgsql VOLATILE
56 103
  COST 100;
57
ALTER FUNCTION taxonconcept_update_ancestors()
104
ALTER FUNCTION taxonconcept_update_ancestors_on_update()
58 105
  OWNER TO bien;
59 106

  
60 107
----- Ancestors table
......
80 127
);
81 128
ALTER TABLE taxonconcept_ancestor
82 129
  OWNER TO bien;
130
COMMENT ON TABLE taxonconcept_ancestor
131
  IS 'Stores the accepted ancestors of a taxonconcept. Auto-populated, so should not be manually modified.';
83 132

  
84
----- Trigger
133
-- Index: taxonconcept_ancestor_descendants
85 134

  
86
-- Trigger: taxonconcept_update_ancestors on taxonconcept
135
-- DROP INDEX taxonconcept_ancestor_descendants;
87 136

  
88
-- DROP TRIGGER taxonconcept_update_ancestors ON taxonconcept;
137
CREATE INDEX taxonconcept_ancestor_descendants
138
  ON taxonconcept_ancestor
139
  USING btree
140
  (ancestor_id , taxonconcept_id );
89 141

  
90
CREATE TRIGGER taxonconcept_update_ancestors
91
  AFTER INSERT OR UPDATE
142

  
143
----- Triggers
144

  
145
-- Trigger: taxonconcept_update_ancestors_on_insert on taxonconcept
146

  
147
-- DROP TRIGGER taxonconcept_update_ancestors_on_insert ON taxonconcept;
148

  
149
CREATE TRIGGER taxonconcept_update_ancestors_on_insert
150
  AFTER INSERT
92 151
  ON taxonconcept
93 152
  FOR EACH ROW
94
  EXECUTE PROCEDURE taxonconcept_update_ancestors();
153
  EXECUTE PROCEDURE taxonconcept_update_ancestors_on_insert();
154

  
155
-- Trigger: taxonconcept_update_ancestors_on_update on taxonconcept
156

  
157
-- DROP TRIGGER taxonconcept_update_ancestors_on_update ON taxonconcept;
158

  
159
CREATE TRIGGER taxonconcept_update_ancestors_on_update
160
  AFTER UPDATE
161
  ON taxonconcept
162
  FOR EACH ROW
163
  EXECUTE PROCEDURE taxonconcept_update_ancestors_on_update();

Also available in: Unified diff