From d20b9d1331e836397ff827467685017df5795c6b Mon Sep 17 00:00:00 2001
From: miker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Date: Tue, 9 Mar 2010 18:55:13 +0000
Subject: [PATCH] teach vandelay.strip_field() how to handle lists of complex
 field specs (ie: 100d,245c,650); add vandelay.add_field() which will transfer
 fields from an incoming record to an incumbent record; add
 vandelay.replace_field() and vandelay.preserve_field(), which are wrappers
 that use strip and add

git-svn-id: svn://svn.open-ils.org/ILS/trunk@15768 dcc99617-32d9-48b4-a31d-7c20da2025e4
---
 Open-ILS/src/sql/Pg/012.schema.vandelay.sql | 77 ++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 2 deletions(-)

diff --git a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
index 689a83286a..f33eb404e6 100644
--- a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
+++ b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
@@ -129,16 +129,82 @@ CREATE TABLE vandelay.import_bib_trash_fields (
 	CONSTRAINT vand_import_bib_trash_fields_idx UNIQUE (owner,field)
 );
 
+CREATE OR REPLACE FUNCTION vandelay.add_field ( incumbent_xml TEXT, incoming_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+
+    use MARC::Record;
+    use MARC::File::XML;
+
+    my $incumbent_xml = shift;
+    my $incoming_xml = shift;
+    my $field_spec = shift;
+    $field_spec =~ s/\s+//g;
+
+    my $incumbent_r = MARC::Record->new_from_xml( $incumbent_xml );
+    my $incoming_r = MARC::Record->new_from_xml( $incoming_xml );
+
+    return $incumbent_xml unless ($incumbent_r && $incoming_r);
+
+    my @field_list = split(',' $field_spec);
+
+    my %fields;
+    for my $f (@field_list) {
+        if ($f =~ /^(.{3})(.*)$/) {
+            $fields{$1} = [ split('', $2) ];
+        }
+    }
+
+    for my $f ( keys %fields) {
+        if ( @{$fields{$f}} ) {
+            for my $from_field ($incoming_r->field( $f )) {
+                for my $to_field ($incumbent_r->field( $f )) {
+                    my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}};
+                    $to_field->add_subfields( @new_sf );
+                }
+            }
+        } else {
+            my @new_fields = map { $_->clone } $incoming_r->field( $f );
+            $incumbent_r->insert_fields_ordered( @new_fields );
+        }
+    }
+
+    $incumbent_xml = $incumbent_r->as_xml_record;
+    $incumbent_xml =~ s/^<\?.+?\?>$//mo;
+    $incumbent_xml =~ s/\n//sgo;
+    $incumbent_xml =~ s/>\s+</></sgo;
+
+    return $incumbent_xml;
+
+$_$ LANGUAGE PLPERLU;
+
 CREATE OR REPLACE FUNCTION vandelay.strip_field ( xml TEXT, field TEXT ) RETURNS TEXT AS $_$
 
     use MARC::Record;
     use MARC::File::XML;
 
     my $xml = shift;
+    my $r = MARC::Record->new_from_xml( $xml );
+
+    return $xml unless ($r);
+
     my $field_spec = shift;
+    $field_spec =~ s/\s+//g;
 
-    my $r = MARC::Record->new_from_xml( $xml );
-    $r->delete_field( $_ ) for ( $r->field( $field_spec ) );
+    my @field_list = split(',' $field_spec);
+
+    my %fields;
+    for my $f (@field_list) {
+        if ($f =~ /^(.{3})(.*)$/) {
+            $fields{$1} = [ split('', $2) ];
+        }
+    }
+
+    for my $f ( keys %fields) {
+        if ( @{$fields{$f}} ) {
+            $_->delete_subfield(code => $fields{$f}) for ($r->field( $f ));
+        } else {
+            $r->delete_field( $_ ) for ( $r->field( $f ) );
+        }
+    }
 
     $xml = $r->as_xml_record;
     $xml =~ s/^<\?.+?\?>$//mo;
@@ -149,6 +215,13 @@ CREATE OR REPLACE FUNCTION vandelay.strip_field ( xml TEXT, field TEXT ) RETURNS
 
 $_$ LANGUAGE PLPERLU;
 
+CREATE OR REPLACE FUNCTION vandelay.replace_field ( incumbent_xml TEXT, incoming_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+    SELECT vandelay.add_field( vandelay.strip_field( $1, $3), $2, $3 );
+$_$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION vandelay.preserve_field ( incumbent_xml TEXT, incoming_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+    SELECT vandelay.add_field( vandelay.strip_field( $2, $3), $1, $3 );
+$_$ LANGUAGE SQL;
 
 CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
 DECLARE
-- 
2.11.0