1 --Upgrade Script for 3.2.4 to 3.2.5
2 \set eg_version '''3.2.5'''
4 INSERT INTO config.upgrade_log (version, applied_to) VALUES ('3.2.5', :eg_version);
6 SELECT evergreen.upgrade_deps_block_check('1154', :eg_version);
8 INSERT INTO config.usr_activity_type
9 (id, ewhat, ehow, egroup, enabled, transient, label)
11 25, 'login', 'ws-translator-v1', 'authen', TRUE, TRUE,
12 oils_i18n_gettext(25, 'Login via Websocket V1', 'cuat', 'label')
14 26, 'login', 'ws-translator-v2', 'authen', TRUE, TRUE,
15 oils_i18n_gettext(26, 'Login via Websocket V2', 'cuat', 'label')
17 27, 'verify', 'ws-translator-v1', 'authz', TRUE, TRUE,
18 oils_i18n_gettext(27, 'Verification via Websocket v1', 'cuat', 'label')
20 28, 'verify', 'ws-translator-v2', 'authz', TRUE, TRUE,
21 oils_i18n_gettext(28, 'Verifiation via Websocket V2', 'cuat', 'label')
23 29, 'login', NULL, 'authen', TRUE, TRUE,
24 oils_i18n_gettext(29, 'Generic Login', 'cuat', 'label')
26 30, 'verify', NULL, 'authz', TRUE, TRUE,
27 oils_i18n_gettext(30, 'Generic Verify', 'cuat', 'label')
32 SELECT evergreen.upgrade_deps_block_check('1157', :eg_version);
34 CREATE OR REPLACE FUNCTION vandelay.replace_field
35 (target_xml TEXT, source_xml TEXT, field TEXT) RETURNS TEXT AS $_$
40 use MARC::File::XML (BinaryEncoding => 'UTF-8');
43 MARC::Charset->assume_unicode(1);
45 my $target_xml = shift;
46 my $source_xml = shift;
47 my $field_spec = shift;
49 my $target_r = MARC::Record->new_from_xml($target_xml);
50 my $source_r = MARC::Record->new_from_xml($source_xml);
52 return $target_xml unless $target_r && $source_r;
54 # Extract the field_spec components into MARC tags, subfields,
55 # and regex matches. Copied wholesale from vandelay.strip_field()
57 my @field_list = split(',', $field_spec);
59 for my $f (@field_list) {
60 $f =~ s/^\s*//; $f =~ s/\s*$//;
61 if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
67 $match =~ s/^\s*//; $match =~ s/\s*$//;
68 $fields{$field} = { sf => [ split('', $sf) ] };
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/ };
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) = @_;
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;
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.
99 for my $target_sf ($target_field->subfields) {
100 my $subfield = $target_sf->[0];
101 my $target_val = $target_sf->[1];
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);
108 # no replacement value for controlled subfield, drop it.
111 # Field is not controlled. Copy it over as-is.
112 push(@new_subfields, $subfield, $target_val);
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
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);
127 # target field already contains this subfield,
128 # so it would have been addressed above.
129 next if $target_field->subfield($subfield);
131 # Ignore uncontrolled subfields.
132 next unless grep {$_ eq $subfield} @controlled_subfields;
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.
139 for my $seen_sf (reverse(@seen_subfields)) {
140 my $idx = @new_subfields;
141 for my $new_sf (reverse(@new_subfields)) {
143 next if $idx % 2 == 1; # sf codes are in the even slots
145 if ($new_subfields[$idx] eq $seen_sf) {
146 splice(@new_subfields, $idx + 2, 0, $subfield, $source_val);
154 # if no slot was found, add to the end of the list.
155 push(@new_subfields, $subfield, $source_val) unless $done;
158 return @new_subfields;
162 for my $f (keys %fields) {
164 for my $target_field ($target_r->field($f)) {
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}));
174 my @controlled_subfields = @{$fields{$f}{sf}};
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];
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
189 $source_field = $source_fields[$#source_fields];
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;
201 $target_r->delete_field($target_field);
206 my @new_subfields = generate_replacement_subfields(
207 $source_field, $target_field, @controlled_subfields);
209 # Build the replacement field from scratch.
210 my $replacement_field = MARC::Field->new(
212 $target_field->indicator(1),
213 $target_field->indicator(2),
217 $target_field->replace_with($replacement_field);
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;
228 $_$ LANGUAGE PLPERLU;
232 SELECT evergreen.upgrade_deps_block_check('1158', :eg_version);
234 --LP#1759238: Fix typo in seed data for Physical Description
236 UPDATE config.metabib_field
237 SET label = 'Physical Description'
238 WHERE id = 39 AND label = 'Physical Descrption';