From 42cd8308d129a9fdcff8da475c4cee6eb55c1379 Mon Sep 17 00:00:00 2001 From: miker Date: Mon, 8 Nov 2010 16:22:59 +0000 Subject: [PATCH] Teach vandelay.replace_field to be a little smarter by allowing simple cases of both replacing and regexp-testing the same subfield git-svn-id: svn://svn.open-ils.org/ILS/trunk@18652 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/sql/Pg/002.schema.config.sql | 2 +- Open-ILS/src/sql/Pg/012.schema.vandelay.sql | 27 ++++- .../0461.schema.vandelay.replace_field.sql | 101 ++++++++++++++++++ 3 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/0461.schema.vandelay.replace_field.sql diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql index 280eea4c0f..a2afe6b5cb 100644 --- a/Open-ILS/src/sql/Pg/002.schema.config.sql +++ b/Open-ILS/src/sql/Pg/002.schema.config.sql @@ -70,7 +70,7 @@ CREATE TABLE config.upgrade_log ( install_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); -INSERT INTO config.upgrade_log (version) VALUES ('0460'); -- dbs +INSERT INTO config.upgrade_log (version) VALUES ('0461'); -- miker CREATE TABLE config.bib_source ( id SERIAL PRIMARY KEY, diff --git a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql index 686cf4543f..14ddb5f827 100644 --- a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql +++ b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql @@ -305,7 +305,7 @@ BEGIN END; $_$ LANGUAGE PLPGSQL; -CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$ +CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT, force_add INT ) RETURNS TEXT AS $_$ use MARC::Record; use MARC::File::XML (BinaryEncoding => 'UTF-8'); @@ -314,6 +314,7 @@ CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT my $target_xml = shift; my $source_xml = shift; my $field_spec = shift; + my $force_add = shift || 0; my $target_r = MARC::Record->new_from_xml( $target_xml ); my $source_r = MARC::Record->new_from_xml( $source_xml ); @@ -349,7 +350,7 @@ CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT for my $from_field ($source_r->field( $f )) { my @tos = $target_r->field( $f ); if (!@tos) { - next if (exists($fields{$f}{match})); + next if (exists($fields{$f}{match}) and !$force_add); my @new_fields = map { $_->clone } $source_r->field( $f ); $target_r->insert_fields_ordered( @new_fields ); } else { @@ -377,6 +378,10 @@ CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT $_$ LANGUAGE PLPERLU; +CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$ + SELECT vandelay.add_field( $1, $2 $3, 0 ); +$_$ LANGUAGE SQL; + CREATE OR REPLACE FUNCTION vandelay.strip_field ( xml TEXT, field TEXT ) RETURNS TEXT AS $_$ use MARC::Record; @@ -437,8 +442,22 @@ CREATE OR REPLACE FUNCTION vandelay.strip_field ( xml TEXT, field TEXT ) RETURNS $_$ LANGUAGE PLPERLU; CREATE OR REPLACE FUNCTION vandelay.replace_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$ - SELECT vandelay.add_field( vandelay.strip_field( $1, $3), $2, $3 ); -$_$ LANGUAGE SQL; +DECLARE + xml_output TEXT; +BEGIN + xml_output := vandelay.strip_field( target_xml, field); + + IF xml_output <> target_xml AND field ~ E'~' THEN + -- we removed something, and there was a regexp restriction in the field definition, so proceed + xml_output := vandelay.add_field( xml_output, source_xml, field, 1 ); + ELSIF field !~ E'~' THEN + -- No regexp restriction, add the field + xml_output := vandelay.add_field( xml_output, source_xml, field, 0 ); + END IF; + + RETURN xml_output; +END; +$_$ LANGUAGE PLPGSQL; CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_xml TEXT, source_xml TEXT, add_rule TEXT, replace_preserve_rule TEXT, strip_rule TEXT ) RETURNS TEXT AS $_$ SELECT vandelay.replace_field( vandelay.add_field( vandelay.strip_field( $1, $5) , $2, $3 ), $2, $4); diff --git a/Open-ILS/src/sql/Pg/upgrade/0461.schema.vandelay.replace_field.sql b/Open-ILS/src/sql/Pg/upgrade/0461.schema.vandelay.replace_field.sql new file mode 100644 index 0000000000..ff5c362be3 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/0461.schema.vandelay.replace_field.sql @@ -0,0 +1,101 @@ + +BEGIN; + +INSERT INTO config.upgrade_log (version) VALUES ('0461'); --miker + +CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT, force_add INT ) RETURNS TEXT AS $_$ + + use MARC::Record; + use MARC::File::XML (BinaryEncoding => 'UTF-8'); + use strict; + + my $target_xml = shift; + my $source_xml = shift; + my $field_spec = shift; + my $force_add = shift || 0; + + my $target_r = MARC::Record->new_from_xml( $target_xml ); + my $source_r = MARC::Record->new_from_xml( $source_xml ); + + return $target_xml unless ($target_r && $source_r); + + my @field_list = split(',', $field_spec); + + my %fields; + for my $f (@field_list) { + $f =~ s/^\s*//; $f =~ s/\s*$//; + if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) { + my $field = $1; + $field =~ s/\s+//; + my $sf = $2; + $sf =~ s/\s+//; + my $match = $3; + $match =~ s/^\s*//; $match =~ s/\s*$//; + $fields{$field} = { sf => [ split('', $sf) ] }; + if ($match) { + my ($msf,$mre) = split('~', $match); + if (length($msf) > 0 and length($mre) > 0) { + $msf =~ s/^\s*//; $msf =~ s/\s*$//; + $mre =~ s/^\s*//; $mre =~ s/\s*$//; + $fields{$field}{match} = { sf => $msf, re => qr/$mre/ }; + } + } + } + } + + for my $f ( keys %fields) { + if ( @{$fields{$f}{sf}} ) { + for my $from_field ($source_r->field( $f )) { + my @tos = $target_r->field( $f ); + if (!@tos) { + next if (exists($fields{$f}{match}) and !$force_add); + my @new_fields = map { $_->clone } $source_r->field( $f ); + $target_r->insert_fields_ordered( @new_fields ); + } else { + for my $to_field (@tos) { + if (exists($fields{$f}{match})) { + next unless (grep { $_ =~ $fields{$f}{match}{re} } $to_field->subfield($fields{$f}{match}{sf})); + } + my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}{sf}}; + $to_field->add_subfields( @new_sf ); + } + } + } + } else { + my @new_fields = map { $_->clone } $source_r->field( $f ); + $target_r->insert_fields_ordered( @new_fields ); + } + } + + $target_xml = $target_r->as_xml_record; + $target_xml =~ s/^<\?.+?\?>$//mo; + $target_xml =~ s/\n//sgo; + $target_xml =~ s/>\s+ target_xml AND field ~ E'~' THEN + -- we removed something, and there was a regexp restriction in the field definition, so proceed + xml_output := vandelay.add_field( xml_output, source_xml, field, 1 ); + ELSIF field !~ E'~' THEN + -- No regexp restriction, add the field + xml_output := vandelay.add_field( xml_output, source_xml, field, 0 ); + END IF; + + RETURN xml_output; +END; +$_$ LANGUAGE PLPGSQL; + +COMMIT; -- 2.43.2