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