]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/XXXX.function.metabib.staged_browse.sql
LP#1358392: See references not always displaying on browse search
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / XXXX.function.metabib.staged_browse.sql
1 BEGIN;
2
3 CREATE OR REPLACE FUNCTION metabib.staged_browse(query text, fields integer[], context_org integer, context_locations integer[], staff boolean, browse_superpage_size integer, count_up_from_zero boolean, result_limit integer, next_pivot_pos integer)
4  RETURNS SETOF metabib.flat_browse_entry_appearance
5 AS $f$
6 DECLARE
7     curs                    REFCURSOR;
8     rec                     RECORD;
9     qpfts_query             TEXT;
10     aqpfts_query            TEXT;
11     afields                 INT[];
12     bfields                 INT[];
13     result_row              metabib.flat_browse_entry_appearance%ROWTYPE;
14     results_skipped         INT := 0;
15     row_counter             INT := 0;
16     row_number              INT;
17     slice_start             INT;
18     slice_end               INT;
19     full_end                INT;
20     all_records             BIGINT[];
21     all_brecords             BIGINT[];
22     all_arecords            BIGINT[];
23     superpage_of_records    BIGINT[];
24     superpage_size          INT;
25     c_tests                 TEXT := '';
26     b_tests                 TEXT := '';
27     c_orgs                  INT[];
28     unauthorized_entry      RECORD;
29 BEGIN
30     IF count_up_from_zero THEN
31         row_number := 0;
32     ELSE
33         row_number := -1;
34     END IF;
35
36     IF NOT staff THEN
37         SELECT x.c_attrs, x.b_attrs INTO c_tests, b_tests FROM asset.patron_default_visibility_mask() x;
38     END IF;
39
40     IF c_tests <> '' THEN c_tests := c_tests || '&'; END IF;
41     IF b_tests <> '' THEN b_tests := b_tests || '&'; END IF;
42
43     SELECT ARRAY_AGG(id) INTO c_orgs FROM actor.org_unit_descendants(context_org);
44
45     c_tests := c_tests || search.calculate_visibility_attribute_test('circ_lib',c_orgs)
46                || '&' || search.calculate_visibility_attribute_test('owning_lib',c_orgs);
47
48     PERFORM 1 FROM config.internal_flag WHERE enabled AND name = 'opac.located_uri.act_as_copy';
49     IF FOUND THEN
50         b_tests := b_tests || search.calculate_visibility_attribute_test(
51             'luri_org',
52             (SELECT ARRAY_AGG(id) FROM actor.org_unit_full_path(context_org) x)
53         );
54     ELSE
55         b_tests := b_tests || search.calculate_visibility_attribute_test(
56             'luri_org',
57             (SELECT ARRAY_AGG(id) FROM actor.org_unit_ancestors(context_org) x)
58         );
59     END IF;
60
61     IF context_locations THEN
62         IF c_tests <> '' THEN c_tests := c_tests || '&'; END IF;
63         c_tests := c_tests || search.calculate_visibility_attribute_test('location',context_locations);
64     END IF;
65
66     OPEN curs NO SCROLL FOR EXECUTE query;
67
68     LOOP
69         FETCH curs INTO rec;
70         IF NOT FOUND THEN
71             IF result_row.pivot_point IS NOT NULL THEN
72                 RETURN NEXT result_row;
73             END IF;
74             RETURN;
75         END IF;
76
77         --Is unauthorized?
78         SELECT INTO unauthorized_entry *
79         FROM metabib.browse_entry_simple_heading_map mbeshm
80         INNER JOIN authority.simple_heading ash ON ( mbeshm.simple_heading = ash.id )
81         INNER JOIN authority.control_set_authority_field acsaf ON ( acsaf.id = ash.atag AND acsaf.tag like '4__')
82         WHERE mbeshm.entry = rec.id;
83
84         -- Gather aggregate data based on the MBE row we're looking at now, authority axis
85         IF (unauthorized_entry.record IS NOT NULL) THEN
86             --unauthorized term belongs to an auth linked to a bib?
87             SELECT INTO all_arecords, result_row.sees, afields
88                     ARRAY_AGG(DISTINCT abl.bib),
89                     STRING_AGG(DISTINCT abl.authority::TEXT, $$,$$),
90                     ARRAY_AGG(DISTINCT map.metabib_field)
91             FROM authority.bib_linking abl
92             INNER JOIN authority.control_set_auth_field_metabib_field_map_refs map ON (
93                     map.authority_field = unauthorized_entry.atag
94                     AND map.metabib_field = ANY(fields)
95             )
96             WHERE abl.authority = unauthorized_entry.record;
97         ELSE
98             --do usual procedure
99             SELECT INTO all_arecords, result_row.sees, afields
100                     ARRAY_AGG(DISTINCT abl.bib), -- bibs to check for visibility
101                     STRING_AGG(DISTINCT aal.source::TEXT, $$,$$), -- authority record ids
102                     ARRAY_AGG(DISTINCT map.metabib_field) -- authority-tag-linked CMF rows
103
104             FROM  metabib.browse_entry_simple_heading_map mbeshm
105                     JOIN authority.simple_heading ash ON ( mbeshm.simple_heading = ash.id )
106                     JOIN authority.authority_linking aal ON ( ash.record = aal.source )
107                     JOIN authority.bib_linking abl ON ( aal.target = abl.authority )
108                     JOIN authority.control_set_auth_field_metabib_field_map_refs map ON (
109                         ash.atag = map.authority_field
110                         AND map.metabib_field = ANY(fields)
111                     )
112             WHERE mbeshm.entry = rec.id;
113
114         END IF;
115
116         -- Gather aggregate data based on the MBE row we're looking at now, bib axis
117         SELECT INTO all_brecords, result_row.authorities, bfields
118                 ARRAY_AGG(DISTINCT source),
119                 STRING_AGG(DISTINCT authority::TEXT, $$,$$),
120                 ARRAY_AGG(DISTINCT def)
121           FROM  metabib.browse_entry_def_map
122           WHERE entry = rec.id
123                 AND def = ANY(fields);
124
125         SELECT INTO result_row.fields STRING_AGG(DISTINCT x::TEXT, $$,$$) FROM UNNEST(afields || bfields) x;
126
127         result_row.sources := 0;
128         result_row.asources := 0;
129
130         -- Bib-linked vis checking
131         IF ARRAY_UPPER(all_brecords,1) IS NOT NULL THEN
132
133             SELECT  INTO result_row.sources COUNT(DISTINCT b.id)
134               FROM  biblio.record_entry b
135                     JOIN asset.copy_vis_attr_cache acvac ON (acvac.record = b.id)
136               WHERE b.id = ANY(all_brecords[1:browse_superpage_size])
137                     AND (
138                         acvac.vis_attr_vector @@ c_tests::query_int
139                         OR b.vis_attr_vector @@ b_tests::query_int
140                     );
141
142             result_row.accurate := TRUE;
143
144         END IF;
145
146         -- Authority-linked vis checking
147         IF ARRAY_UPPER(all_arecords,1) IS NOT NULL THEN
148
149             SELECT  INTO result_row.asources COUNT(DISTINCT b.id)
150               FROM  biblio.record_entry b
151                     JOIN asset.copy_vis_attr_cache acvac ON (acvac.record = b.id)
152               WHERE b.id = ANY(all_arecords[1:browse_superpage_size])
153                     AND (
154                         acvac.vis_attr_vector @@ c_tests::query_int
155                         OR b.vis_attr_vector @@ b_tests::query_int
156                     );
157
158             result_row.aaccurate := TRUE;
159
160         END IF;
161
162         IF result_row.sources > 0 OR result_row.asources > 0 THEN
163
164             -- The function that calls this function needs row_number in order
165             -- to correctly order results from two different runs of this
166             -- functions.
167             result_row.row_number := row_number;
168
169             -- Now, if row_counter is still less than limit, return a row.  If
170             -- not, but it is less than next_pivot_pos, continue on without
171             -- returning actual result rows until we find
172             -- that next pivot, and return it.
173
174             IF row_counter < result_limit THEN
175                 result_row.browse_entry := rec.id;
176                 result_row.value := rec.value;
177
178                 RETURN NEXT result_row;
179             ELSE
180                 result_row.browse_entry := NULL;
181                 result_row.authorities := NULL;
182                 result_row.fields := NULL;
183                 result_row.value := NULL;
184                 result_row.sources := NULL;
185                 result_row.sees := NULL;
186                 result_row.accurate := NULL;
187                 result_row.aaccurate := NULL;
188                 result_row.pivot_point := rec.id;
189
190                 IF row_counter >= next_pivot_pos THEN
191                     RETURN NEXT result_row;
192                     RETURN;
193                 END IF;
194             END IF;
195
196             IF count_up_from_zero THEN
197                 row_number := row_number + 1;
198             ELSE
199                 row_number := row_number - 1;
200             END IF;
201
202             -- row_counter is different from row_number.
203             -- It simply counts up from zero so that we know when
204             -- we've reached our limit.
205             row_counter := row_counter + 1;
206         END IF;
207     END LOOP;
208 END;
209 $f$ LANGUAGE plpgsql ROWS 10;
210
211 COMMIT;