LP865817: Fix Located URI visibility test
[Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0631.schema.located_uri_visiblity_fix.sql
1 -- Evergreen DB patch 0631.schema.located_uri_visiblity_fix.sql
2 --
3 BEGIN;
4 -- check whether patch can be applied
5 SELECT evergreen.upgrade_deps_block_check('0631', :eg_version);
6
7 CREATE OR REPLACE FUNCTION search.query_parser_fts (
8
9     param_search_ou INT,
10     param_depth     INT,
11     param_query     TEXT,
12     param_statuses  INT[],
13     param_locations INT[],
14     param_offset    INT,
15     param_check     INT,
16     param_limit     INT,
17     metarecord      BOOL,
18     staff           BOOL
19  
20 ) RETURNS SETOF search.search_result AS $func$
21 DECLARE
22
23     current_res         search.search_result%ROWTYPE;
24     search_org_list     INT[];
25     luri_org_list       INT[];
26     tmp_int_list        INT[];
27
28     check_limit         INT;
29     core_limit          INT;
30     core_offset         INT;
31     tmp_int             INT;
32
33     core_result         RECORD;
34     core_cursor         REFCURSOR;
35     core_rel_query      TEXT;
36
37     total_count         INT := 0;
38     check_count         INT := 0;
39     deleted_count       INT := 0;
40     visible_count       INT := 0;
41     excluded_count      INT := 0;
42
43 BEGIN
44
45     check_limit := COALESCE( param_check, 1000 );
46     core_limit  := COALESCE( param_limit, 25000 );
47     core_offset := COALESCE( param_offset, 0 );
48
49     -- core_skip_chk := COALESCE( param_skip_chk, 1 );
50
51     IF param_search_ou > 0 THEN
52         IF param_depth IS NOT NULL THEN
53             SELECT array_accum(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou, param_depth );
54         ELSE
55             SELECT array_accum(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou );
56         END IF;
57
58         SELECT array_accum(distinct id) INTO luri_org_list FROM actor.org_unit_ancestors( param_search_ou );
59
60     ELSIF param_search_ou < 0 THEN
61         SELECT array_accum(distinct org_unit) INTO search_org_list FROM actor.org_lasso_map WHERE lasso = -param_search_ou;
62
63         FOR tmp_int IN SELECT * FROM UNNEST(search_org_list) LOOP
64             SELECT array_accum(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestors( tmp_int );
65             luri_org_list := luri_org_list || tmp_int_list;
66         END LOOP;
67
68         SELECT array_accum(DISTINCT x.id) INTO luri_org_list FROM UNNEST(luri_org_list) x(id);
69
70     ELSIF param_search_ou = 0 THEN
71         -- reserved for user lassos (ou_buckets/type='lasso') with ID passed in depth ... hack? sure.
72     END IF;
73
74     OPEN core_cursor FOR EXECUTE param_query;
75
76     LOOP
77
78         FETCH core_cursor INTO core_result;
79         EXIT WHEN NOT FOUND;
80         EXIT WHEN total_count >= core_limit;
81
82         total_count := total_count + 1;
83
84         CONTINUE WHEN total_count NOT BETWEEN  core_offset + 1 AND check_limit + core_offset;
85
86         check_count := check_count + 1;
87
88         PERFORM 1 FROM biblio.record_entry b WHERE NOT b.deleted AND b.id IN ( SELECT * FROM unnest( core_result.records ) );
89         IF NOT FOUND THEN
90             -- RAISE NOTICE ' % were all deleted ... ', core_result.records;
91             deleted_count := deleted_count + 1;
92             CONTINUE;
93         END IF;
94
95         PERFORM 1
96           FROM  biblio.record_entry b
97                 JOIN config.bib_source s ON (b.source = s.id)
98           WHERE s.transcendant
99                 AND b.id IN ( SELECT * FROM unnest( core_result.records ) );
100
101         IF FOUND THEN
102             -- RAISE NOTICE ' % were all transcendant ... ', core_result.records;
103             visible_count := visible_count + 1;
104
105             current_res.id = core_result.id;
106             current_res.rel = core_result.rel;
107
108             tmp_int := 1;
109             IF metarecord THEN
110                 SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
111             END IF;
112
113             IF tmp_int = 1 THEN
114                 current_res.record = core_result.records[1];
115             ELSE
116                 current_res.record = NULL;
117             END IF;
118
119             RETURN NEXT current_res;
120
121             CONTINUE;
122         END IF;
123
124         PERFORM 1
125           FROM  asset.call_number cn
126                 JOIN asset.uri_call_number_map map ON (map.call_number = cn.id)
127                 JOIN asset.uri uri ON (map.uri = uri.id)
128           WHERE NOT cn.deleted
129                 AND cn.label = '##URI##'
130                 AND uri.active
131                 AND ( param_locations IS NULL OR array_upper(param_locations, 1) IS NULL )
132                 AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
133                 AND cn.owning_lib IN ( SELECT * FROM unnest( luri_org_list ) )
134           LIMIT 1;
135
136         IF FOUND THEN
137             -- RAISE NOTICE ' % have at least one URI ... ', core_result.records;
138             visible_count := visible_count + 1;
139
140             current_res.id = core_result.id;
141             current_res.rel = core_result.rel;
142
143             tmp_int := 1;
144             IF metarecord THEN
145                 SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
146             END IF;
147
148             IF tmp_int = 1 THEN
149                 current_res.record = core_result.records[1];
150             ELSE
151                 current_res.record = NULL;
152             END IF;
153
154             RETURN NEXT current_res;
155
156             CONTINUE;
157         END IF;
158
159         IF param_statuses IS NOT NULL AND array_upper(param_statuses, 1) > 0 THEN
160
161             PERFORM 1
162               FROM  asset.call_number cn
163                     JOIN asset.copy cp ON (cp.call_number = cn.id)
164               WHERE NOT cn.deleted
165                     AND NOT cp.deleted
166                     AND cp.status IN ( SELECT * FROM unnest( param_statuses ) )
167                     AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
168                     AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
169               LIMIT 1;
170
171             IF NOT FOUND THEN
172                 PERFORM 1
173                   FROM  biblio.peer_bib_copy_map pr
174                         JOIN asset.copy cp ON (cp.id = pr.target_copy)
175                   WHERE NOT cp.deleted
176                         AND cp.status IN ( SELECT * FROM unnest( param_statuses ) )
177                         AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
178                         AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
179                   LIMIT 1;
180
181                 IF NOT FOUND THEN
182                 -- RAISE NOTICE ' % and multi-home linked records were all status-excluded ... ', core_result.records;
183                     excluded_count := excluded_count + 1;
184                     CONTINUE;
185                 END IF;
186             END IF;
187
188         END IF;
189
190         IF param_locations IS NOT NULL AND array_upper(param_locations, 1) > 0 THEN
191
192             PERFORM 1
193               FROM  asset.call_number cn
194                     JOIN asset.copy cp ON (cp.call_number = cn.id)
195               WHERE NOT cn.deleted
196                     AND NOT cp.deleted
197                     AND cp.location IN ( SELECT * FROM unnest( param_locations ) )
198                     AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
199                     AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
200               LIMIT 1;
201
202             IF NOT FOUND THEN
203                 PERFORM 1
204                   FROM  biblio.peer_bib_copy_map pr
205                         JOIN asset.copy cp ON (cp.id = pr.target_copy)
206                   WHERE NOT cp.deleted
207                         AND cp.location IN ( SELECT * FROM unnest( param_locations ) )
208                         AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
209                         AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
210                   LIMIT 1;
211
212                 IF NOT FOUND THEN
213                     -- RAISE NOTICE ' % and multi-home linked records were all copy_location-excluded ... ', core_result.records;
214                     excluded_count := excluded_count + 1;
215                     CONTINUE;
216                 END IF;
217             END IF;
218
219         END IF;
220
221         IF staff IS NULL OR NOT staff THEN
222
223             PERFORM 1
224               FROM  asset.opac_visible_copies
225               WHERE circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
226                     AND record IN ( SELECT * FROM unnest( core_result.records ) )
227               LIMIT 1;
228
229             IF NOT FOUND THEN
230                 PERFORM 1
231                   FROM  biblio.peer_bib_copy_map pr
232                         JOIN asset.opac_visible_copies cp ON (cp.copy_id = pr.target_copy)
233                   WHERE cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
234                         AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
235                   LIMIT 1;
236
237                 IF NOT FOUND THEN
238
239                     -- RAISE NOTICE ' % and multi-home linked records were all visibility-excluded ... ', core_result.records;
240                     excluded_count := excluded_count + 1;
241                     CONTINUE;
242                 END IF;
243             END IF;
244
245         ELSE
246
247             PERFORM 1
248               FROM  asset.call_number cn
249                     JOIN asset.copy cp ON (cp.call_number = cn.id)
250               WHERE NOT cn.deleted
251                     AND NOT cp.deleted
252                     AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
253                     AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
254               LIMIT 1;
255
256             IF NOT FOUND THEN
257
258                 PERFORM 1
259                   FROM  biblio.peer_bib_copy_map pr
260                         JOIN asset.copy cp ON (cp.id = pr.target_copy)
261                   WHERE NOT cp.deleted
262                         AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
263                         AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
264                   LIMIT 1;
265
266                 IF NOT FOUND THEN
267
268                     PERFORM 1
269                       FROM  asset.call_number cn
270                             JOIN asset.copy cp ON (cp.call_number = cn.id)
271                       WHERE cn.record IN ( SELECT * FROM unnest( core_result.records ) )
272                             AND NOT cp.deleted
273                       LIMIT 1;
274
275                     IF FOUND THEN
276                         -- RAISE NOTICE ' % and multi-home linked records were all visibility-excluded ... ', core_result.records;
277                         excluded_count := excluded_count + 1;
278                         CONTINUE;
279                     END IF;
280                 END IF;
281
282             END IF;
283
284         END IF;
285
286         visible_count := visible_count + 1;
287
288         current_res.id = core_result.id;
289         current_res.rel = core_result.rel;
290
291         tmp_int := 1;
292         IF metarecord THEN
293             SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
294         END IF;
295
296         IF tmp_int = 1 THEN
297             current_res.record = core_result.records[1];
298         ELSE
299             current_res.record = NULL;
300         END IF;
301
302         RETURN NEXT current_res;
303
304         IF visible_count % 1000 = 0 THEN
305             -- RAISE NOTICE ' % visible so far ... ', visible_count;
306         END IF;
307
308     END LOOP;
309
310     current_res.id = NULL;
311     current_res.rel = NULL;
312     current_res.record = NULL;
313     current_res.total = total_count;
314     current_res.checked = check_count;
315     current_res.deleted = deleted_count;
316     current_res.visible = visible_count;
317     current_res.excluded = excluded_count;
318
319     CLOSE core_cursor;
320
321     RETURN NEXT current_res;
322
323 END;
324 $func$ LANGUAGE PLPGSQL;
325
326 COMMIT;