]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0316.schema.authority-bib-overlay-stored-proc.sql
LP#1733695: Stamping upgrade scripts for multilingual search
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0316.schema.authority-bib-overlay-stored-proc.sql
1 BEGIN;
2
3 INSERT INTO config.upgrade_log (version) VALUES ('0316');
4
5 -- Function that takes, and returns, marcxml and compiles an embedded ruleset for you, and they applys it
6 CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_marc TEXT, template_marc TEXT ) RETURNS TEXT AS $$
7 DECLARE
8     dyn_profile     vandelay.compile_profile%ROWTYPE;
9     replace_rule    TEXT;
10     tmp_marc        TEXT;
11     trgt_marc        TEXT;
12     tmpl_marc        TEXT;
13     match_count     INT;
14 BEGIN
15
16     IF target_marc IS NULL OR template_marc IS NULL THEN
17         -- RAISE NOTICE 'no marc for target or template record';
18         RETURN NULL;
19     END IF;
20
21     dyn_profile := vandelay.compile_profile( template_marc );
22
23     IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN
24         -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule;
25         RETURN NULL;
26     END IF;
27
28     IF dyn_profile.replace_rule <> '' THEN
29         trgt_marc = target_marc;
30         tmpl_marc = template_marc;
31         replace_rule = dyn_profile.replace_rule;
32     ELSE
33         tmp_marc = target_marc;
34         trgt_marc = template_marc;
35         tmpl_marc = tmp_marc;
36         replace_rule = dyn_profile.preserve_rule;
37     END IF;
38
39     RETURN vandelay.merge_record_xml( trgt_marc, tmpl_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule );
40
41 END;
42 $$ LANGUAGE PLPGSQL;
43
44 -- Fix a bug in this, for subfield-specific additions
45 CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
46
47     use MARC::Record;
48     use MARC::File::XML;
49
50     my $target_xml = shift;
51     my $source_xml = shift;
52     my $field_spec = shift;
53
54     my $target_r = MARC::Record->new_from_xml( $target_xml );
55     my $source_r = MARC::Record->new_from_xml( $source_xml );
56
57     return $target_xml unless ($target_r && $source_r);
58
59     my @field_list = split(',', $field_spec);
60
61     my %fields;
62     for my $f (@field_list) {
63         $f =~ s/^\s*//; $f =~ s/\s*$//;
64         if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
65             my $field = $1;
66             $field =~ s/\s+//;
67             my $sf = $2;
68             $sf =~ s/\s+//;
69             my $match = $3;
70             $match =~ s/^\s*//; $match =~ s/\s*$//;
71             $fields{$field} = { sf => [ split('', $sf) ] };
72             if ($match) {
73                 my ($msf,$mre) = split('~', $match);
74                 if (length($msf) > 0 and length($mre) > 0) {
75                     $msf =~ s/^\s*//; $msf =~ s/\s*$//;
76                     $mre =~ s/^\s*//; $mre =~ s/\s*$//;
77                     $fields{$field}{match} = { sf => $msf, re => qr/$mre/ };
78                 }
79             }
80         }
81     }
82
83     for my $f ( keys %fields) {
84         if ( @{$fields{$f}{sf}} ) {
85             for my $from_field ($source_r->field( $f )) {
86                 for my $to_field ($target_r->field( $f )) {
87                     if (exists($fields{$f}{match})) {
88                         next unless (grep { $_ =~ $field{$f}{match}{re} } $to_field->subfield($field{$f}{match}{sf}));
89                     }
90                     my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}};
91                     $to_field->add_subfields( @new_sf );
92                 }
93             }
94         } else {
95             my @new_fields = map { $_->clone } $source_r->field( $f );
96             $target_r->insert_fields_ordered( @new_fields );
97         }
98     }
99
100     $target_xml = $target_r->as_xml_record;
101     $target_xml =~ s/^<\?.+?\?>$//mo;
102     $target_xml =~ s/\n//sgo;
103     $target_xml =~ s/>\s+</></sgo;
104
105     return $target_xml;
106
107 $_$ LANGUAGE PLPERLU;
108
109 -- Function to generate an ephemeral overlay template from an authority record
110 CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT, BIGINT ) RETURNS TEXT AS $func$
111
112     use MARC::Record;
113     use MARC::File::XML;
114
115     my $xml = shift;
116     my $r = MARC::Record->new_from_xml( $xml );
117
118     return undef unless ($r);
119
120     my $id = shift() || $r->subfield( '035' => 'a' ) || $r->subfield( '901' => 'c' );
121     $id =~ s/^\s*(?:\([^)]+\))?\s*(.+)\s*?$/$1/;
122     return undef unless ($id); # We need an ID!
123
124     my $tmpl = MARC::Record->new();
125
126     my @rule_fields;
127     for my $field ( $r->field( '1..' ) ) { # Get main entry fields from the authority record
128
129         my $tag = $field->tag;
130         my $i1 = $field->indicator(1);
131         my $i2 = $field->indicator(2);
132         my $sf = join '', map { $_->[0] } $field->subfields;
133         my @data = map { @$_ } $field->subfields;
134
135         my @replace_them;
136
137         # Map the authority field to bib fields it can control. 
138         if ($tag >= 100 and $tag <= 111) {       # names
139             @replace_them = map { $tag + $_ } (0, 300, 500, 600, 700);
140         } elsif ($tag eq '130') {                # uniform title
141             @replace_them = qw/130 240 440 730 830/;
142         } elsif ($tag >= 150 and $tag <= 155) {  # subjects
143             @replace_them = ($tag + 500);
144         } elsif ($tag >= 180 and $tag <= 185) {  # floating subdivisions
145             @replace_them = qw/100 400 600 700 800 110 410 610 710 810 111 411 611 711 811 130 240 440 730 830 650 651 655/;
146         } else {
147             next;
148         }
149
150         # Dummy up the bib-side data
151         $tmpl->append_fields(
152             map {
153                 MARC::Field->new( $_, $i1, $i2, @data )
154             } @replace_them
155         );
156
157         # Construct some 'replace' rules
158         push @rule_fields, map { $_ . $sf . '[0~\)' .$id . '$]' } @replace_them;
159     }
160
161     # Insert the replace rules into the template
162     $tmpl->append_fields(
163         MARC::Field->new( '905' => ' ' => ' ' => 'r' => join(',', @rule_fields ) )
164     );
165
166     $xml = $tmpl->as_xml_record;
167     $xml =~ s/^<\?.+?\?>$//mo;
168
169     # Leave formatting intact for now
170     #$xml =~ s/\n//sgo;
171     #$xml =~ s/>\s+</></sgo;
172
173     return $xml;
174
175 $func$ LANGUAGE PLPERLU;
176
177 CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( BIGINT ) RETURNS TEXT AS $func$
178     SELECT authority.generate_overlay_template( marc, id ) FROM authority.record_entry WHERE id = $1;
179 $func$ LANGUAGE SQL;
180
181 CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT ) RETURNS TEXT AS $func$
182     SELECT authority.generate_overlay_template( $1, NULL );
183 $func$ LANGUAGE SQL;
184
185 COMMIT;
186