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
13 result_row metabib.flat_browse_entry_appearance%ROWTYPE;
14 results_skipped INT := 0;
21 all_brecords BIGINT[];
22 all_arecords BIGINT[];
23 superpage_of_records BIGINT[];
28 unauthorized_entry RECORD;
30 IF count_up_from_zero THEN
37 SELECT x.c_attrs, x.b_attrs INTO c_tests, b_tests FROM asset.patron_default_visibility_mask() x;
40 IF c_tests <> '' THEN c_tests := c_tests || '&'; END IF;
41 IF b_tests <> '' THEN b_tests := b_tests || '&'; END IF;
43 SELECT ARRAY_AGG(id) INTO c_orgs FROM actor.org_unit_descendants(context_org);
45 c_tests := c_tests || search.calculate_visibility_attribute_test('circ_lib',c_orgs)
46 || '&' || search.calculate_visibility_attribute_test('owning_lib',c_orgs);
48 PERFORM 1 FROM config.internal_flag WHERE enabled AND name = 'opac.located_uri.act_as_copy';
50 b_tests := b_tests || search.calculate_visibility_attribute_test(
52 (SELECT ARRAY_AGG(id) FROM actor.org_unit_full_path(context_org) x)
55 b_tests := b_tests || search.calculate_visibility_attribute_test(
57 (SELECT ARRAY_AGG(id) FROM actor.org_unit_ancestors(context_org) x)
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);
66 OPEN curs NO SCROLL FOR EXECUTE query;
71 IF result_row.pivot_point IS NOT NULL THEN
72 RETURN NEXT result_row;
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;
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)
96 WHERE abl.authority = unauthorized_entry.record;
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
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)
112 WHERE mbeshm.entry = rec.id;
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
123 AND def = ANY(fields);
125 SELECT INTO result_row.fields STRING_AGG(DISTINCT x::TEXT, $$,$$) FROM UNNEST(afields || bfields) x;
127 result_row.sources := 0;
128 result_row.asources := 0;
130 -- Bib-linked vis checking
131 IF ARRAY_UPPER(all_brecords,1) IS NOT NULL THEN
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])
138 acvac.vis_attr_vector @@ c_tests::query_int
139 OR b.vis_attr_vector @@ b_tests::query_int
142 result_row.accurate := TRUE;
146 -- Authority-linked vis checking
147 IF ARRAY_UPPER(all_arecords,1) IS NOT NULL THEN
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])
154 acvac.vis_attr_vector @@ c_tests::query_int
155 OR b.vis_attr_vector @@ b_tests::query_int
158 result_row.aaccurate := TRUE;
162 IF result_row.sources > 0 OR result_row.asources > 0 THEN
164 -- The function that calls this function needs row_number in order
165 -- to correctly order results from two different runs of this
167 result_row.row_number := row_number;
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.
174 IF row_counter < result_limit THEN
175 result_row.browse_entry := rec.id;
176 result_row.value := rec.value;
178 RETURN NEXT result_row;
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;
190 IF row_counter >= next_pivot_pos THEN
191 RETURN NEXT result_row;
196 IF count_up_from_zero THEN
197 row_number := row_number + 1;
199 row_number := row_number - 1;
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;
209 $f$ LANGUAGE plpgsql ROWS 10;