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