834202bc42428d301f098a84dbb3b6722850244e
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 1085.function.luri_vis_cache.sql
1 BEGIN;
2
3 SELECT evergreen.upgrade_deps_block_check('1085', :eg_version);
4
5 CREATE OR REPLACE FUNCTION asset.calculate_copy_visibility_attribute_set ( copy_id BIGINT ) RETURNS INT[] AS $f$
6 DECLARE
7     copy_row    asset.copy%ROWTYPE;
8     lgroup_map  asset.copy_location_group_map%ROWTYPE;
9     attr_set    INT[] := '{}'::INT[];
10 BEGIN
11     SELECT * INTO copy_row FROM asset.copy WHERE id = copy_id;
12
13     attr_set := attr_set || search.calculate_visibility_attribute(copy_row.opac_visible::INT, 'copy_flags');
14     attr_set := attr_set || search.calculate_visibility_attribute(copy_row.circ_lib, 'circ_lib');
15     attr_set := attr_set || search.calculate_visibility_attribute(copy_row.status, 'status');
16     attr_set := attr_set || search.calculate_visibility_attribute(copy_row.location, 'location');
17
18     SELECT  ARRAY_APPEND(
19                 attr_set,
20                 search.calculate_visibility_attribute(owning_lib, 'owning_lib')
21             ) INTO attr_set
22       FROM  asset.call_number
23       WHERE id = copy_row.call_number;
24
25     FOR lgroup_map IN SELECT * FROM asset.copy_location_group_map WHERE location = copy_row.location LOOP
26         attr_set := attr_set || search.calculate_visibility_attribute(lgroup_map.lgroup, 'location_group');
27     END LOOP;
28
29     RETURN attr_set;
30 END;
31 $f$ LANGUAGE PLPGSQL;
32
33 DROP FUNCTION IF EXISTS biblio.calculate_bib_visibility_attribute_set ( BIGINT );
34 CREATE OR REPLACE FUNCTION biblio.calculate_bib_visibility_attribute_set ( bib_id BIGINT, new_source INT DEFAULT NULL, force_source BOOL DEFAULT FALSE ) RETURNS INT[] AS $f$
35 DECLARE
36     bib_row     biblio.record_entry%ROWTYPE;
37     cn_row      asset.call_number%ROWTYPE;
38     attr_set    INT[] := '{}'::INT[];
39 BEGIN
40     SELECT * INTO bib_row FROM biblio.record_entry WHERE id = bib_id;
41
42     IF force_source THEN
43         IF new_source IS NOT NULL THEN
44             attr_set := attr_set || search.calculate_visibility_attribute(new_source, 'bib_source');
45         END IF;
46     ELSIF bib_row.source IS NOT NULL THEN
47         attr_set := attr_set || search.calculate_visibility_attribute(bib_row.source, 'bib_source');
48     END IF;
49
50     FOR cn_row IN
51         SELECT  *
52           FROM  asset.call_number
53           WHERE record = bib_id
54                 AND label = '##URI##'
55                 AND NOT deleted
56     LOOP
57         attr_set := attr_set || search.calculate_visibility_attribute(cn_row.owning_lib, 'luri_org');
58     END LOOP;
59
60     RETURN attr_set;
61 END;
62 $f$ LANGUAGE PLPGSQL;
63
64 CREATE OR REPLACE FUNCTION asset.cache_copy_visibility () RETURNS TRIGGER as $func$
65 DECLARE
66     ocn     asset.call_number%ROWTYPE;
67     ncn     asset.call_number%ROWTYPE;
68     cid     BIGINT;
69     dobib   BOOL;
70 BEGIN
71
72     SELECT enabled = FALSE INTO dobib FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc';
73
74     IF TG_TABLE_NAME = 'peer_bib_copy_map' THEN -- Only needs ON INSERT OR DELETE, so handle separately
75         IF TG_OP = 'INSERT' THEN
76             INSERT INTO asset.copy_vis_attr_cache (record, target_copy, vis_attr_vector) VALUES (
77                 NEW.peer_record,
78                 NEW.target_copy,
79                 asset.calculate_copy_visibility_attribute_set(NEW.target_copy)
80             );
81
82             RETURN NEW;
83         ELSIF TG_OP = 'DELETE' THEN
84             DELETE FROM asset.copy_vis_attr_cache
85               WHERE record = OLD.peer_record AND target_copy = OLD.target_copy;
86
87             RETURN OLD;
88         END IF;
89     END IF;
90
91     IF TG_OP = 'INSERT' THEN -- Handles ON INSERT. ON UPDATE is below.
92         IF TG_TABLE_NAME IN ('copy', 'unit') THEN
93             SELECT * INTO ncn FROM asset.call_number cn WHERE id = NEW.call_number;
94             INSERT INTO asset.copy_vis_attr_cache (record, target_copy, vis_attr_vector) VALUES (
95                 ncn.record,
96                 NEW.id,
97                 asset.calculate_copy_visibility_attribute_set(NEW.id)
98             );
99         ELSIF TG_TABLE_NAME = 'record_entry' THEN
100             NEW.vis_attr_vector := biblio.calculate_bib_visibility_attribute_set(NEW.id, NEW.source, TRUE);
101         ELSIF TG_TABLE_NAME = 'call_number' AND NEW.label = '##URI##' AND dobib THEN -- New located URI
102             UPDATE  biblio.record_entry
103               SET   vis_attr_vector = biblio.calculate_bib_visibility_attribute_set(NEW.record)
104               WHERE id = NEW.record;
105
106         END IF;
107
108         RETURN NEW;
109     END IF;
110
111     -- handle items first, since with circulation activity
112     -- their statuses change frequently
113     IF TG_TABLE_NAME IN ('copy', 'unit') THEN -- This handles ON UPDATE OR DELETE. ON INSERT above
114
115         IF TG_OP = 'DELETE' THEN -- Shouldn't get here, normally
116             DELETE FROM asset.copy_vis_attr_cache WHERE target_copy = OLD.id;
117             RETURN OLD;
118         END IF;
119
120         SELECT * INTO ncn FROM asset.call_number cn WHERE id = NEW.call_number;
121
122         IF OLD.deleted <> NEW.deleted THEN
123             IF NEW.deleted THEN
124                 DELETE FROM asset.copy_vis_attr_cache WHERE target_copy = OLD.id;
125             ELSE
126                 INSERT INTO asset.copy_vis_attr_cache (record, target_copy, vis_attr_vector) VALUES (
127                     ncn.record,
128                     NEW.id,
129                     asset.calculate_copy_visibility_attribute_set(NEW.id)
130                 );
131             END IF;
132
133             RETURN NEW;
134         ELSIF OLD.location   <> NEW.location OR
135             OLD.status       <> NEW.status OR
136             OLD.opac_visible <> NEW.opac_visible OR
137             OLD.circ_lib     <> NEW.circ_lib OR
138             OLD.call_number  <> NEW.call_number
139         THEN
140             IF OLD.call_number  <> NEW.call_number THEN -- Special check since it's more expensive than the next branch
141                 SELECT * INTO ocn FROM asset.call_number cn WHERE id = OLD.call_number;
142
143                 IF ncn.record <> ocn.record THEN
144                     -- We have to use a record-specific WHERE clause
145                     -- to avoid modifying the entries for peer-bib copies.
146                     UPDATE  asset.copy_vis_attr_cache
147                       SET   target_copy = NEW.id,
148                             record = ncn.record
149                       WHERE target_copy = OLD.id
150                             AND record = ocn.record;
151
152                 END IF;
153             ELSE
154                 -- Any of these could change visibility, but
155                 -- we'll save some queries and not try to calculate
156                 -- the change directly.  We want to update peer-bib
157                 -- entries in this case, unlike above.
158                 UPDATE  asset.copy_vis_attr_cache
159                   SET   target_copy = NEW.id,
160                         vis_attr_vector = asset.calculate_copy_visibility_attribute_set(NEW.id)
161                   WHERE target_copy = OLD.id;
162             END IF;
163         END IF;
164
165     ELSIF TG_TABLE_NAME = 'call_number' THEN
166
167         IF TG_OP = 'DELETE' AND OLD.label = '##URI##' AND dobib THEN -- really deleted located URI, if the delete protection rule is disabled...
168             UPDATE  biblio.record_entry
169               SET   vis_attr_vector = biblio.calculate_bib_visibility_attribute_set(OLD.record)
170               WHERE id = OLD.record;
171             RETURN OLD;
172         END IF;
173
174         IF OLD.label = '##URI##' AND dobib THEN -- Located URI
175             IF OLD.deleted <> NEW.deleted OR OLD.record <> NEW.record OR OLD.owning_lib <> NEW.owning_lib THEN
176                 UPDATE  biblio.record_entry
177                   SET   vis_attr_vector = biblio.calculate_bib_visibility_attribute_set(NEW.record)
178                   WHERE id = NEW.record;
179
180                 IF OLD.record <> NEW.record THEN -- maybe on merge?
181                     UPDATE  biblio.record_entry
182                       SET   vis_attr_vector = biblio.calculate_bib_visibility_attribute_set(OLD.record)
183                       WHERE id = OLD.record;
184                 END IF;
185             END IF;
186
187         ELSIF OLD.record <> NEW.record OR OLD.owning_lib <> NEW.owning_lib THEN
188             UPDATE  asset.copy_vis_attr_cache
189               SET   record = NEW.record,
190                     vis_attr_vector = asset.calculate_copy_visibility_attribute_set(target_copy)
191               WHERE target_copy IN (SELECT id FROM asset.copy WHERE call_number = NEW.id)
192                     AND record = OLD.record;
193
194         END IF;
195
196     ELSIF TG_TABLE_NAME = 'record_entry' AND OLD.source IS DISTINCT FROM NEW.source THEN -- Only handles ON UPDATE, INSERT above
197         NEW.vis_attr_vector := biblio.calculate_bib_visibility_attribute_set(NEW.id, NEW.source, TRUE);
198     END IF;
199
200     RETURN NEW;
201 END;
202 $func$ LANGUAGE PLPGSQL;
203
204 DROP TRIGGER z_opac_vis_mat_view_tgr ON asset.call_number;
205 DROP TRIGGER z_opac_vis_mat_view_tgr ON biblio.record_entry;
206 CREATE TRIGGER z_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE OR DELETE ON asset.call_number FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
207 CREATE TRIGGER z_opac_vis_mat_view_tgr BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
208
209 COMMIT;
210
211 UPDATE  biblio.record_entry
212   SET   vis_attr_vector = biblio.calculate_bib_visibility_attribute_set(id)
213   WHERE id IN (
214             SELECT  DISTINCT cn.record
215               FROM  asset.call_number cn
216               WHERE NOT cn.deleted
217                     AND cn.label = '##URI##'
218                     AND EXISTS (
219                         SELECT  1
220                           FROM  asset.uri_call_number_map m
221                           WHERE m.call_number = cn.id
222                     )
223                 UNION
224             SELECT id FROM biblio.record_entry WHERE source IS NOT NULL
225         );
226