LP 1564402: Database Function to Return ISBN13 user/dyrcona/lp1564402-evergreen-isbn13-function
authorJason Stephenson <jstephenson@mvlcstaff.org>
Thu, 31 Mar 2016 18:36:54 +0000 (14:36 -0400)
committerJason Stephenson <jstephenson@mvlcstaff.org>
Thu, 31 Mar 2016 19:18:49 +0000 (15:18 -0400)
This commit adds a database function to return the ISBN13 from a text
input.  The function is evergreen.isbn13(text).

See the release notes for more information.

Signed-off-by: Jason Stephenson <jstephenson@mvlcstaff.org>
Open-ILS/src/sql/Pg/000.functions.general.sql
Open-ILS/src/sql/Pg/t/isbn13.pg [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.function.evergreen.isbn13.sql [new file with mode: 0644]
docs/RELEASE_NOTES_NEXT/Cataloging/database_function_to_return_isbn13.adoc [new file with mode: 0644]

index ad6182e..9603fd2 100644 (file)
@@ -86,4 +86,43 @@ END
 $protect_reserved$
 LANGUAGE plpgsql;
 
+CREATE OR REPLACE FUNCTION evergreen.isbn13(text)
+  RETURNS text AS
+$BODY$
+    use Business::ISBN;
+    use strict;
+    use warnings;
+
+    my $input = shift;
+    my $output = '';
+
+    # Find the first "ISBN" in the input.
+    if ($input =~ /^\s*([0-9xX-]+)/) {
+        $input = $1;
+    }
+
+    my $isbn = Business::ISBN->new($input);
+
+    # Fix the checksum if necessary.
+    if ($isbn && $isbn->is_valid_checksum() == Business::ISBN::BAD_CHECKSUM) {
+        $isbn->fix_checksum();
+    }
+
+    # If we now have a valid ISBN, convert it to ISBN13
+    if ($isbn && $isbn->is_valid()) {
+        $output = ($isbn->type eq 'ISBN13') ? $isbn->isbn : $isbn->as_isbn13->isbn;
+    }
+    return $output if $output;
+
+    # If there was no valid ISBN, return undef;
+    return undef;
+$BODY$
+  LANGUAGE plperlu VOLATILE
+  COST 100;
+COMMENT ON FUNCTION evergreen.isbn13(text) IS '
+Takes the first ISBN-like data from a text input and returns the
+ISBN13 version or NUll if the input is invalid or cannot be translated
+to ISBN13.
+';
+
 COMMIT;
diff --git a/Open-ILS/src/sql/Pg/t/isbn13.pg b/Open-ILS/src/sql/Pg/t/isbn13.pg
new file mode 100644 (file)
index 0000000..47403db
--- /dev/null
@@ -0,0 +1,27 @@
+-- Start transaction and plan the tests.
+BEGIN;
+
+-- Number of tests that will be run
+SELECT plan(8);
+
+-- Run the tests
+
+SELECT is(evergreen.isbn13('0060530871'), '9780060530877', 'Known good ISBN10 to ISBN13');
+
+SELECT is(evergreen.isbn13('9780394577913'), '9780394577913', 'ISBN13');
+
+SELECT is(evergreen.isbn13('9780061787768 (pbk.)'), '9780061787768', 'ISBN13 with extra on the end');
+
+SELECT is(evergreen.isbn13('0061787760 (pbk.)'), '9780061787768', 'ISBN10 to ISBN13 with extra on the end');
+
+SELECT is(evergreen.isbn13('  9780061787768 (pbk.)'), '9780061787768', 'ISBN13 with leading spaces');
+
+SELECT is(evergreen.isbn13(' 0061787760 (pbk.)'), '9780061787768', 'ISBN10 to ISBN13 with leading space');
+
+SELECT is(evergreen.isbn13('$6.00'), NULL, 'Price is not an ISBN.');
+
+SELECT is(evergreen.isbn13('Eengeepo5i'), NULL, 'Random gibberish is not an ISBN.');
+
+-- Finish the test and clean up.
+SELECT * FROM finish();
+ROLLBACK;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.function.evergreen.isbn13.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.function.evergreen.isbn13.sql
new file mode 100644 (file)
index 0000000..932e07b
--- /dev/null
@@ -0,0 +1,44 @@
+BEGIN;
+
+-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); 
+
+CREATE OR REPLACE FUNCTION evergreen.isbn13(text)
+  RETURNS text AS
+$BODY$
+    use Business::ISBN;
+    use strict;
+    use warnings;
+
+    my $input = shift;
+    my $output = '';
+
+    # Find the first "ISBN" in the input.
+    if ($input =~ /^\s*([0-9xX-]+)/) {
+        $input = $1;
+    }
+
+    my $isbn = Business::ISBN->new($input);
+
+    # Fix the checksum if necessary.
+    if ($isbn && $isbn->is_valid_checksum() == Business::ISBN::BAD_CHECKSUM) {
+        $isbn->fix_checksum();
+    }
+
+    # If we now have a valid ISBN, convert it to ISBN13
+    if ($isbn && $isbn->is_valid()) {
+        $output = ($isbn->type eq 'ISBN13') ? $isbn->isbn : $isbn->as_isbn13->isbn;
+    }
+    return $output if $output;
+
+    # If there was no valid ISBN, return undef;
+    return undef;
+$BODY$
+  LANGUAGE plperlu VOLATILE
+  COST 100;
+COMMENT ON FUNCTION evergreen.isbn13(text) IS '
+Takes the first ISBN-like data from a text input and returns the
+ISBN13 version or NUll if the input is invalid or cannot be translated
+to ISBN13.
+';
+
+COMMIT;
diff --git a/docs/RELEASE_NOTES_NEXT/Cataloging/database_function_to_return_isbn13.adoc b/docs/RELEASE_NOTES_NEXT/Cataloging/database_function_to_return_isbn13.adoc
new file mode 100644 (file)
index 0000000..6f27b3f
--- /dev/null
@@ -0,0 +1,29 @@
+Database Function to Return ISBN13
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A database function, evergreen.isbn13(text), was added to return the
+ISBN13 value of the first ISBN in the input text.  The function
+expects the first non-whitespace sequence in the input to look like an
+ISBN.  If it does, it parses that as an ISBN and returns the ISBN13
+value for that ISBN.  If this sequence is not an ISBN, or if no such
+sequence is found, then NULL is returned.
+
+This function is useful if you're extracting information for a vendor
+and they require the ISBN13 and only the ISBN13.  For instance, you
+may be asked to provide a list of ISBN13, barcode, call number, and
+bibliographic record id, for some added content service.  A query like
+the one below could make use of this function to return that
+information:
+
+--------------------------
+select distinct on (isbn, itemid)
+evergreen.isbn13(mrfr.value) as isbn,
+acp.barcode as itemid,
+btrim(regexp_replace(acn.label, '[\s]+',' ','g')) as callno,
+acn.record as bibrecordid
+from asset.copy acp, asset.call_number acn, metabib.real_full_rec mrfr
+where acp.deleted = 'f'
+and acp.call_number != -1 and acp.call_number = acn.id
+and acn.record = mrfr.record and mrfr.tag = '020' and mrfr.subfield in ('a','z')
+and evergreen.isbn13(mrfr.value) is not null
+--------------------------