LP#1037553: bibliographic record source now copied to 901$s
authorGalen Charlton <gmc@esilibrary.com>
Wed, 26 Aug 2015 17:59:37 +0000 (17:59 +0000)
committerMike Rylander <mrylander@gmail.com>
Tue, 9 Aug 2016 18:53:08 +0000 (14:53 -0400)
If a bibliographic record has a source set, the name of that source
is now copied to the 901$s whenever the record is created or updated.
This allows the source to be used for record matching and MARC
field queries.

To test:

[1] Create or import a bibliographic record and ensure that its
    source is set to a non-null value.
[2] Inspect the record in MARC format view and verify that its
    901 field now has a subfield $s containing the name of the
    source.
[3] Use pg_prove to run the pgTAP test added by this patch
    and verify that the test passes.

Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/sql/Pg/002.functions.config.sql
Open-ILS/src/sql/Pg/t/bib_901_field.pg [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.bib_source_in_901.sql [new file with mode: 0644]
docs/RELEASE_NOTES_NEXT/Cataloging/bib_source_in_901s.txt [new file with mode: 0644]

index d52c6f9..77876fe 100644 (file)
@@ -395,6 +395,18 @@ if ($schema eq 'biblio') {
         $new_901->add_subfields("d" => $_TD->{new}{share_depth});
     }
 
+    if ($_TD->{new}{source}) {
+        my $plan = spi_prepare('
+            SELECT source
+            FROM config.bib_source
+            WHERE id = $1
+        ', 'INTEGER');
+        my $source_name =
+            spi_exec_prepared($plan, {limit => 1}, $_TD->{new}{source})->{rows}[0]{source};
+        spi_freeplan($plan);
+        $new_901->add_subfields("s" => $source_name) if $source_name;
+    }
+
     $marc->append_fields($new_901);
 } elsif ($schema eq 'authority') {
     my $new_901 = MARC::Field->new("901", " ", " ",
diff --git a/Open-ILS/src/sql/Pg/t/bib_901_field.pg b/Open-ILS/src/sql/Pg/t/bib_901_field.pg
new file mode 100644 (file)
index 0000000..e41481c
--- /dev/null
@@ -0,0 +1,21 @@
+BEGIN;
+
+SELECT plan(1);
+
+INSERT INTO config.bib_source(id, source) VALUES (-999, 'fuente bibliográfica');
+INSERT INTO biblio.record_entry (marc, last_xact_id, source)
+VALUES ('<record xmlns="http://www.loc.gov/MARC21/slim"><leader>00531nam a2200157 a 4500</leader></record>', 'test', -999);
+
+SELECT is((
+            SELECT (XPATH(
+                '//marc:datafield[@tag="901"]/marc:subfield[@code="s"]/text()',
+                marc::XML,
+                ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]
+            ))[1]::TEXT
+            FROM biblio.record_entry
+            WHERE id = CURRVAL('biblio.record_entry_id_seq')
+          ),
+          'fuente bibliográfica',
+          'bibliographic source placed in 901$s');
+
+ROLLBACK;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.bib_source_in_901.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.bib_source_in_901.sql
new file mode 100644 (file)
index 0000000..9644936
--- /dev/null
@@ -0,0 +1,122 @@
+BEGIN;
+
+-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+CREATE OR REPLACE FUNCTION evergreen.maintain_901 () RETURNS TRIGGER AS $func$
+use strict;
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+use MARC::Charset;
+use Encode;
+use Unicode::Normalize;
+
+MARC::Charset->assume_unicode(1);
+
+my $schema = $_TD->{table_schema};
+my $marc = MARC::Record->new_from_xml($_TD->{new}{marc});
+
+my @old901s = $marc->field('901');
+$marc->delete_fields(@old901s);
+
+if ($schema eq 'biblio') {
+    my $tcn_value = $_TD->{new}{tcn_value};
+
+    # Set TCN value to record ID?
+    my $id_as_tcn = spi_exec_query("
+        SELECT enabled
+        FROM config.global_flag
+        WHERE name = 'cat.bib.use_id_for_tcn'
+    ");
+    if (($id_as_tcn->{processed}) && $id_as_tcn->{rows}[0]->{enabled} eq 't') {
+        $tcn_value = $_TD->{new}{id}; 
+        $_TD->{new}{tcn_value} = $tcn_value;
+    }
+
+    my $new_901 = MARC::Field->new("901", " ", " ",
+        "a" => $tcn_value,
+        "b" => $_TD->{new}{tcn_source},
+        "c" => $_TD->{new}{id},
+        "t" => $schema
+    );
+
+    if ($_TD->{new}{owner}) {
+        $new_901->add_subfields("o" => $_TD->{new}{owner});
+    }
+
+    if ($_TD->{new}{share_depth}) {
+        $new_901->add_subfields("d" => $_TD->{new}{share_depth});
+    }
+
+    if ($_TD->{new}{source}) {
+        my $plan = spi_prepare('
+            SELECT source
+            FROM config.bib_source
+            WHERE id = $1
+        ', 'INTEGER');
+        my $source_name =
+            spi_exec_prepared($plan, {limit => 1}, $_TD->{new}{source})->{rows}[0]{source};
+        spi_freeplan($plan);
+        $new_901->add_subfields("s" => $source_name) if $source_name;
+    }
+
+    $marc->append_fields($new_901);
+} elsif ($schema eq 'authority') {
+    my $new_901 = MARC::Field->new("901", " ", " ",
+        "c" => $_TD->{new}{id},
+        "t" => $schema,
+    );
+    $marc->append_fields($new_901);
+} elsif ($schema eq 'serial') {
+    my $new_901 = MARC::Field->new("901", " ", " ",
+        "c" => $_TD->{new}{id},
+        "t" => $schema,
+        "o" => $_TD->{new}{owning_lib},
+    );
+
+    if ($_TD->{new}{record}) {
+        $new_901->add_subfields("r" => $_TD->{new}{record});
+    }
+
+    $marc->append_fields($new_901);
+} else {
+    my $new_901 = MARC::Field->new("901", " ", " ",
+        "c" => $_TD->{new}{id},
+        "t" => $schema,
+    );
+    $marc->append_fields($new_901);
+}
+
+my $xml = $marc->as_xml_record();
+$xml =~ s/\n//sgo;
+$xml =~ s/^<\?xml.+\?\s*>//go;
+$xml =~ s/>\s+</></go;
+$xml =~ s/\p{Cc}//go;
+
+# Embed a version of OpenILS::Application::AppUtils->entityize()
+# to avoid having to set PERL5LIB for PostgreSQL as well
+
+$xml = NFC($xml);
+
+# Convert raw ampersands to entities
+$xml =~ s/&(?!\S+;)/&amp;/gso;
+
+# Convert Unicode characters to entities
+$xml =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
+
+$xml =~ s/[\x00-\x1f]//go;
+$_TD->{new}{marc} = $xml;
+
+return "MODIFY";
+$func$ LANGUAGE PLPERLU;
+
+COMMIT;
+
+\qecho Now running an update to set the 901$s for bibliographic
+\qecho records that have a source set. This may take a while.
+\qecho
+\qecho The update can be cancelled now \qecho and run later
+\qecho using the following SQL statement:
+\qecho
+\qecho UPDATE biblio.record_entry SET id = id WHERE source IS NOT NULL;
+\qecho
+UPDATE biblio.record_entry SET id = id WHERE source IS NOT NULL;
diff --git a/docs/RELEASE_NOTES_NEXT/Cataloging/bib_source_in_901s.txt b/docs/RELEASE_NOTES_NEXT/Cataloging/bib_source_in_901s.txt
new file mode 100644 (file)
index 0000000..2199605
--- /dev/null
@@ -0,0 +1,6 @@
+Bibliographic record source now copied to 901$s
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+If a bibliographic record has a source set, the name of that source
+is now copied to the 901$s whenever the record is created or updated.
+This allows the source to be used for record matching and MARC
+field queries.