]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql
Stamping upgrade for relaxing rank_ou sorting
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0402.schema.unique_authority_index_revisited.sql
1 BEGIN;
2
3 -- Make the authority heading normalization routine more defensive
4 -- Also drop back to a plain index for 2.0, we will get more restrictive over time
5
6 INSERT INTO config.upgrade_log (version) VALUES ('0402'); -- dbs
7
8 CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
9     use strict;
10     use warnings;
11
12     use utf8;
13     use MARC::Record;
14     use MARC::File::XML (BinaryEncoding => 'UTF8');
15     use UUID::Tiny ':std';
16
17     my $xml = shift() or return undef;
18
19     my $r;
20
21     # Prevent errors in XML parsing from blowing out ungracefully
22     eval {
23         $r = MARC::Record->new_from_xml( $xml );
24         1;
25     } or do {
26        return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
27     };
28
29     if (!$r) {
30        return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
31     }
32
33     # From http://www.loc.gov/standards/sourcelist/subject.html
34     my $thes_code_map = {
35         a => 'lcsh',
36         b => 'lcshac',
37         c => 'mesh',
38         d => 'nal',
39         k => 'cash',
40         n => 'notapplicable',
41         r => 'aat',
42         s => 'sears',
43         v => 'rvm',
44     };
45
46     # Default to "No attempt to code" if the leader is horribly broken
47     my $fixed_field = $r->field('008');
48     my $thes_char = '|';
49     if ($fixed_field) { 
50         $thes_char = substr($fixed_field->data(), 11, 1) || '|';
51     }
52
53     my $thes_code = 'UNDEFINED';
54
55     if ($thes_char eq 'z') {
56         # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
57         $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
58     } elsif ($thes_code_map->{$thes_char}) {
59         $thes_code = $thes_code_map->{$thes_char};
60     }
61
62     my $auth_txt = '';
63     my $head = $r->field('1..');
64     if ($head) {
65         # Concatenate all of these subfields together, prefixed by their code
66         # to prevent collisions along the lines of "Fiction, North Carolina"
67         foreach my $sf ($head->subfields()) {
68             $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1];
69         }
70     }
71     
72     # Perhaps better to parameterize the spi and pass as a parameter
73     $auth_txt =~ s/'//go;
74
75     if ($auth_txt) {
76         my $result = spi_exec_query("SELECT public.naco_normalize('$auth_txt') AS norm_text");
77         my $norm_txt = $result->{rows}[0]->{norm_text};
78         return $head->tag() . "_" . $thes_code . " " . $norm_txt;
79     }
80
81     return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml);
82 $func$ LANGUAGE 'plperlu' IMMUTABLE;
83
84 DROP INDEX authority.unique_by_heading_and_thesaurus;
85
86 CREATE INDEX by_heading_and_thesaurus
87     ON authority.record_entry (authority.normalize_heading(marc))
88     WHERE deleted IS FALSE or deleted = FALSE
89 ;
90
91 COMMIT;