]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0942.schema.filter_authority_browse_search_by_thesaurus.sql
LP#1744385: Additions and edits to release note entry
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0942.schema.filter_authority_browse_search_by_thesaurus.sql
1 BEGIN;
2
3 SELECT evergreen.upgrade_deps_block_check('0942', :eg_version);
4
5 CREATE OR REPLACE FUNCTION authority.extract_thesaurus( marcxml TEXT ) RETURNS TEXT AS $func$
6 DECLARE
7     thes_code TEXT;
8 BEGIN
9     thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
10     IF thes_code IS NULL THEN
11         thes_code := '|';
12     ELSIF thes_code = 'z' THEN
13         thes_code := COALESCE( oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml), '' );
14     END IF;
15     RETURN thes_code;
16 END;
17 $func$ LANGUAGE PLPGSQL STABLE STRICT;
18
19 -- Intended to be used in a unique index on authority.record_entry like so:
20 -- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
21 --   ON authority.record_entry (heading)
22 --   WHERE deleted IS FALSE or deleted = FALSE;
23 CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT, no_thesaurus BOOL ) RETURNS TEXT AS $func$
24 DECLARE
25     acsaf           authority.control_set_authority_field%ROWTYPE;
26     tag_used        TEXT;
27     nfi_used        TEXT;
28     sf              TEXT;
29     sf_node         TEXT;
30     tag_node        TEXT;
31     thes_code       TEXT;
32     cset            INT;
33     heading_text    TEXT;
34     tmp_text        TEXT;
35     first_sf        BOOL;
36     auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT; 
37 BEGIN
38     SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id;
39
40     IF cset IS NULL THEN
41         SELECT  control_set INTO cset
42           FROM  authority.control_set_authority_field
43           WHERE tag IN ( SELECT  UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[]))
44           LIMIT 1;
45     END IF;
46
47     heading_text := '';
48     FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
49         tag_used := acsaf.tag;
50         nfi_used := acsaf.nfi;
51         first_sf := TRUE;
52
53         FOR tag_node IN SELECT unnest(oils_xpath('//*[@tag="'||tag_used||'"]',marcxml)) LOOP
54             FOR sf_node IN SELECT unnest(oils_xpath('./*[contains("'||acsaf.sf_list||'",@code)]',tag_node)) LOOP
55
56                 tmp_text := oils_xpath_string('.', sf_node);
57                 sf := oils_xpath_string('./@code', sf_node);
58
59                 IF first_sf AND tmp_text IS NOT NULL AND nfi_used IS NOT NULL THEN
60
61                     tmp_text := SUBSTRING(
62                         tmp_text FROM
63                         COALESCE(
64                             NULLIF(
65                                 REGEXP_REPLACE(
66                                     oils_xpath_string('./@ind'||nfi_used, tag_node),
67                                     $$\D+$$,
68                                     '',
69                                     'g'
70                                 ),
71                                 ''
72                             )::INT,
73                             0
74                         ) + 1
75                     );
76
77                 END IF;
78
79                 first_sf := FALSE;
80
81                 IF tmp_text IS NOT NULL AND tmp_text <> '' THEN
82                     heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text;
83                 END IF;
84             END LOOP;
85
86             EXIT WHEN heading_text <> '';
87         END LOOP;
88
89         EXIT WHEN heading_text <> '';
90     END LOOP;
91
92     IF heading_text <> '' THEN
93         IF no_thesaurus IS TRUE THEN
94             heading_text := tag_used || ' ' || public.naco_normalize(heading_text);
95         ELSE
96             thes_code := authority.extract_thesaurus(marcxml);
97             heading_text := tag_used || '_' || COALESCE(nfi_used,'-') || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
98         END IF;
99     ELSE
100         heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
101     END IF;
102
103     RETURN heading_text;
104 END;
105 $func$ LANGUAGE PLPGSQL STABLE STRICT;
106
107 ALTER TABLE authority.simple_heading ADD COLUMN thesaurus TEXT;
108 CREATE INDEX authority_simple_heading_thesaurus_idx ON authority.simple_heading (thesaurus);
109
110 CREATE OR REPLACE FUNCTION authority.simple_heading_set( marcxml TEXT ) RETURNS SETOF authority.simple_heading AS $func$
111 DECLARE
112     res             authority.simple_heading%ROWTYPE;
113     acsaf           authority.control_set_authority_field%ROWTYPE;
114     tag_used        TEXT;
115     nfi_used        TEXT;
116     sf              TEXT;
117     cset            INT;
118     heading_text    TEXT;
119     joiner_text     TEXT;
120     sort_text       TEXT;
121     tmp_text        TEXT;
122     tmp_xml         TEXT;
123     first_sf        BOOL;
124     auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT; 
125 BEGIN
126
127     SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id;
128
129     IF cset IS NULL THEN
130         SELECT  control_set INTO cset
131           FROM  authority.control_set_authority_field
132           WHERE tag IN ( SELECT  UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[]))
133           LIMIT 1;
134     END IF;
135
136     res.record := auth_id;
137     res.thesaurus := authority.extract_thesaurus(marcxml);
138
139     FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
140
141         res.atag := acsaf.id;
142         tag_used := acsaf.tag;
143         nfi_used := acsaf.nfi;
144         joiner_text := COALESCE(acsaf.joiner, ' ');
145
146         FOR tmp_xml IN SELECT UNNEST(XPATH('//*[@tag="'||tag_used||'"]', marcxml::XML)::TEXT[]) LOOP
147
148             heading_text := COALESCE(
149                 oils_xpath_string('./*[contains("'||acsaf.display_sf_list||'",@code)]', tmp_xml, joiner_text),
150                 ''
151             );
152
153             IF nfi_used IS NOT NULL THEN
154
155                 sort_text := SUBSTRING(
156                     heading_text FROM
157                     COALESCE(
158                         NULLIF(
159                             REGEXP_REPLACE(
160                                 oils_xpath_string('./@ind'||nfi_used, tmp_xml::TEXT),
161                                 $$\D+$$,
162                                 '',
163                                 'g'
164                             ),
165                             ''
166                         )::INT,
167                         0
168                     ) + 1
169                 );
170
171             ELSE
172                 sort_text := heading_text;
173             END IF;
174
175             IF heading_text IS NOT NULL AND heading_text <> '' THEN
176                 res.value := heading_text;
177                 res.sort_value := public.naco_normalize(sort_text);
178                 res.index_vector = to_tsvector('keyword'::regconfig, res.sort_value);
179                 RETURN NEXT res;
180             END IF;
181
182         END LOOP;
183
184     END LOOP;
185
186     RETURN;
187 END;
188
189 $func$ LANGUAGE PLPGSQL STABLE STRICT;
190 -- AFTER UPDATE OR INSERT trigger for authority.record_entry
191 CREATE OR REPLACE FUNCTION authority.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
192 DECLARE
193     ashs    authority.simple_heading%ROWTYPE;
194     mbe_row metabib.browse_entry%ROWTYPE;
195     mbe_id  BIGINT;
196     ash_id  BIGINT;
197 BEGIN
198
199     IF NEW.deleted IS TRUE THEN -- If this authority is deleted
200         DELETE FROM authority.bib_linking WHERE authority = NEW.id; -- Avoid updating fields in bibs that are no longer visible
201         DELETE FROM authority.full_rec WHERE record = NEW.id; -- Avoid validating fields against deleted authority records
202         DELETE FROM authority.simple_heading WHERE record = NEW.id;
203           -- Should remove matching $0 from controlled fields at the same time?
204
205         -- XXX What do we about the actual linking subfields present in
206         -- authority records that target this one when this happens?
207         DELETE FROM authority.authority_linking
208             WHERE source = NEW.id OR target = NEW.id;
209
210         RETURN NEW; -- and we're done
211     END IF;
212
213     IF TG_OP = 'UPDATE' THEN -- re-ingest?
214         PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
215
216         IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
217             RETURN NEW;
218         END IF;
219
220         -- Unless there's a setting stopping us, propagate these updates to any linked bib records
221         PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_auto_update' AND enabled;
222
223         IF NOT FOUND THEN
224             PERFORM authority.propagate_changes(NEW.id);
225         END IF;
226         
227         DELETE FROM authority.simple_heading WHERE record = NEW.id;
228         DELETE FROM authority.authority_linking WHERE source = NEW.id;
229     END IF;
230
231     INSERT INTO authority.authority_linking (source, target, field)
232         SELECT source, target, field FROM authority.calculate_authority_linking(
233             NEW.id, NEW.control_set, NEW.marc::XML
234         );
235
236     FOR ashs IN SELECT * FROM authority.simple_heading_set(NEW.marc) LOOP
237
238         INSERT INTO authority.simple_heading (record,atag,value,sort_value,thesaurus)
239             VALUES (ashs.record, ashs.atag, ashs.value, ashs.sort_value, ashs.thesaurus);
240             ash_id := CURRVAL('authority.simple_heading_id_seq'::REGCLASS);
241
242         SELECT INTO mbe_row * FROM metabib.browse_entry
243             WHERE value = ashs.value AND sort_value = ashs.sort_value;
244
245         IF FOUND THEN
246             mbe_id := mbe_row.id;
247         ELSE
248             INSERT INTO metabib.browse_entry
249                 ( value, sort_value ) VALUES
250                 ( ashs.value, ashs.sort_value );
251
252             mbe_id := CURRVAL('metabib.browse_entry_id_seq'::REGCLASS);
253         END IF;
254
255         INSERT INTO metabib.browse_entry_simple_heading_map (entry,simple_heading) VALUES (mbe_id,ash_id);
256
257     END LOOP;
258
259     -- Flatten and insert the afr data
260     PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
261     IF NOT FOUND THEN
262         PERFORM authority.reingest_authority_full_rec(NEW.id);
263         PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
264         IF NOT FOUND THEN
265             PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
266         END IF;
267     END IF;
268
269     RETURN NEW;
270 END;
271 $func$ LANGUAGE PLPGSQL;
272
273 DROP FUNCTION IF EXISTS authority.atag_search_heading_refs(TEXT, TEXT, INT, INT);
274 DROP FUNCTION IF EXISTS authority.btag_search_heading_refs(TEXT, TEXT, INT, INT);
275 DROP FUNCTION IF EXISTS authority.axis_search_heading_refs(TEXT, TEXT, INT, INT);
276 DROP FUNCTION IF EXISTS authority.atag_search_heading(TEXT, TEXT, INT, INT);
277 DROP FUNCTION IF EXISTS authority.btag_search_heading(TEXT, TEXT, INT, INT);
278 DROP FUNCTION IF EXISTS authority.axis_search_heading(TEXT, TEXT, INT, INT);
279 DROP FUNCTION IF EXISTS authority.simple_heading_search_heading(INT[], TEXT, INT, INT);
280 DROP FUNCTION IF EXISTS authority.atag_search_rank_refs(TEXT, TEXT, INT, INT);
281 DROP FUNCTION IF EXISTS authority.btag_search_rank_refs(TEXT, TEXT, INT, INT);
282 DROP FUNCTION IF EXISTS authority.axis_search_rank_refs(TEXT, TEXT, INT, INT);
283 DROP FUNCTION IF EXISTS authority.atag_search_rank(TEXT, TEXT, INT, INT);
284 DROP FUNCTION IF EXISTS authority.btag_search_rank(TEXT, TEXT, INT, INT);
285 DROP FUNCTION IF EXISTS authority.axis_search_rank(TEXT, TEXT, INT, INT);
286 DROP FUNCTION IF EXISTS authority.simple_heading_search_rank(INT[], TEXT, INT, INT);
287 DROP FUNCTION IF EXISTS authority.atag_browse_top_refs(TEXT, TEXT, INT, INT);
288 DROP FUNCTION IF EXISTS authority.btag_browse_top_refs(TEXT, TEXT, INT, INT);
289 DROP FUNCTION IF EXISTS authority.axis_browse_top_refs(TEXT, TEXT, INT, INT);
290 DROP FUNCTION IF EXISTS authority.atag_browse_top(TEXT, TEXT, INT, INT);
291 DROP FUNCTION IF EXISTS authority.btag_browse_top(TEXT, TEXT, INT, INT);
292 DROP FUNCTION IF EXISTS authority.axis_browse_top(TEXT, TEXT, INT, INT);
293 DROP FUNCTION IF EXISTS authority.simple_heading_browse_top(INT[], TEXT, INT, INT);
294 DROP FUNCTION IF EXISTS authority.atag_browse_center_refs(TEXT, TEXT, INT, INT);
295 DROP FUNCTION IF EXISTS authority.btag_browse_center_refs(TEXT, TEXT, INT, INT);
296 DROP FUNCTION IF EXISTS authority.axis_browse_center_refs(TEXT, TEXT, INT, INT);
297 DROP FUNCTION IF EXISTS authority.atag_browse_center(TEXT, TEXT, INT, INT);
298 DROP FUNCTION IF EXISTS authority.btag_browse_center(TEXT, TEXT, INT, INT);
299 DROP FUNCTION IF EXISTS authority.axis_browse_center(TEXT, TEXT, INT, INT);
300 DROP FUNCTION IF EXISTS authority.simple_heading_browse_center(INT[], TEXT, INT, INT);
301 DROP FUNCTION IF EXISTS authority.simple_heading_find_pivot(INT[], TEXT);
302
303 -- Support function used to find the pivot for alpha-heading-browse style searching
304 CREATE OR REPLACE FUNCTION authority.simple_heading_find_pivot( a INT[], q TEXT, thesauruses TEXT DEFAULT '' ) RETURNS TEXT AS $$
305 DECLARE
306     sort_value_row  RECORD;
307     value_row       RECORD;
308     t_term          TEXT;
309 BEGIN
310
311     t_term := public.naco_normalize(q);
312
313     SELECT  CASE WHEN ash.sort_value LIKE t_term || '%' THEN 1 ELSE 0 END
314                 + CASE WHEN ash.value LIKE t_term || '%' THEN 1 ELSE 0 END AS rank,
315             ash.sort_value
316     INTO  sort_value_row
317     FROM  authority.simple_heading ash
318     WHERE ash.atag = ANY (a)
319             AND ash.sort_value >= t_term
320             AND CASE thesauruses
321                 WHEN '' THEN TRUE
322                 ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
323                 END
324     ORDER BY rank DESC, ash.sort_value
325     LIMIT 1;
326
327     SELECT  CASE WHEN ash.sort_value LIKE t_term || '%' THEN 1 ELSE 0 END
328                 + CASE WHEN ash.value LIKE t_term || '%' THEN 1 ELSE 0 END AS rank,
329             ash.sort_value
330     INTO  value_row
331     FROM  authority.simple_heading ash
332     WHERE ash.atag = ANY (a)
333             AND ash.value >= t_term
334             AND CASE thesauruses
335                 WHEN '' THEN TRUE
336                 ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
337                 END
338     ORDER BY rank DESC, ash.sort_value
339     LIMIT 1;
340
341     IF value_row.rank > sort_value_row.rank THEN
342         RETURN value_row.sort_value;
343     ELSE
344         RETURN sort_value_row.sort_value;
345     END IF;
346 END;
347 $$ LANGUAGE PLPGSQL;
348
349 CREATE OR REPLACE FUNCTION authority.simple_heading_browse_center( atag_list INT[], q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
350 DECLARE
351     pivot_sort_value    TEXT;
352     boffset             INT DEFAULT 0;
353     aoffset             INT DEFAULT 0;
354     blimit              INT DEFAULT 0;
355     alimit              INT DEFAULT 0;
356 BEGIN
357
358     pivot_sort_value := authority.simple_heading_find_pivot(atag_list,q,thesauruses);
359
360     IF page = 0 THEN
361         blimit := pagesize / 2;
362         alimit := blimit;
363
364         IF pagesize % 2 <> 0 THEN
365             alimit := alimit + 1;
366         END IF;
367     ELSE
368         blimit := pagesize;
369         alimit := blimit;
370
371         boffset := pagesize / 2;
372         aoffset := boffset;
373
374         IF pagesize % 2 <> 0 THEN
375             boffset := boffset + 1;
376         END IF;
377     END IF;
378
379     IF page <= 0 THEN
380         -- "bottom" half of the browse results
381         RETURN QUERY
382             SELECT id FROM (
383                 SELECT  ash.id,
384                         row_number() over ()
385                 FROM  authority.simple_heading ash
386                 WHERE ash.atag = ANY (atag_list)
387                         AND CASE thesauruses
388                             WHEN '' THEN TRUE
389                             ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
390                             END
391                         AND ash.sort_value < pivot_sort_value
392                 ORDER BY ash.sort_value DESC
393                 LIMIT blimit
394                 OFFSET ABS(page) * pagesize - boffset
395             ) x ORDER BY row_number DESC;
396     END IF;
397
398     IF page >= 0 THEN
399         -- "bottom" half of the browse results
400         RETURN QUERY
401             SELECT  ash.id
402             FROM  authority.simple_heading ash
403             WHERE ash.atag = ANY (atag_list)
404                     AND CASE thesauruses
405                         WHEN '' THEN TRUE
406                         ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
407                         END
408                     AND ash.sort_value >= pivot_sort_value
409             ORDER BY ash.sort_value
410             LIMIT alimit
411             OFFSET ABS(page) * pagesize - aoffset;
412     END IF;
413 END;
414 $$ LANGUAGE PLPGSQL ROWS 10;
415
416 CREATE OR REPLACE FUNCTION authority.axis_browse_center( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
417     SELECT * FROM authority.simple_heading_browse_center(authority.axis_authority_tags($1), $2, $3, $4, $5)
418 $$ LANGUAGE SQL ROWS 10;
419
420 CREATE OR REPLACE FUNCTION authority.btag_browse_center( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
421     SELECT * FROM authority.simple_heading_browse_center(authority.btag_authority_tags($1), $2, $3, $4, $5)
422 $$ LANGUAGE SQL ROWS 10;
423
424 CREATE OR REPLACE FUNCTION authority.atag_browse_center( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
425     SELECT * FROM authority.simple_heading_browse_center(authority.atag_authority_tags($1), $2, $3, $4, $5)
426 $$ LANGUAGE SQL ROWS 10;
427
428 CREATE OR REPLACE FUNCTION authority.axis_browse_center_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
429     SELECT * FROM authority.simple_heading_browse_center(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)
430 $$ LANGUAGE SQL ROWS 10;
431
432 CREATE OR REPLACE FUNCTION authority.btag_browse_center_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
433     SELECT * FROM authority.simple_heading_browse_center(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)
434 $$ LANGUAGE SQL ROWS 10;
435
436 CREATE OR REPLACE FUNCTION authority.atag_browse_center_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 9, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
437     SELECT * FROM authority.simple_heading_browse_center(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)
438 $$ LANGUAGE SQL ROWS 10;
439
440
441 CREATE OR REPLACE FUNCTION authority.simple_heading_browse_top( atag_list INT[], q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
442 DECLARE
443     pivot_sort_value    TEXT;
444 BEGIN
445
446     pivot_sort_value := authority.simple_heading_find_pivot(atag_list,q,thesauruses);
447
448     IF page < 0 THEN
449          -- "bottom" half of the browse results
450         RETURN QUERY
451             SELECT id FROM (
452                 SELECT  ash.id,
453                         row_number() over ()
454                 FROM  authority.simple_heading ash
455                 WHERE ash.atag = ANY (atag_list)
456                         AND CASE thesauruses
457                             WHEN '' THEN TRUE
458                             ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
459                             END
460                         AND ash.sort_value < pivot_sort_value
461                 ORDER BY ash.sort_value DESC
462                 LIMIT pagesize
463                 OFFSET (ABS(page) - 1) * pagesize
464             ) x ORDER BY row_number DESC;
465     END IF;
466
467     IF page >= 0 THEN
468          -- "bottom" half of the browse results
469         RETURN QUERY
470             SELECT  ash.id
471             FROM  authority.simple_heading ash
472             WHERE ash.atag = ANY (atag_list)
473                 AND CASE thesauruses
474                     WHEN '' THEN TRUE
475                     ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
476                     END
477                     AND ash.sort_value >= pivot_sort_value
478             ORDER BY ash.sort_value
479             LIMIT pagesize
480             OFFSET ABS(page) * pagesize ;
481     END IF;
482 END;
483 $$ LANGUAGE PLPGSQL ROWS 10;
484
485 CREATE OR REPLACE FUNCTION authority.axis_browse_top( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
486     SELECT * FROM authority.simple_heading_browse_top(authority.axis_authority_tags($1), $2, $3, $4, $5)
487 $$ LANGUAGE SQL ROWS 10;
488
489 CREATE OR REPLACE FUNCTION authority.btag_browse_top( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
490     SELECT * FROM authority.simple_heading_browse_top(authority.btag_authority_tags($1), $2, $3, $4, $5)
491 $$ LANGUAGE SQL ROWS 10;
492
493 CREATE OR REPLACE FUNCTION authority.atag_browse_top( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
494     SELECT * FROM authority.simple_heading_browse_top(authority.atag_authority_tags($1), $2, $3, $4, $5)
495 $$ LANGUAGE SQL ROWS 10;
496
497 CREATE OR REPLACE FUNCTION authority.axis_browse_top_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
498     SELECT * FROM authority.simple_heading_browse_top(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)
499 $$ LANGUAGE SQL ROWS 10;
500
501 CREATE OR REPLACE FUNCTION authority.btag_browse_top_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
502     SELECT * FROM authority.simple_heading_browse_top(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)
503 $$ LANGUAGE SQL ROWS 10;
504
505 CREATE OR REPLACE FUNCTION authority.atag_browse_top_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
506     SELECT * FROM authority.simple_heading_browse_top(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)
507 $$ LANGUAGE SQL ROWS 10;
508
509
510 CREATE OR REPLACE FUNCTION authority.simple_heading_search_rank( atag_list INT[], q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
511     SELECT  ash.id
512       FROM  authority.simple_heading ash,
513             public.naco_normalize($2) t(term),
514             plainto_tsquery('keyword'::regconfig,$2) ptsq(term)
515       WHERE ash.atag = ANY ($1)
516             AND ash.index_vector @@ ptsq.term
517             AND CASE $5
518                 WHEN '' THEN TRUE
519                 ELSE ash.thesaurus = ANY(regexp_split_to_array($5, ','))
520                 END
521       ORDER BY ts_rank_cd(ash.index_vector,ptsq.term,14)::numeric
522                     + CASE WHEN ash.sort_value LIKE t.term || '%' THEN 2 ELSE 0 END
523                     + CASE WHEN ash.value LIKE t.term || '%' THEN 1 ELSE 0 END DESC
524       LIMIT $4
525       OFFSET $4 * $3;
526 $$ LANGUAGE SQL ROWS 10;
527
528 CREATE OR REPLACE FUNCTION authority.axis_search_rank( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
529     SELECT * FROM authority.simple_heading_search_rank(authority.axis_authority_tags($1), $2, $3, $4, $5)
530 $$ LANGUAGE SQL ROWS 10;
531
532 CREATE OR REPLACE FUNCTION authority.btag_search_rank( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
533     SELECT * FROM authority.simple_heading_search_rank(authority.btag_authority_tags($1), $2, $3, $4, $5)
534 $$ LANGUAGE SQL ROWS 10;
535
536 CREATE OR REPLACE FUNCTION authority.atag_search_rank( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
537     SELECT * FROM authority.simple_heading_search_rank(authority.atag_authority_tags($1), $2, $3, $4, $5)
538 $$ LANGUAGE SQL ROWS 10;
539
540 CREATE OR REPLACE FUNCTION authority.axis_search_rank_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
541     SELECT * FROM authority.simple_heading_search_rank(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)
542 $$ LANGUAGE SQL ROWS 10;
543
544 CREATE OR REPLACE FUNCTION authority.btag_search_rank_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
545     SELECT * FROM authority.simple_heading_search_rank(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)
546 $$ LANGUAGE SQL ROWS 10;
547
548 CREATE OR REPLACE FUNCTION authority.atag_search_rank_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
549     SELECT * FROM authority.simple_heading_search_rank(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)
550 $$ LANGUAGE SQL ROWS 10;
551
552
553 CREATE OR REPLACE FUNCTION authority.simple_heading_search_heading( atag_list INT[], q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
554     SELECT  ash.id
555       FROM  authority.simple_heading ash,
556             public.naco_normalize($2) t(term),
557             plainto_tsquery('keyword'::regconfig,$2) ptsq(term)
558       WHERE ash.atag = ANY ($1)
559             AND ash.index_vector @@ ptsq.term
560             AND CASE $5
561                 WHEN '' THEN TRUE
562                 ELSE ash.thesaurus = ANY(regexp_split_to_array($5, ','))
563                 END
564       ORDER BY ash.sort_value
565       LIMIT $4
566       OFFSET $4 * $3;
567 $$ LANGUAGE SQL ROWS 10;
568
569 CREATE OR REPLACE FUNCTION authority.axis_search_heading( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
570     SELECT * FROM authority.simple_heading_search_heading(authority.axis_authority_tags($1), $2, $3, $4, $5)
571 $$ LANGUAGE SQL ROWS 10;
572
573 CREATE OR REPLACE FUNCTION authority.btag_search_heading( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
574     SELECT * FROM authority.simple_heading_search_heading(authority.btag_authority_tags($1), $2, $3, $4, $5)
575 $$ LANGUAGE SQL ROWS 10;
576
577 CREATE OR REPLACE FUNCTION authority.atag_search_heading( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
578     SELECT * FROM authority.simple_heading_search_heading(authority.atag_authority_tags($1), $2, $3, $4, $5)
579 $$ LANGUAGE SQL ROWS 10;
580
581 CREATE OR REPLACE FUNCTION authority.axis_search_heading_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
582     SELECT * FROM authority.simple_heading_search_heading(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)
583 $$ LANGUAGE SQL ROWS 10;
584
585 CREATE OR REPLACE FUNCTION authority.btag_search_heading_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
586     SELECT * FROM authority.simple_heading_search_heading(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)
587 $$ LANGUAGE SQL ROWS 10;
588
589 CREATE OR REPLACE FUNCTION authority.atag_search_heading_refs( a TEXT, q TEXT, page INT DEFAULT 0, pagesize INT DEFAULT 10, thesauruses TEXT DEFAULT '' ) RETURNS SETOF BIGINT AS $$
590     SELECT * FROM authority.simple_heading_search_heading(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)
591 $$ LANGUAGE SQL ROWS 10;
592
593
594 \qecho
595 \qecho Updating the thesaurus codes in authority.simple_heading;
596 \qecho This may take a while in databases with many authority records.
597 \qecho
598 UPDATE authority.simple_heading a
599 SET thesaurus = authority.extract_thesaurus(b.marc)
600 FROM authority.record_entry b
601 WHERE a.record = b.id;
602
603 COMMIT;