LP#837566 undeleting a bib record causes an error
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / XXXX.schema.cache_visibility_and_peer_records.sql
1 CREATE OR REPLACE FUNCTION asset.cache_copy_visibility () RETURNS TRIGGER as $func$
2 DECLARE
3     add_front       TEXT;
4     add_back        TEXT;
5     add_base_query  TEXT;
6     add_peer_query  TEXT;
7     remove_query    TEXT;
8     do_add          BOOLEAN := false;
9     do_remove       BOOLEAN := false;
10 BEGIN
11     add_base_query := $$
12         SELECT  cp.id, cp.circ_lib, cn.record, cn.id AS call_number, cp.location, cp.status
13           FROM  asset.copy cp
14                 JOIN asset.call_number cn ON (cn.id = cp.call_number)
15                 JOIN actor.org_unit a ON (cp.circ_lib = a.id)
16                 JOIN asset.copy_location cl ON (cp.location = cl.id)
17                 JOIN config.copy_status cs ON (cp.status = cs.id)
18                 JOIN biblio.record_entry b ON (cn.record = b.id)
19           WHERE NOT cp.deleted
20                 AND NOT cn.deleted
21                 AND NOT b.deleted
22                 AND cs.opac_visible
23                 AND cl.opac_visible
24                 AND cp.opac_visible
25                 AND a.opac_visible
26     $$;
27     add_peer_query := $$
28         SELECT  cp.id, cp.circ_lib, pbcm.peer_record AS record, NULL AS call_number, cp.location, cp.status
29           FROM  asset.copy cp
30                 JOIN biblio.peer_bib_copy_map pbcm ON (pbcm.target_copy = cp.id)
31                 JOIN actor.org_unit a ON (cp.circ_lib = a.id)
32                 JOIN asset.copy_location cl ON (cp.location = cl.id)
33                 JOIN config.copy_status cs ON (cp.status = cs.id)
34           WHERE NOT cp.deleted
35                 AND cs.opac_visible
36                 AND cl.opac_visible
37                 AND cp.opac_visible
38                 AND a.opac_visible
39     $$;
40     add_front := $$
41         INSERT INTO asset.opac_visible_copies (copy_id, circ_lib, record)
42           SELECT id, circ_lib, record FROM (
43     $$;
44     add_back := $$
45         ) AS x
46     $$;
47  
48     remove_query := $$ DELETE FROM asset.opac_visible_copies WHERE copy_id IN ( SELECT id FROM asset.copy WHERE $$;
49
50     IF TG_TABLE_NAME = 'peer_bib_copy_map' THEN
51         IF TG_OP = 'INSERT' THEN
52             add_peer_query := add_peer_query || ' AND cp.id = ' || NEW.target_copy || ' AND pbcm.peer_record = ' || NEW.peer_record;
53             EXECUTE add_front || add_peer_query || add_back;
54             RETURN NEW;
55         ELSE
56             remove_query := 'DELETE FROM asset.opac_visible_copies WHERE copy_id = ' || OLD.target_copy || ' AND record = ' || OLD.peer_record || ';';
57             EXECUTE remove_query;
58             RETURN OLD;
59         END IF;
60     END IF;
61
62     IF TG_OP = 'INSERT' THEN
63
64         IF TG_TABLE_NAME IN ('copy', 'unit') THEN
65             add_base_query := add_base_query || ' AND cp.id = ' || NEW.id;
66             EXECUTE add_front || add_base_query || add_back;
67         END IF;
68
69         RETURN NEW;
70
71     END IF;
72
73     -- handle items first, since with circulation activity
74     -- their statuses change frequently
75     IF TG_TABLE_NAME IN ('copy', 'unit') THEN
76
77         IF OLD.location    <> NEW.location OR
78            OLD.call_number <> NEW.call_number OR
79            OLD.status      <> NEW.status OR
80            OLD.circ_lib    <> NEW.circ_lib THEN
81             -- any of these could change visibility, but
82             -- we'll save some queries and not try to calculate
83             -- the change directly
84             do_remove := true;
85             do_add := true;
86         ELSE
87
88             IF OLD.deleted <> NEW.deleted THEN
89                 IF NEW.deleted THEN
90                     do_remove := true;
91                 ELSE
92                     do_add := true;
93                 END IF;
94             END IF;
95
96             IF OLD.opac_visible <> NEW.opac_visible THEN
97                 IF OLD.opac_visible THEN
98                     do_remove := true;
99                 ELSIF NOT do_remove THEN -- handle edge case where deleted item
100                                         -- is also marked opac_visible
101                     do_add := true;
102                 END IF;
103             END IF;
104
105         END IF;
106
107         IF do_remove THEN
108             DELETE FROM asset.opac_visible_copies WHERE copy_id = NEW.id;
109         END IF;
110         IF do_add THEN
111             add_base_query := add_base_query || ' AND cp.id = ' || NEW.id;
112             add_peer_query := add_peer_query || ' AND cp.id = ' || NEW.id;
113             EXECUTE add_front || add_base_query || ' UNION ' || add_peer_query || add_back;
114         END IF;
115
116         RETURN NEW;
117
118     END IF;
119
120     IF TG_TABLE_NAME IN ('call_number', 'record_entry') THEN -- these have a 'deleted' column
121  
122         IF OLD.deleted AND NEW.deleted THEN -- do nothing
123
124             RETURN NEW;
125  
126         ELSIF NEW.deleted THEN -- remove rows
127  
128             IF TG_TABLE_NAME = 'call_number' THEN
129                 DELETE FROM asset.opac_visible_copies WHERE copy_id IN (SELECT id FROM asset.copy WHERE call_number = NEW.id);
130             ELSIF TG_TABLE_NAME = 'record_entry' THEN
131                 DELETE FROM asset.opac_visible_copies WHERE record = NEW.id;
132             END IF;
133  
134             RETURN NEW;
135  
136         ELSIF OLD.deleted THEN -- add rows
137  
138             IF TG_TABLE_NAME = 'call_number' THEN
139                 add_base_query := add_base_query || ' AND cn.id = ' || NEW.id;
140                 EXECUTE add_front || add_base_query || add_back;
141             ELSIF TG_TABLE_NAME = 'record_entry' THEN
142                 add_base_query := add_base_query || ' AND cn.record = ' || NEW.id;
143                 add_peer_query := add_peer_query || ' AND pbcm.peer_record = ' || NEW.id;
144                 EXECUTE add_front || add_base_query || ' UNION ' || add_peer_query || add_back;
145             END IF;
146  
147             RETURN NEW;
148  
149         END IF;
150  
151     END IF;
152
153     IF TG_TABLE_NAME = 'call_number' THEN
154
155         IF OLD.record <> NEW.record THEN
156             -- call number is linked to different bib
157             remove_query := remove_query || 'call_number = ' || NEW.id || ');';
158             EXECUTE remove_query;
159             add_base_query := add_base_query || ' AND cn.id = ' || NEW.id;
160             EXECUTE add_front || add_base_query || add_back;
161         END IF;
162
163         RETURN NEW;
164
165     END IF;
166
167     IF TG_TABLE_NAME IN ('record_entry') THEN
168         RETURN NEW; -- don't have 'opac_visible'
169     END IF;
170
171     -- actor.org_unit, asset.copy_location, asset.copy_status
172     IF NEW.opac_visible = OLD.opac_visible THEN -- do nothing
173
174         RETURN NEW;
175
176     ELSIF NEW.opac_visible THEN -- add rows
177
178         IF TG_TABLE_NAME = 'org_unit' THEN
179             add_base_query := add_base_query || ' AND cp.circ_lib = ' || NEW.id;
180             add_peer_query := add_peer_query || ' AND cp.circ_lib = ' || NEW.id;
181         ELSIF TG_TABLE_NAME = 'copy_location' THEN
182             add_base_query := add_base_query || ' AND cp.location = ' || NEW.id;
183             add_peer_query := add_peer_query || ' AND cp.location = ' || NEW.id;
184         ELSIF TG_TABLE_NAME = 'copy_status' THEN
185             add_base_query := add_base_query || ' AND cp.status = ' || NEW.id;
186             add_peer_query := add_peer_query || ' AND cp.status = ' || NEW.id;
187         END IF;
188  
189         EXECUTE add_front || add_base_query || ' UNION ' || add_peer_query || add_back;
190  
191     ELSE -- delete rows
192
193         IF TG_TABLE_NAME = 'org_unit' THEN
194             remove_query := 'DELETE FROM asset.opac_visible_copies WHERE circ_lib = ' || NEW.id || ';';
195         ELSIF TG_TABLE_NAME = 'copy_location' THEN
196             remove_query := remove_query || 'location = ' || NEW.id || ');';
197         ELSIF TG_TABLE_NAME = 'copy_status' THEN
198             remove_query := remove_query || 'status = ' || NEW.id || ');';
199         END IF;
200  
201         EXECUTE remove_query;
202  
203     END IF;
204  
205     RETURN NEW;
206 END;
207 $func$ LANGUAGE PLPGSQL;