]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/version-upgrade/3.2.4-3.2.5-upgrade-db.sql
Bumping version numbers, adding Upgrade Script and Changelog
[Evergreen.git] / Open-ILS / src / sql / Pg / version-upgrade / 3.2.4-3.2.5-upgrade-db.sql
1 --Upgrade Script for 3.2.4 to 3.2.5
2 \set eg_version '''3.2.5'''
3 BEGIN;
4 INSERT INTO config.upgrade_log (version, applied_to) VALUES ('3.2.5', :eg_version);
5
6 SELECT evergreen.upgrade_deps_block_check('1154', :eg_version);
7
8 INSERT INTO config.usr_activity_type 
9     (id, ewhat, ehow, egroup, enabled, transient, label)
10 VALUES (
11     25, 'login', 'ws-translator-v1', 'authen', TRUE, TRUE,
12     oils_i18n_gettext(25, 'Login via Websocket V1', 'cuat', 'label')
13 ), (
14     26, 'login', 'ws-translator-v2', 'authen', TRUE, TRUE,
15     oils_i18n_gettext(26, 'Login via Websocket V2', 'cuat', 'label')
16 ), (
17     27, 'verify', 'ws-translator-v1', 'authz', TRUE, TRUE,
18     oils_i18n_gettext(27, 'Verification via Websocket v1', 'cuat', 'label')
19 ), (
20     28, 'verify', 'ws-translator-v2', 'authz', TRUE, TRUE,
21     oils_i18n_gettext(28, 'Verifiation via Websocket V2', 'cuat', 'label')
22 ), (
23     29, 'login', NULL, 'authen', TRUE, TRUE,
24     oils_i18n_gettext(29, 'Generic Login', 'cuat', 'label')
25 ), (
26     30, 'verify', NULL, 'authz', TRUE, TRUE,
27     oils_i18n_gettext(30, 'Generic Verify', 'cuat', 'label')
28 );
29
30
31
32 SELECT evergreen.upgrade_deps_block_check('1157', :eg_version); 
33
34 CREATE OR REPLACE FUNCTION vandelay.replace_field 
35     (target_xml TEXT, source_xml TEXT, field TEXT) RETURNS TEXT AS $_$
36
37     use strict;
38     use MARC::Record;
39     use MARC::Field;
40     use MARC::File::XML (BinaryEncoding => 'UTF-8');
41     use MARC::Charset;
42
43     MARC::Charset->assume_unicode(1);
44
45     my $target_xml = shift;
46     my $source_xml = shift;
47     my $field_spec = shift;
48
49     my $target_r = MARC::Record->new_from_xml($target_xml);
50     my $source_r = MARC::Record->new_from_xml($source_xml);
51
52     return $target_xml unless $target_r && $source_r;
53
54     # Extract the field_spec components into MARC tags, subfields, 
55     # and regex matches.  Copied wholesale from vandelay.strip_field()
56
57     my @field_list = split(',', $field_spec);
58     my %fields;
59     for my $f (@field_list) {
60         $f =~ s/^\s*//; $f =~ s/\s*$//;
61         if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
62             my $field = $1;
63             $field =~ s/\s+//;
64             my $sf = $2;
65             $sf =~ s/\s+//;
66             my $match = $3;
67             $match =~ s/^\s*//; $match =~ s/\s*$//;
68             $fields{$field} = { sf => [ split('', $sf) ] };
69             if ($match) {
70                 my ($msf,$mre) = split('~', $match);
71                 if (length($msf) > 0 and length($mre) > 0) {
72                     $msf =~ s/^\s*//; $msf =~ s/\s*$//;
73                     $mre =~ s/^\s*//; $mre =~ s/\s*$//;
74                     $fields{$field}{match} = { sf => $msf, re => qr/$mre/ };
75                 }
76             }
77         }
78     }
79
80     # Returns a flat list of subfield (code, value, code, value, ...)
81     # suitable for adding to a MARC::Field.
82     sub generate_replacement_subfields {
83         my ($source_field, $target_field, @controlled_subfields) = @_;
84
85         # Performing a wholesale field replacment.  
86         # Use the entire source field as-is.
87         return map {$_->[0], $_->[1]} $source_field->subfields
88             unless @controlled_subfields;
89
90         my @new_subfields;
91
92         # Iterate over all target field subfields:
93         # 1. Keep uncontrolled subfields as is.
94         # 2. Replace values for controlled subfields when a
95         #    replacement value exists on the source record.
96         # 3. Delete values for controlled subfields when no 
97         #    replacement value exists on the source record.
98
99         for my $target_sf ($target_field->subfields) {
100             my $subfield = $target_sf->[0];
101             my $target_val = $target_sf->[1];
102
103             if (grep {$_ eq $subfield} @controlled_subfields) {
104                 if (my $source_val = $source_field->subfield($subfield)) {
105                     # We have a replacement value
106                     push(@new_subfields, $subfield, $source_val);
107                 } else {
108                     # no replacement value for controlled subfield, drop it.
109                 }
110             } else {
111                 # Field is not controlled.  Copy it over as-is.
112                 push(@new_subfields, $subfield, $target_val);
113             }
114         }
115
116         # Iterate over all subfields in the source field and back-fill
117         # any values that exist only in the source field.  Insert these
118         # subfields in the same relative position they exist in the
119         # source field.
120                 
121         my @seen_subfields;
122         for my $source_sf ($source_field->subfields) {
123             my $subfield = $source_sf->[0];
124             my $source_val = $source_sf->[1];
125             push(@seen_subfields, $subfield);
126
127             # target field already contains this subfield, 
128             # so it would have been addressed above.
129             next if $target_field->subfield($subfield);
130
131             # Ignore uncontrolled subfields.
132             next unless grep {$_ eq $subfield} @controlled_subfields;
133
134             # Adding a new subfield.  Find its relative position and add
135             # it to the list under construction.  Work backwards from
136             # the list of already seen subfields to find the best slot.
137
138             my $done = 0;
139             for my $seen_sf (reverse(@seen_subfields)) {
140                 my $idx = @new_subfields;
141                 for my $new_sf (reverse(@new_subfields)) {
142                     $idx--;
143                     next if $idx % 2 == 1; # sf codes are in the even slots
144
145                     if ($new_subfields[$idx] eq $seen_sf) {
146                         splice(@new_subfields, $idx + 2, 0, $subfield, $source_val);
147                         $done = 1;
148                         last;
149                     }
150                 }
151                 last if $done;
152             }
153
154             # if no slot was found, add to the end of the list.
155             push(@new_subfields, $subfield, $source_val) unless $done;
156         }
157
158         return @new_subfields;
159     }
160
161     # MARC tag loop
162     for my $f (keys %fields) {
163         my $tag_idx = -1;
164         for my $target_field ($target_r->field($f)) {
165
166             # field spec contains a regex for this field.  Confirm field on 
167             # target record matches the specified regex before replacing.
168             if (exists($fields{$f}{match})) {
169                 next unless (grep { $_ =~ $fields{$f}{match}{re} } 
170                     $target_field->subfield($fields{$f}{match}{sf}));
171             }
172
173             my @new_subfields;
174             my @controlled_subfields = @{$fields{$f}{sf}};
175
176             # If the target record has multiple matching bib fields,
177             # replace them from matching fields on the source record
178             # in a predictable order to avoid replacing with them with
179             # same source field repeatedly.
180             my @source_fields = $source_r->field($f);
181             my $source_field = $source_fields[++$tag_idx];
182
183             if (!$source_field && @controlled_subfields) {
184                 # When there are more target fields than source fields
185                 # and we are replacing values for subfields and not
186                 # performing wholesale field replacment, use the last
187                 # available source field as the input for all remaining
188                 # target fields.
189                 $source_field = $source_fields[$#source_fields];
190             }
191
192             if (!$source_field) {
193                 # No source field exists.  Delete all affected target
194                 # data.  This is a little bit counterintuitive, but is
195                 # backwards compatible with the previous version of this
196                 # function which first deleted all affected data, then
197                 # replaced values where possible.
198                 if (@controlled_subfields) {
199                     $target_field->delete_subfield($_) for @controlled_subfields;
200                 } else {
201                     $target_r->delete_field($target_field);
202                 }
203                 next;
204             }
205
206             my @new_subfields = generate_replacement_subfields(
207                 $source_field, $target_field, @controlled_subfields);
208
209             # Build the replacement field from scratch.  
210             my $replacement_field = MARC::Field->new(
211                 $target_field->tag,
212                 $target_field->indicator(1),
213                 $target_field->indicator(2),
214                 @new_subfields
215             );
216
217             $target_field->replace_with($replacement_field);
218         }
219     }
220
221     $target_xml = $target_r->as_xml_record;
222     $target_xml =~ s/^<\?.+?\?>$//mo;
223     $target_xml =~ s/\n//sgo;
224     $target_xml =~ s/>\s+</></sgo;
225
226     return $target_xml;
227
228 $_$ LANGUAGE PLPERLU;
229
230
231
232 SELECT evergreen.upgrade_deps_block_check('1158', :eg_version);
233
234 --LP#1759238: Fix typo in seed data for Physical Description
235
236 UPDATE config.metabib_field
237     SET label = 'Physical Description'
238     WHERE id = 39 AND label = 'Physical Descrption';
239
240 COMMIT;