LP#1387722: Update MARC leader when deleting a record
authorRogan Hamby <rogan.hamby@gmail.com>
Fri, 23 Mar 2018 13:51:59 +0000 (09:51 -0400)
committerBen Shum <ben@evergreener.net>
Wed, 2 May 2018 03:06:52 +0000 (22:06 -0500)
When merging bib records, in the Leader, position 05 - Record Status
of the deleted record, the code should be changed to "d," for deleted,
as it is when a record is simply deleted within the client.

Rogan's squashed branch for updating record status in leader, along with
pgtap test and release notes.

Signed-off-by: Rogan Hamby <rogan.hamby@gmail.com>
Signed-off-by: Ben Shum <ben@evergreener.net>

Open-ILS/src/sql/Pg/010.schema.biblio.sql
Open-ILS/src/sql/Pg/t/lp1387722_record_leader_updates.pg [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/xxxx.schema.set_record_status_in_leader_trigger.sql [new file with mode: 0644]
docs/RELEASE_NOTES_NEXT/Cataloging/leader_updated_on_delete_creation_update.adoc [new file with mode: 0644]

index 857307e..7ce4490 100644 (file)
@@ -123,4 +123,36 @@ $$ LANGUAGE PLPGSQL;
 
 CREATE TRIGGER norm_sort_label BEFORE INSERT OR UPDATE ON biblio.monograph_part FOR EACH ROW EXECUTE PROCEDURE biblio.normalize_biblio_monograph_part_sortkey();
 
+CREATE OR REPLACE FUNCTION biblio.set_record_status_in_leader() RETURNS TRIGGER AS $func$
+use strict;
+use MARC::Record;
+use MARC::Field;
+use MARC::File::XML (BinaryEncoding => 'utf8');
+use Unicode::Normalize;
+
+my $old_marc = MARC::Record->new_from_xml($_TD->{new}{marc});
+my $old_leader = $old_marc->leader();
+my $old_status = substr($old_leader,5,1);
+
+my $status;
+if ($_TD->{event} eq 'INSERT') {$status = 'n';}
+elsif ($_TD->{event} eq 'UPDATE' && $_TD->{new}{deleted} eq 't') {$status = 'd';}
+elsif ($_TD->{event} eq 'UPDATE' && $_TD->{new}{deleted} eq 'f') {$status = 'c';}
+
+if ($old_status ne $status) {
+    my $marc = MARC::Record->new_from_xml($_TD->{new}{marc});
+    my $leader = $marc->leader();
+    substr($leader,5,1) = $status;
+    $marc->leader($leader);
+    my $marc_xml = $marc->as_xml_record();
+    $marc_xml = NFC($marc_xml);  
+    $_TD->{new}{marc} = $marc_xml;
+} 
+
+return "MODIFY";
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE TRIGGER set_record_status_in_leader BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.set_record_status_in_leader();
+
 COMMIT;
diff --git a/Open-ILS/src/sql/Pg/t/lp1387722_record_leader_updates.pg b/Open-ILS/src/sql/Pg/t/lp1387722_record_leader_updates.pg
new file mode 100644 (file)
index 0000000..ff845ce
--- /dev/null
@@ -0,0 +1,39 @@
+BEGIN;
+
+SELECT plan(4);
+
+----------------------------------
+-- Setup Test environment and data
+----------------------------------
+
+-- create bib 70,000
+INSERT into biblio.record_entry (id, marc, last_xact_id)
+  VALUES (70000, 
+  $$
+  <record xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd" xmlns="http://www.loc.gov/MARC21/slim"><leader>00934|jm a2200241 a 4500</leader><controlfield tag="001">03-0003745</controlfield><controlfield tag="005">19991118131708.0</controlfield><controlfield tag="008">971016n nyuuuu eng </controlfield><datafield tag="050" ind1=" " ind2=" "><subfield code="a">4539</subfield></datafield><datafield tag="100" ind1="1" ind2=" "><subfield code="a">Bart&#xF3;k, B&#xE9;la,</subfield><subfield code="d">1881-1945.</subfield></datafield><datafield tag="240" ind1=" " ind2=" "><subfield code="t">Concertos,</subfield><subfield code="m">piano,</subfield><subfield code="n">no. 1,</subfield><subfield code="n">Sz. 83</subfield><subfield code="f">(1926) </subfield><subfield code="a">Concertos,</subfield><subfield code="m">piano,</subfield><subfield code="n">no. 1,</subfield><subfield code="n">Sz. 83,</subfield><subfield code="n">(1926)</subfield></datafield><datafield tag="245" ind1=" " ind2=" "><subfield code="a">Piano concerto no. 1 (1926) ; Rhapsody, op. 1 (1904)</subfield></datafield><datafield tag="260" ind1=" " ind2=" "><subfield code="a">New York, NY :</subfield><subfield code="b">Vox</subfield></datafield></record>
+  $$,
+  'PGTAP'
+  );
+
+-----------------------------------
+-- Test biblio.set_record_status_in_leader()
+-----------------------------------
+
+-- initially the status is undefined so now it should be 'n'
+SELECT is((SELECT SUBSTR(ARRAY_TO_STRING(oils_xpath('//*[local-name()="leader"]/text()',marc),''),6,1) FROM biblio.record_entry WHERE id = 70000), 'n', 'Record is marked new.');
+
+-- check to see if it sets to 'c' correctly upon editing
+UPDATE biblio.record_entry SET marc = REPLACE(marc,'piano','dydraulophone') WHERE id = 70000;
+SELECT is((SELECT SUBSTR(ARRAY_TO_STRING(oils_xpath('//*[local-name()="leader"]/text()',marc),''),6,1) FROM biblio.record_entry WHERE id = 70000), 'c', 'Record is marked updated.');
+
+-- see if the record correctly marks as deleted 'd'
+UPDATE biblio.record_entry SET deleted = TRUE WHERE id = 70000;
+SELECT is((SELECT SUBSTR(ARRAY_TO_STRING(oils_xpath('//*[local-name()="leader"]/text()',marc),''),6,1) FROM biblio.record_entry WHERE id = 70000), 'd', 'Record is marked deleted.');
+
+-- see if the record is correctly set to 'c' when undeleted
+UPDATE biblio.record_entry SET deleted = FALSE WHERE id = 70000;
+SELECT is((SELECT SUBSTR(ARRAY_TO_STRING(oils_xpath('//*[local-name()="leader"]/text()',marc),''),6,1) FROM biblio.record_entry WHERE id = 70000), 'c', 'Record is marked updated.');
+
+SELECT * FROM finish();
+
+ROLLBACK;
diff --git a/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.set_record_status_in_leader_trigger.sql b/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.set_record_status_in_leader_trigger.sql
new file mode 100644 (file)
index 0000000..d7f7206
--- /dev/null
@@ -0,0 +1,37 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('xxxx', :eg_version);
+
+CREATE OR REPLACE FUNCTION biblio.set_record_status_in_leader() RETURNS TRIGGER AS $func$
+use strict;
+use MARC::Record;
+use MARC::Field;
+use MARC::File::XML (BinaryEncoding => 'utf8');
+use Unicode::Normalize;
+
+my $old_marc = MARC::Record->new_from_xml($_TD->{new}{marc});
+my $old_leader = $old_marc->leader();
+my $old_status = substr($old_leader,5,1);
+
+my $status;
+if ($_TD->{event} eq 'INSERT') {$status = 'n';}
+elsif ($_TD->{event} eq 'UPDATE' && $_TD->{new}{deleted} eq 't') {$status = 'd';}
+elsif ($_TD->{event} eq 'UPDATE' && $_TD->{new}{deleted} eq 'f') {$status = 'c';}
+
+if ($old_status ne $status) {
+    my $marc = MARC::Record->new_from_xml($_TD->{new}{marc});
+    my $leader = $marc->leader();
+    substr($leader,5,1) = $status;
+    $marc->leader($leader);
+    my $marc_xml = $marc->as_xml_record();
+    $marc_xml = NFC($marc_xml);  
+    $_TD->{new}{marc} = $marc_xml;
+} 
+
+return "MODIFY";
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE TRIGGER set_record_status_in_leader BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.set_record_status_in_leader();
+
+COMMIT;
diff --git a/docs/RELEASE_NOTES_NEXT/Cataloging/leader_updated_on_delete_creation_update.adoc b/docs/RELEASE_NOTES_NEXT/Cataloging/leader_updated_on_delete_creation_update.adoc
new file mode 100644 (file)
index 0000000..527ef7c
--- /dev/null
@@ -0,0 +1,7 @@
+MARC Leader Updated on Bib Deletion, Creation and Update
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+There is now a trigger in place on the bibliographic record table that 
+will update the Leader/05 when a new record is inserted, when a record 
+is updated or deleted.  On insert (created new or imported) it will be 
+marked as 'n' for new, on update (including undeletion) it will be 
+marked 'c' for modified and on deletion will be marked 'd' for deleted.