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