Add contrib/isn module for ISBN/ISSN/EAN13/etc product numbers, and
authorTom Lane
Sat, 9 Sep 2006 04:07:52 +0000 (04:07 +0000)
committerTom Lane
Sat, 9 Sep 2006 04:07:52 +0000 (04:07 +0000)
remove the old isbn_issn module which is about to be obsoleted by EAN13.
contrib/isn is by Germán Méndez Bravo.  Our thanks to Garrett A. Wollman
for having written the original isbn_issn module.

18 files changed:
contrib/Makefile
contrib/README
contrib/isbn_issn/Makefile [deleted file]
contrib/isbn_issn/README.isbn_issn [deleted file]
contrib/isbn_issn/isbn_issn.c [deleted file]
contrib/isbn_issn/isbn_issn.sql.in [deleted file]
contrib/isbn_issn/uninstall_isbn_issn.sql [deleted file]
contrib/isn/EAN13.h [new file with mode: 0644]
contrib/isn/ISBN.h [new file with mode: 0644]
contrib/isn/ISMN.h [new file with mode: 0644]
contrib/isn/ISSN.h [new file with mode: 0644]
contrib/isn/Makefile [new file with mode: 0644]
contrib/isn/README.isn [new file with mode: 0644]
contrib/isn/UPC.h [new file with mode: 0644]
contrib/isn/isn.c [new file with mode: 0644]
contrib/isn/isn.h [new file with mode: 0644]
contrib/isn/isn.sql.in [new file with mode: 0644]
contrib/isn/uninstall_isn.sql [new file with mode: 0644]

index acfdd1fda00b40cbafe8f2b8c05387cb5972880e..1787a1b7908a90e1d711962b353b796eca5b14f6 100644 (file)
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/contrib/Makefile,v 1.69 2006/09/05 18:00:57 teodor Exp $
+# $PostgreSQL: pgsql/contrib/Makefile,v 1.70 2006/09/09 04:07:51 tgl Exp $
 
 subdir = contrib
 top_builddir = ..
@@ -12,10 +12,10 @@ WANTED_DIRS = \
        dblink      \
        earthdistance   \
        fuzzystrmatch   \
-       hstore          \
+       hstore      \
        intagg      \
        intarray    \
-       isbn_issn   \
+       isn     \
        lo      \
        ltree       \
        oid2name    \
index 6b15b70b2b22b6108150b361069d01f9366ba088..d6067d44dce0fbdcdde21421563da871675bf828 100644 (file)
@@ -64,9 +64,9 @@ intarray -
    Index support for arrays of int4, using GiST
    by Teodor Sigaev  and Oleg Bartunov 
 
-isbn_issn -
-   PostgreSQL type extensions for ISBN (books) and ISSN (serials)
-   by Garrett A. Wollman >
+isn -
+   PostgreSQL type extensions for ISBN, ISSN, ISMN, EAN13 product numbers
+   by Germán Méndez Bravo (Kronuz) >
 
 lo -
    Large Object maintenance
diff --git a/contrib/isbn_issn/Makefile b/contrib/isbn_issn/Makefile
deleted file mode 100644 (file)
index c208d9b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# $PostgreSQL: pgsql/contrib/isbn_issn/Makefile,v 1.15 2006/02/27 12:54:39 petere Exp $
-
-MODULES = isbn_issn
-DATA_built = isbn_issn.sql
-DATA = uninstall_isbn_issn.sql
-DOCS = README.isbn_issn
-
-ifdef USE_PGXS
-PGXS := $(shell pg_config --pgxs)
-include $(PGXS)
-else
-subdir = contrib/isbn_issn
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/isbn_issn/README.isbn_issn b/contrib/isbn_issn/README.isbn_issn
deleted file mode 100644 (file)
index 6b734ce..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-ISBN (books) and ISSN (serials)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This directory contains definitions for a couple of PostgreSQL
-external types, for a couple of international-standard namespaces:
-ISBN (books) and ISSN (serials).  Rather than just using a char()
-member of the appropriate length, I wanted my database to include
-the validity-checking that both these numbering systems were designed
-to encompass.  A little bit of research revealed the formulae
-for computing the check digits, and I also included some validity
-constraints on the number of hyphens.
-
-The internal representation of these types is intended to be
-compatible with `char16', in the (perhaps vain) hope that
-this will make it possible to create indices of these types
-using char16_ops.
-
-These are based on Tom Ivar Helbekkmo's IP address type definition,
-from which I have copied the entire form of the implementation.
-
-Garrett A. Wollman, August 1998
diff --git a/contrib/isbn_issn/isbn_issn.c b/contrib/isbn_issn/isbn_issn.c
deleted file mode 100644 (file)
index 7f84951..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * PostgreSQL type definitions for ISBNs.
- *
- * $PostgreSQL: pgsql/contrib/isbn_issn/isbn_issn.c,v 1.9 2006/05/30 22:12:13 tgl Exp $
- */
-
-#include "postgres.h"
-
-#include "fmgr.h"
-
-
-PG_MODULE_MAGIC;
-
-/*
- * This is the internal storage format for ISBNs.
- * NB: This is an intentional type pun with builtin type `char16'.
- */
-
-typedef struct isbn
-{
-   char        num[13];
-   char        pad[3];
-}  isbn;
-
-/*
- * Various forward declarations:
- */
-
-isbn      *isbn_in(char *str);
-char      *isbn_out(isbn * addr);
-
-bool       isbn_lt(isbn * a1, isbn * a2);
-bool       isbn_le(isbn * a1, isbn * a2);
-bool       isbn_eq(isbn * a1, isbn * a2);
-bool       isbn_ge(isbn * a1, isbn * a2);
-bool       isbn_gt(isbn * a1, isbn * a2);
-
-bool       isbn_ne(isbn * a1, isbn * a2);
-
-int4       isbn_cmp(isbn * a1, isbn * a2);
-
-int4       isbn_sum(char *str);
-
-/*
- * ISBN reader.
- */
-
-isbn *
-isbn_in(char *str)
-{
-   isbn       *result;
-   int         len;
-
-   len = strlen(str);
-   if (len != 13)
-       ereport(ERROR,
-               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                errmsg("invalid ISBN: \"%s\"", str),
-                errdetail("ISBNs must be 13 characters in length.")));
-
-   if (isbn_sum(str) != 0)
-       ereport(ERROR,
-               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                errmsg("invalid ISBN: \"%s\"", str),
-                errdetail("ISBN failed checksum.")));
-
-   result = (isbn *) palloc(sizeof(isbn));
-   memcpy(result->num, str, len);
-   memset(result->pad, ' ', 3);
-   return (result);
-}
-
-/*
- * The ISBN checksum is defined as follows:
- *
- * Number the digits from 1 to 9 (call this N).
- * Compute the sum, S, of N * D_N.
- * The check digit, C, is the value which satisfies the equation
- * S + 10*C === 0 (mod 11)
- * The value 10 for C is written as `X'.
- *
- * For our purposes, we want the complete sum including the check
- * digit; if this is zero, then the checksum passed.  We also check
- * the syntactic validity if the provided string, and return 12
- * if any errors are found.
- */
-int4
-isbn_sum(char *str)
-{
-   int4        sum = 0,
-               dashes = 0,
-               val;
-   int         i;
-
-   for (i = 0; str[i] && i < 13; i++)
-   {
-       switch (str[i])
-       {
-           case '-':
-               if (++dashes > 3)
-                   return 12;
-               continue;
-
-           case '0':
-           case '1':
-           case '2':
-           case '3':
-           case '4':
-           case '5':
-           case '6':
-           case '7':
-           case '8':
-           case '9':
-               val = str[i] - '0';
-               break;
-
-           case 'X':
-           case 'x':
-               val = 10;
-               break;
-
-           default:
-               return 12;
-       }
-
-       sum += val * (i + 1 - dashes);
-   }
-   return (sum % 11);
-}
-
-/*
- * ISBN output function.
- */
-
-char *
-isbn_out(isbn * num)
-{
-   char       *result;
-
-   if (num == NULL)
-       return (NULL);
-
-   result = (char *) palloc(14);
-
-   result[0] = '\0';
-   strncat(result, num->num, 13);
-   return (result);
-}
-
-/*
- * Boolean tests for magnitude.
- */
-
-bool
-isbn_lt(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) < 0);
-}
-
-bool
-isbn_le(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) <= 0);
-}
-
-bool
-isbn_eq(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) == 0);
-}
-
-bool
-isbn_ge(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) >= 0);
-}
-
-bool
-isbn_gt(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) > 0);
-}
-
-bool
-isbn_ne(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13) != 0);
-}
-
-/*
- * Comparison function for sorting:
- */
-
-int4
-isbn_cmp(isbn * a1, isbn * a2)
-{
-   return (strncmp(a1->num, a2->num, 13));
-}
-
-
-/* ----------------------------- ISSN --------------------------- */
-
-/*
- * This is the internal storage format for ISSNs.
- * NB: This is an intentional type pun with builtin type `char16'.
- */
-
-typedef struct issn
-{
-   char        num[9];
-   char        pad[7];
-}  issn;
-
-/*
- * Various forward declarations:
- */
-
-issn      *issn_in(char *str);
-char      *issn_out(issn * addr);
-
-bool       issn_lt(issn * a1, issn * a2);
-bool       issn_le(issn * a1, issn * a2);
-bool       issn_eq(issn * a1, issn * a2);
-bool       issn_ge(issn * a1, issn * a2);
-bool       issn_gt(issn * a1, issn * a2);
-
-bool       issn_ne(issn * a1, issn * a2);
-
-int4       issn_cmp(issn * a1, issn * a2);
-
-int4       issn_sum(char *str);
-
-/*
- * ISSN reader.
- */
-
-issn *
-issn_in(char *str)
-{
-   issn       *result;
-   int         len;
-
-   len = strlen(str);
-   if (len != 9)
-       ereport(ERROR,
-               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                errmsg("invalid ISSN: \"%s\"", str),
-                errdetail("ISSNs must be 9 characters in length.")));
-
-   if (issn_sum(str) != 0)
-       ereport(ERROR,
-               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                errmsg("invalid ISSN: \"%s\"", str),
-                errdetail("ISSN failed checksum.")));
-
-   result = (issn *) palloc(sizeof(issn));
-   memcpy(result->num, str, len);
-   memset(result->pad, ' ', 7);
-   return (result);
-}
-
-/*
- * The ISSN checksum works just like the ISBN sum, only different
- * (of course!).
- * Here, the weights start at 8 and decrease.
- */
-int4
-issn_sum(char *str)
-{
-   int4        sum = 0,
-               dashes = 0,
-               val;
-   int         i;
-
-   for (i = 0; str[i] && i < 9; i++)
-   {
-       switch (str[i])
-       {
-           case '-':
-               if (++dashes > 1)
-                   return 12;
-               continue;
-
-           case '0':
-           case '1':
-           case '2':
-           case '3':
-           case '4':
-           case '5':
-           case '6':
-           case '7':
-           case '8':
-           case '9':
-               val = str[i] - '0';
-               break;
-
-           case 'X':
-           case 'x':
-               val = 10;
-               break;
-
-           default:
-               return 12;
-       }
-
-       sum += val * (8 - (i - dashes));
-   }
-   return (sum % 11);
-}
-
-/*
- * ISSN output function.
- */
-
-char *
-issn_out(issn * num)
-{
-   char       *result;
-
-   if (num == NULL)
-       return (NULL);
-
-   result = (char *) palloc(14);
-
-   result[0] = '\0';
-   strncat(result, num->num, 9);
-   return (result);
-}
-
-/*
- * Boolean tests for magnitude.
- */
-
-bool
-issn_lt(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) < 0);
-}
-
-bool
-issn_le(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) <= 0);
-}
-
-bool
-issn_eq(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) == 0);
-}
-
-bool
-issn_ge(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) >= 0);
-}
-
-bool
-issn_gt(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) > 0);
-}
-
-bool
-issn_ne(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9) != 0);
-}
-
-/*
- * Comparison function for sorting:
- */
-
-int4
-issn_cmp(issn * a1, issn * a2)
-{
-   return (strncmp(a1->num, a2->num, 9));
-}
diff --git a/contrib/isbn_issn/isbn_issn.sql.in b/contrib/isbn_issn/isbn_issn.sql.in
deleted file mode 100644 (file)
index 1fb0b5f..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
---
--- PostgreSQL code for ISSNs.
---
--- $PostgreSQL: pgsql/contrib/isbn_issn/isbn_issn.sql.in,v 1.12 2006/02/27 16:09:48 petere Exp $
---
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
---
--- Input and output functions and the type itself:
---
-
-CREATE FUNCTION issn_in(cstring)
-RETURNS issn
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_out(issn)
-RETURNS cstring
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE TYPE issn (
-   INTERNALLENGTH = 16,
-   EXTERNALLENGTH = 9,
-   INPUT = issn_in,
-   OUTPUT = issn_out
-);
-
-COMMENT ON TYPE issn
-  is 'International Standard Serial Number';
-
-
---
--- The various boolean tests:
---
-
-CREATE FUNCTION issn_lt(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_le(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_eq(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_ge(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_gt(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION issn_ne(issn, issn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
---
--- Now the operators.  Note how some of the parameters to some
--- of the 'create operator' commands are commented out.  This
--- is because they reference as yet undefined operators, and
--- will be implicitly defined when those are, further down.
---
-
-CREATE OPERATOR < (
-   LEFTARG = issn,
-   RIGHTARG = issn,
--- NEGATOR = >=,
-   PROCEDURE = issn_lt
-);
-
-CREATE OPERATOR <= (
-   LEFTARG = issn,
-   RIGHTARG = issn,
--- NEGATOR = >,
-   PROCEDURE = issn_le
-);
-
-CREATE OPERATOR = (
-   LEFTARG = issn,
-   RIGHTARG = issn,
-   COMMUTATOR = =,
--- NEGATOR = <>,
-   PROCEDURE = issn_eq
-);
-
-CREATE OPERATOR >= (
-   LEFTARG = issn,
-   RIGHTARG = issn,
-   NEGATOR = <,
-   PROCEDURE = issn_ge
-);
-
-CREATE OPERATOR > (
-   LEFTARG = issn,
-   RIGHTARG = issn,
-   NEGATOR = <=,
-   PROCEDURE = issn_gt
-);
-
-CREATE OPERATOR <> (
-   LEFTARG = issn,
-   RIGHTARG = issn,
-   NEGATOR = =,
-   PROCEDURE = issn_ne
-);
-
--- Register 'issn' comparison function
-CREATE FUNCTION issn_cmp(issn, issn)
-RETURNS integer
-AS '$libdir/isbn_issn'
-LANGUAGE C STRICT;
-
--- Create default operator class for 'issn'    --
--- Needed to create index or primary key       --
-
-CREATE OPERATOR CLASS issn_ops
-DEFAULT FOR TYPE issn USING btree 
-AS
-        OPERATOR        1       < ,
-        OPERATOR        2       <= ,
-        OPERATOR        3       = ,
-        OPERATOR        4       >= ,
-        OPERATOR        5       > ,
-        FUNCTION        1       issn_cmp(issn, issn);
-
-
-------------------------------------------------------------------------
-
---
--- Same code for ISBN
---
--- Input and output functions and the type itself:
---
-
-CREATE FUNCTION isbn_in(cstring)
-RETURNS isbn
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_out(isbn)
-RETURNS cstring
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE TYPE isbn (
-   INTERNALLENGTH = 16,
-   EXTERNALLENGTH = 13,
-   INPUT = isbn_in,
-   OUTPUT = isbn_out
-);
-
-COMMENT ON TYPE isbn IS 'International Standard Book Number';
-
-
---
--- The various boolean tests:
---
-
-CREATE FUNCTION isbn_lt(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_le(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_eq(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_ge(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_gt(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE FUNCTION isbn_ne(isbn, isbn)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
---
--- Now the operators.  Note how some of the parameters to some
--- of the 'create operator' commands are commented out.  This
--- is because they reference as yet undefined operators, and
--- will be implicitly defined when those are, further down.
---
-
-CREATE OPERATOR < (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
--- NEGATOR = >=,
-   PROCEDURE = isbn_lt
-);
-
-CREATE OPERATOR <= (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
--- NEGATOR = >,
-   PROCEDURE = isbn_le
-);
-
-CREATE OPERATOR = (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
-   COMMUTATOR = =,
--- NEGATOR = <>,
-   PROCEDURE = isbn_eq
-);
-
-CREATE OPERATOR >= (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
-   NEGATOR = <,
-   PROCEDURE = isbn_ge
-);
-
-CREATE OPERATOR > (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
-   NEGATOR = <=,
-   PROCEDURE = isbn_gt
-);
-
-CREATE OPERATOR <> (
-   LEFTARG = isbn,
-   RIGHTARG = isbn,
-   NEGATOR = =,
-   PROCEDURE = isbn_ne
-);
-
-
--- Register 'isbn' comparison function
-CREATE FUNCTION isbn_cmp(isbn, isbn)
-RETURNS integer
-AS '$libdir/isbn_issn'
-LANGUAGE C STRICT;
-
--- Create default operator class for 'isbn'    --
--- Needed to create index or primary key       --
-
-CREATE OPERATOR CLASS isbn_ops
-DEFAULT FOR TYPE isbn USING btree 
-AS
-        OPERATOR        1       < ,
-        OPERATOR        2       <= ,
-        OPERATOR        3       = ,
-        OPERATOR        4       >= ,
-        OPERATOR        5       > ,
-        FUNCTION        1       isbn_cmp(isbn, isbn);
diff --git a/contrib/isbn_issn/uninstall_isbn_issn.sql b/contrib/isbn_issn/uninstall_isbn_issn.sql
deleted file mode 100644 (file)
index 07a26f3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-SET search_path = public;
-
-DROP OPERATOR CLASS isbn_ops USING btree;
-
-DROP FUNCTION isbn_cmp(isbn, isbn);
-
-DROP OPERATOR <> (isbn, isbn);
-
-DROP OPERATOR > (isbn, isbn);
-
-DROP OPERATOR >= (isbn, isbn);
-
-DROP OPERATOR = (isbn, isbn);
-
-DROP OPERATOR <= (isbn, isbn);
-
-DROP OPERATOR < (isbn, isbn);
-
-DROP FUNCTION isbn_ne(isbn, isbn);
-
-DROP FUNCTION isbn_gt(isbn, isbn);
-
-DROP FUNCTION isbn_ge(isbn, isbn);
-
-DROP FUNCTION isbn_eq(isbn, isbn);
-
-DROP FUNCTION isbn_le(isbn, isbn);
-
-DROP FUNCTION isbn_lt(isbn, isbn);
-
-DROP TYPE isbn CASCADE;
-
-DROP OPERATOR CLASS issn_ops USING btree;
-
-DROP FUNCTION issn_cmp(issn, issn);
-
-DROP OPERATOR <> (issn, issn);
-
-DROP OPERATOR > (issn, issn);
-
-DROP OPERATOR >= (issn, issn);
-
-DROP OPERATOR = (issn, issn);
-
-DROP OPERATOR <= (issn, issn);
-
-DROP OPERATOR < (issn, issn);
-
-DROP FUNCTION issn_ne(issn, issn);
-
-DROP FUNCTION issn_gt(issn, issn);
-
-DROP FUNCTION issn_ge(issn, issn);
-
-DROP FUNCTION issn_eq(issn, issn);
-
-DROP FUNCTION issn_le(issn, issn);
-
-DROP FUNCTION issn_lt(issn, issn);
-
-DROP TYPE issn CASCADE;
diff --git a/contrib/isn/EAN13.h b/contrib/isn/EAN13.h
new file mode 100644 (file)
index 0000000..43886c2
--- /dev/null
@@ -0,0 +1,147 @@
+/* 
+ * EAN13.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Information recompiled by Kronuz on August 23, 2006
+ * http://www.gs1.org/productssolutions/idkeys/support/prefix_list.html
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/EAN13.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned EAN13_index[10][2] = {
+   {0,     6},
+   {6,     1},
+   {7,     1},
+   {8,     5},
+   {13,    20},
+   {33,    15},
+   {48,    19},
+   {67,    23},
+   {90,    17},
+   {107,   12},
+};
+const char *EAN13_range[][2] = {
+   {"000", "019"}, /* GS1 US */
+   {"020", "029"}, /* Restricted distribution (MO defined) */
+   {"030", "039"}, /* GS1 US */
+   {"040", "049"}, /* Restricted distribution (MO defined) */
+   {"050", "059"}, /* Coupons */
+   {"060", "099"}, /* GS1 US */
+   {"100", "139"}, /* GS1 US */
+   {"200", "299"}, /* Restricted distribution (MO defined) */
+   {"300", "379"}, /* GS1 France */
+   {"380", "380"}, /* GS1 Bulgaria */
+   {"383", "383"}, /* GS1 Slovenija */
+   {"385", "385"}, /* GS1 Croatia */
+   {"387", "387"}, /* GS1 BIH (Bosnia-Herzegovina) */
+   {"400", "440"}, /* GS1 Germany */
+   {"450", "459"}, /* GS1 Japan */
+   {"460", "469"}, /* GS1 Russia */
+   {"470", "470"}, /* GS1 Kyrgyzstan */
+   {"471", "471"}, /* GS1 Taiwan */
+   {"474", "474"}, /* GS1 Estonia */
+   {"475", "475"}, /* GS1 Latvia */
+   {"476", "476"}, /* GS1 Azerbaijan */
+   {"477", "477"}, /* GS1 Lithuania */
+   {"478", "478"}, /* GS1 Uzbekistan */
+   {"479", "479"}, /* GS1 Sri Lanka */
+   {"480", "480"}, /* GS1 Philippines */
+   {"481", "481"}, /* GS1 Belarus */
+   {"482", "482"}, /* GS1 Ukraine */
+   {"484", "484"}, /* GS1 Moldova */
+   {"485", "485"}, /* GS1 Armenia */
+   {"486", "486"}, /* GS1 Georgia */
+   {"487", "487"}, /* GS1 Kazakstan */
+   {"489", "489"}, /* GS1 Hong Kong */
+   {"490", "499"}, /* GS1 Japan */
+   {"500", "509"}, /* GS1 UK */
+   {"520", "520"}, /* GS1 Greece */
+   {"528", "528"}, /* GS1 Lebanon */
+   {"529", "529"}, /* GS1 Cyprus */
+   {"530", "530"}, /* GS1 Albania */
+   {"531", "531"}, /* GS1 MAC (FYR Macedonia) */
+   {"535", "535"}, /* GS1 Malta */
+   {"539", "539"}, /* GS1 Ireland */
+   {"540", "549"}, /* GS1 Belgium & Luxembourg */
+   {"560", "560"}, /* GS1 Portugal */
+   {"569", "569"}, /* GS1 Iceland */
+   {"570", "579"}, /* GS1 Denmark */
+   {"590", "590"}, /* GS1 Poland */
+   {"594", "594"}, /* GS1 Romania */
+   {"599", "599"}, /* GS1 Hungary */
+   {"600", "601"}, /* GS1 South Africa */
+   {"603", "603"}, /* GS1 Ghana */
+   {"608", "608"}, /* GS1 Bahrain */
+   {"609", "609"}, /* GS1 Mauritius */
+   {"611", "611"}, /* GS1 Morocco */
+   {"613", "613"}, /* GS1 Algeria */
+   {"616", "616"}, /* GS1 Kenya */
+   {"618", "618"}, /* GS1 Ivory Coast */
+   {"619", "619"}, /* GS1 Tunisia */
+   {"621", "621"}, /* GS1 Syria */
+   {"622", "622"}, /* GS1 Egypt */
+   {"624", "624"}, /* GS1 Libya */
+   {"625", "625"}, /* GS1 Jordan */
+   {"626", "626"}, /* GS1 Iran */
+   {"627", "627"}, /* GS1 Kuwait */
+   {"628", "628"}, /* GS1 Saudi Arabia */
+   {"629", "629"}, /* GS1 Emirates */
+   {"640", "649"}, /* GS1 Finland */
+   {"690", "695"}, /* GS1 China */
+   {"700", "709"}, /* GS1 Norway */
+   {"729", "729"}, /* GS1 Israel */
+   {"730", "739"}, /* GS1 Sweden */
+   {"740", "740"}, /* GS1 Guatemala */
+   {"741", "741"}, /* GS1 El Salvador */
+   {"742", "742"}, /* GS1 Honduras */
+   {"743", "743"}, /* GS1 Nicaragua */
+   {"744", "744"}, /* GS1 Costa Rica */
+   {"745", "745"}, /* GS1 Panama */
+   {"746", "746"}, /* GS1 Republica Dominicana */
+   {"750", "750"}, /* GS1 Mexico */
+   {"754", "755"}, /* GS1 Canada */
+   {"759", "759"}, /* GS1 Venezuela */
+   {"760", "769"}, /* GS1 Schweiz, Suisse, Svizzera */
+   {"770", "770"}, /* GS1 Colombia */
+   {"773", "773"}, /* GS1 Uruguay */
+   {"775", "775"}, /* GS1 Peru */
+   {"777", "777"}, /* GS1 Bolivia */
+   {"779", "779"}, /* GS1 Argentina */
+   {"780", "780"}, /* GS1 Chile */
+   {"784", "784"}, /* GS1 Paraguay */
+   {"786", "786"}, /* GS1 Ecuador */
+   {"789", "790"}, /* GS1 Brasil */
+   {"800", "839"}, /* GS1 Italy */
+   {"840", "849"}, /* GS1 Spain */
+   {"850", "850"}, /* GS1 Cuba */
+   {"858", "858"}, /* GS1 Slovakia */
+   {"859", "859"}, /* GS1 Czech */
+   {"860", "860"}, /* GS1 YU (Serbia & Montenegro) */
+   {"865", "865"}, /* GS1 Mongolia */
+   {"867", "867"}, /* GS1 North Korea */
+   {"869", "869"}, /* GS1 Turkey */
+   {"870", "879"}, /* GS1 Netherlands */
+   {"880", "880"}, /* GS1 South Korea */
+   {"884", "884"}, /* GS1 Cambodia */
+   {"885", "885"}, /* GS1 Thailand */
+   {"888", "888"}, /* GS1 Singapore */
+   {"890", "890"}, /* GS1 India */
+   {"893", "893"}, /* GS1 Vietnam */
+   {"899", "899"}, /* GS1 Indonesia */
+   {"900", "919"}, /* GS1 Austria */
+   {"930", "939"}, /* GS1 Australia */
+   {"940", "949"}, /* GS1 New Zealand */
+   {"950", "950"}, /* GS1 Head Office */
+   {"955", "955"}, /* GS1 Malaysia */
+   {"958", "958"}, /* GS1 Macau */
+   {"977", "977"}, /* Serial publications (ISSN) */
+   {"978", "978"}, /* Bookland (ISBN) */
+   {"979", "979"}, /* International Standard Music Number (ISMN) and ISBN contingent */
+   {"980", "980"}, /* Refund receipts */
+   {"981", "982"}, /* Common Currency Coupons */
+   {"990", "999"}, /* Coupons */
+   {NULL, NULL}
+};
diff --git a/contrib/isn/ISBN.h b/contrib/isn/ISBN.h
new file mode 100644 (file)
index 0000000..0b23a95
--- /dev/null
@@ -0,0 +1,732 @@
+/* 
+ * ISBN.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Information recompiled by Kronuz on June 20, 2006
+ * http://www.isbn-international.org/
+ * http://www.isbn.org/
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/ISBN.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ * 0-393-04002-X => 039304002(X) <=> 039304002 <=> (978)039304002 <=> 978039304002(9) <=> 978-0-393-04002-9
+ *
+ *
+ * ISBN         0   3    9    3    0   4    0   0   2
+ * Weight       10  9    8    7    6   5    4   3   2
+ * Product      0 + 27 + 72 + 21 + 0 + 20 + 0 + 0 + 4 = 144
+ *              144 / 11 = 13 remainder 1
+ * Check digit  11 - 1 = 10 = X
+ * => 0-393-04002-X
+ *
+ * ISBN         9   7    8   0   3   9    3   0   4   0   0   2
+ * Weight       1   3    1   3   1   3    1   3   1   3   1   3
+ * Product      9 + 21 + 8 + 0 + 3 + 27 + 3 + 0 + 4 + 0 + 0 + 6 = 81
+ *              81 / 10 = 8 remainder 1
+ * Check digit  10 - 1 = 9
+ * => 978-0-393-04002-9
+ *
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned ISBN_index[10][2] = {
+   {0,     6},
+   {6,     6},
+   {12,    8},
+   {20,    10},
+   {30,    6},
+   {36,    12},
+   {48,    0},
+   {48,    5},
+   {53,    59},
+   {112,   573},
+};
+
+const char *ISBN_range[][2] = {
+   {"0-00", "0-19"},
+   {"0-200", "0-699"},
+   {"0-7000", "0-8499"},
+   {"0-85000", "0-89999"},
+   {"0-900000", "0-949999"},
+   {"0-9500000", "0-9999999"},
+   {"1-00", "1-09"},
+   {"1-100", "1-399"},
+   {"1-4000", "1-5499"},
+   {"1-55000", "1-86979"},
+   {"1-869800", "1-998999"},
+   {"1-9990000", "1-9999999"},
+   {"2-00", "2-19"},
+   {"2-200", "2-349"},
+   {"2-35000", "2-39999"},
+   {"2-400", "2-699"},
+   {"2-7000", "2-8399"},
+   {"2-84000", "2-89999"},
+   {"2-900000", "2-949999"},
+   {"2-9500000", "2-9999999"},
+   {"3-00", "3-02"},
+   {"3-030", "3-033"},
+   {"3-0340", "3-0369"},
+   {"3-03700", "3-03999"},
+   {"3-04", "3-19"},
+   {"3-200", "3-699"},
+   {"3-7000", "3-8499"},
+   {"3-85000", "3-89999"},
+   {"3-900000", "3-949999"},
+   {"3-9500000", "3-9999999"},
+   {"4-00", "4-19"},
+   {"4-200", "4-699"},
+   {"4-7000", "4-8499"},
+   {"4-85000", "4-89999"},
+   {"4-900000", "4-949999"},
+   {"4-9500000", "4-9999999"},
+   {"5-00", "5-19"},
+   {"5-200", "5-699"},
+   {"5-7000", "5-8499"},
+   {"5-85000", "5-89999"},
+   {"5-900000", "5-909999"},
+   {"5-91000", "5-91999"},
+   {"5-9200", "5-9299"},
+   {"5-93000", "5-94999"},
+   {"5-9500", "5-9799"},
+   {"5-98000", "5-98999"},
+   {"5-9900000", "5-9909999"},
+   {"5-9910", "5-9999"},
+   {"7-00", "7-09"},
+   {"7-100", "7-499"},
+   {"7-5000", "7-7999"},
+   {"7-80000", "7-89999"},
+   {"7-900000", "7-999999"},
+   {"80-00", "80-19"},
+   {"80-200", "80-699"},
+   {"80-7000", "80-8499"},
+   {"80-85000", "80-89999"},
+   {"80-900000", "80-999999"},
+   {"81-00", "81-19"},
+   {"81-200", "81-699"},
+   {"81-7000", "81-8499"},
+   {"81-85000", "81-89999"},
+   {"81-900000", "81-999999"},
+   {"82-00", "82-19"},
+   {"82-200", "82-699"},
+   {"82-7000", "82-8999"},
+   {"82-90000", "82-98999"},
+   {"82-990000", "82-999999"},
+   {"83-00", "83-19"},
+   {"83-200", "83-599"},
+   {"83-60000", "83-69999"},
+   {"83-7000", "83-8499"},
+   {"83-85000", "83-89999"},
+   {"83-900000", "83-999999"},
+   {"84-00", "84-19"},
+   {"84-200", "84-699"},
+   {"84-7000", "84-8499"},
+   {"84-85000", "84-89999"},
+   {"84-9000", "84-9199"},
+   {"84-920000", "84-923999"},
+   {"84-92400", "84-92999"},
+   {"84-930000", "84-949999"},
+   {"84-95000", "84-96999"},
+   {"84-9700", "84-9999"},
+   {"85-00", "85-19"},
+   {"85-200", "85-599"},
+   {"85-60000", "85-69999"},
+   {"85-7000", "85-8499"},
+   {"85-85000", "85-89999"},
+   {"85-900000", "85-979999"},
+   {"85-98000", "85-99999"},
+   {"86-00", "86-29"},
+   {"86-300", "86-699"},
+   {"86-7000", "86-7999"},
+   {"86-80000", "86-89999"},
+   {"86-900000", "86-999999"},
+   {"87-00", "87-29"},
+   {"87-400", "87-649"},
+   {"87-7000", "87-7999"},
+   {"87-85000", "87-94999"},
+   {"87-970000", "87-999999"},
+   {"88-00", "88-19"},
+   {"88-200", "88-599"},
+   {"88-6000", "88-8499"},
+   {"88-85000", "88-89999"},
+   {"88-900000", "88-949999"},
+   {"88-95000", "88-99999"},
+   {"89-00", "89-24"},
+   {"89-250", "89-549"},
+   {"89-5500", "89-8499"},
+   {"89-85000", "89-94999"},
+   {"89-950000", "89-999999"},
+   {"90-00", "90-19"},
+   {"90-200", "90-499"},
+   {"90-5000", "90-6999"},
+   {"90-70000", "90-79999"},
+   {"90-800000", "90-849999"},
+   {"90-8500", "90-8999"},
+   {"90-900000", "90-909999"},
+   {"90-940000", "90-949999"},
+   {"91-0", "91-1"},
+   {"91-20", "91-49"},
+   {"91-500", "91-649"},
+   {"91-7000", "91-7999"},
+   {"91-85000", "91-94999"},
+   {"91-970000", "91-999999"},
+   {"92-0", "92-5"},
+   {"92-60", "92-79"},
+   {"92-800", "92-899"},
+   {"92-9000", "92-9499"},
+   {"92-95000", "92-98999"},
+   {"92-990000", "92-999999"},
+   {"950-00", "950-49"},
+   {"950-500", "950-899"},
+   {"950-9000", "950-9899"},
+   {"950-99000", "950-99999"},
+   {"951-0", "951-1"},
+   {"951-20", "951-54"},
+   {"951-550", "951-889"},
+   {"951-8900", "951-9499"},
+   {"951-95000", "951-99999"},
+   {"952-00", "952-19"},
+   {"952-200", "952-499"},
+   {"952-5000", "952-5999"},
+   {"952-60", "952-65"},
+   {"952-6600", "952-6699"},
+   {"952-67000", "952-69999"},
+   {"952-7000", "952-7999"},
+   {"952-89", "952-94"},
+   {"952-9500", "952-9899"},
+   {"952-99000", "952-99999"},
+   {"953-0", "953-0"},
+   {"953-10", "953-14"},
+   {"953-150", "953-599"},
+   {"953-6000", "953-9499"},
+   {"953-95000", "953-99999"},
+   {"954-00", "954-29"},
+   {"954-300", "954-799"},
+   {"954-8000", "954-8999"},
+   {"954-90000", "954-92999"},
+   {"954-9300", "954-9999"},
+   {"955-0", "955-0"},
+   {"955-1000", "955-1999"},
+   {"955-20", "955-54"},
+   {"955-550", "955-799"},
+   {"955-8000", "955-9499"},
+   {"955-95000", "955-99999"},
+   {"956-00", "956-19"},
+   {"956-200", "956-699"},
+   {"956-7000", "956-9999"},
+   {"957-00", "957-02"},
+   {"957-0300", "957-0499"},
+   {"957-05", "957-19"},
+   {"957-2000", "957-2099"},
+   {"957-21", "957-27"},
+   {"957-28000", "957-30999"},
+   {"957-31", "957-43"},
+   {"957-440", "957-819"},
+   {"957-8200", "957-9699"},
+   {"957-97000", "957-99999"},
+   {"958-00", "958-59"},
+   {"958-600", "958-799"},
+   {"958-8000", "958-9499"},
+   {"958-95000", "958-99999"},
+   {"959-00", "959-19"},
+   {"959-200", "959-699"},
+   {"959-7000", "959-8499"},
+   {"960-00", "960-19"},
+   {"960-200", "960-659"},
+   {"960-6600", "960-6899"},
+   {"960-690", "960-699"},
+   {"960-7000", "960-8499"},
+   {"960-85000", "960-99999"},
+   {"961-00", "961-19"},
+   {"961-200", "961-599"},
+   {"961-6000", "961-8999"},
+   {"961-90000", "961-94999"},
+   {"962-00", "962-19"},
+   {"962-200", "962-699"},
+   {"962-7000", "962-8499"},
+   {"962-85000", "962-86999"},
+   {"962-8700", "962-8999"},
+   {"962-900", "962-999"},
+   {"963-00", "963-19"},
+   {"963-200", "963-699"},
+   {"963-7000", "963-8499"},
+   {"963-85000", "963-89999"},
+   {"963-9000", "963-9999"},
+   {"964-00", "964-14"},
+   {"964-150", "964-249"},
+   {"964-2500", "964-2999"},
+   {"964-300", "964-549"},
+   {"964-5500", "964-8999"},
+   {"964-90000", "964-96999"},
+   {"964-970", "964-989"},
+   {"964-9900", "964-9999"},
+   {"965-00", "965-19"},
+   {"965-200", "965-599"},
+   {"965-7000", "965-7999"},
+   {"965-90000", "965-99999"},
+   {"966-00", "966-28"},
+   {"966-2900", "966-2999"},
+   {"966-300", "966-699"},
+   {"966-7000", "966-8999"},
+   {"966-90000", "966-99999"},
+   {"967-0", "967-5"},
+   {"967-60", "967-89"},
+   {"967-900", "967-989"},
+   {"967-9900", "967-9989"},
+   {"967-99900", "967-99999"},
+   {"968-01", "968-39"},
+   {"968-400", "968-499"},
+   {"968-5000", "968-7999"},
+   {"968-800", "968-899"},
+   {"968-9000", "968-9999"},
+   {"969-0", "969-1"},
+   {"969-20", "969-39"},
+   {"969-400", "969-799"},
+   {"969-8000", "969-9999"},
+   {"970-01", "970-59"},
+   {"970-600", "970-899"},
+   {"970-9000", "970-9099"},
+   {"970-91000", "970-96999"},
+   {"970-9700", "970-9999"},
+   {"971-000", "971-019"},
+   {"971-02", "971-02"},
+   {"971-0300", "971-0599"},
+   {"971-06", "971-09"},
+   {"971-10", "971-49"},
+   {"971-500", "971-849"},
+   {"971-8500", "971-9099"},
+   {"971-91000", "971-99999"},
+   {"972-0", "972-1"},
+   {"972-20", "972-54"},
+   {"972-550", "972-799"},
+   {"972-8000", "972-9499"},
+   {"972-95000", "972-99999"},
+   {"973-0", "973-0"},
+   {"973-100", "973-199"},
+   {"973-20", "973-54"},
+   {"973-550", "973-759"},
+   {"973-7600", "973-8499"},
+   {"973-85000", "973-88999"},
+   {"973-8900", "973-9499"},
+   {"973-95000", "973-99999"},
+   {"974-00", "974-19"},
+   {"974-200", "974-699"},
+   {"974-7000", "974-8499"},
+   {"974-85000", "974-89999"},
+   {"974-90000", "974-94999"},
+   {"974-9500", "974-9999"},
+   {"975-00000", "975-00999"},
+   {"975-01", "975-24"},
+   {"975-250", "975-599"},
+   {"975-6000", "975-9199"},
+   {"975-92000", "975-98999"},
+   {"975-990", "975-999"},
+   {"976-0", "976-3"},
+   {"976-40", "976-59"},
+   {"976-600", "976-799"},
+   {"976-8000", "976-9499"},
+   {"976-95000", "976-99999"},
+   {"977-00", "977-19"},
+   {"977-200", "977-499"},
+   {"977-5000", "977-6999"},
+   {"977-700", "977-999"},
+   {"978-000", "978-199"},
+   {"978-2000", "978-2999"},
+   {"978-30000", "978-79999"},
+   {"978-8000", "978-8999"},
+   {"978-900", "978-999"},
+   {"979-000", "979-099"},
+   {"979-1000", "979-1499"},
+   {"979-15000", "979-19999"},
+   {"979-20", "979-29"},
+   {"979-3000", "979-3999"},
+   {"979-400", "979-799"},
+   {"979-8000", "979-9499"},
+   {"979-95000", "979-99999"},
+   {"980-00", "980-19"},
+   {"980-200", "980-599"},
+   {"980-6000", "980-9999"},
+   {"981-00", "981-19"},
+   {"981-200", "981-299"},
+   {"981-3000", "981-9999"},
+   {"982-00", "982-09"},
+   {"982-100", "982-699"},
+   {"982-70", "982-89"},
+   {"982-9000", "982-9999"},
+   {"983-00", "983-01"},
+   {"983-020", "983-199"},
+   {"983-2000", "983-3999"},
+   {"983-40000", "983-49999"},
+   {"983-50", "983-79"},
+   {"983-800", "983-899"},
+   {"983-9000", "983-9899"},
+   {"983-99000", "983-99999"},
+   {"984-00", "984-39"},
+   {"984-400", "984-799"},
+   {"984-8000", "984-8999"},
+   {"984-90000", "984-99999"},
+   {"985-00", "985-39"},
+   {"985-400", "985-599"},
+   {"985-6000", "985-8999"},
+   {"985-90000", "985-99999"},
+   {"986-00", "986-11"},
+   {"986-120", "986-559"},
+   {"986-5600", "986-7999"},
+   {"986-80000", "986-99999"},
+   {"987-00", "987-09"},
+   {"987-1000", "987-1999"},
+   {"987-20000", "987-29999"},
+   {"987-30", "987-49"},
+   {"987-500", "987-899"},
+   {"987-9000", "987-9499"},
+   {"987-95000", "987-99999"},
+   {"988-00", "988-19"},
+   {"988-200", "988-799"},
+   {"988-8000", "988-9699"},
+   {"988-97000", "988-99999"},
+   {"989-0", "989-1"},
+   {"989-20", "989-54"},
+   {"989-550", "989-799"},
+   {"989-8000", "989-9499"},
+   {"989-95000", "989-99999"},
+   {"9944-0", "9944-2"},
+   {"9944-300", "9944-499"},
+   {"9944-5000", "9944-5999"},
+   {"9944-60", "9944-89"},
+   {"9944-900", "9944-999"},
+   {"9945-00", "9945-39"},
+   {"9945-400", "9945-849"},
+   {"9945-8500", "9945-9999"},
+   {"9946-0", "9946-1"},
+   {"9946-20", "9946-39"},
+   {"9946-400", "9946-899"},
+   {"9946-9000", "9946-9999"},
+   {"9947-0", "9947-1"},
+   {"9947-20", "9947-79"},
+   {"9947-800", "9947-999"},
+   {"9948-00", "9948-39"},
+   {"9948-400", "9948-849"},
+   {"9948-8500", "9948-9999"},
+   {"9949-0", "9949-0"},
+   {"9949-10", "9949-39"},
+   {"9949-400", "9949-899"},
+   {"9949-9000", "9949-9999"},
+   {"9950-00", "9950-29"},
+   {"9950-300", "9950-849"},
+   {"9950-8500", "9950-9999"},
+   {"9951-00", "9951-39"},
+   {"9951-400", "9951-849"},
+   {"9951-8500", "9951-9999"},
+   {"9952-0", "9952-1"},
+   {"9952-20", "9952-39"},
+   {"9952-400", "9952-799"},
+   {"9952-8000", "9952-9999"},
+   {"9953-0", "9953-0"},
+   {"9953-10", "9953-39"},
+   {"9953-400", "9953-599"},
+   {"9953-60", "9953-89"},
+   {"9953-9000", "9953-9999"},
+   {"9954-0", "9954-1"},
+   {"9954-20", "9954-39"},
+   {"9954-400", "9954-799"},
+   {"9954-8000", "9954-9999"},
+   {"9955-00", "9955-39"},
+   {"9955-400", "9955-929"},
+   {"9955-9300", "9955-9999"},
+   {"9956-0", "9956-0"},
+   {"9956-10", "9956-39"},
+   {"9956-400", "9956-899"},
+   {"9956-9000", "9956-9999"},
+   {"9957-00", "9957-39"},
+   {"9957-400", "9957-849"},
+   {"9957-8500", "9957-9999"},
+   {"9958-0", "9958-0"},
+   {"9958-10", "9958-49"},
+   {"9958-500", "9958-899"},
+   {"9958-9000", "9958-9999"},
+   {"9959-0", "9959-1"},
+   {"9959-20", "9959-79"},
+   {"9959-800", "9959-949"},
+   {"9959-9500", "9959-9999"},
+   {"9960-00", "9960-59"},
+   {"9960-600", "9960-899"},
+   {"9960-9000", "9960-9999"},
+   {"9961-0", "9961-2"},
+   {"9961-30", "9961-69"},
+   {"9961-700", "9961-949"},
+   {"9961-9500", "9961-9999"},
+   {"9962-00", "9962-54"},
+   {"9962-5500", "9962-5599"},
+   {"9962-56", "9962-59"},
+   {"9962-600", "9962-849"},
+   {"9962-8500", "9962-9999"},
+   {"9963-0", "9963-2"},
+   {"9963-30", "9963-54"},
+   {"9963-550", "9963-749"},
+   {"9963-7500", "9963-9999"},
+   {"9964-0", "9964-6"},
+   {"9964-70", "9964-94"},
+   {"9964-950", "9964-999"},
+   {"9965-00", "9965-39"},
+   {"9965-400", "9965-899"},
+   {"9965-9000", "9965-9999"},
+   {"9966-00", "9966-69"},
+   {"9966-7000", "9966-7499"},
+   {"9966-750", "9966-959"},
+   {"9966-9600", "9966-9999"},
+   {"9967-00", "9967-39"},
+   {"9967-400", "9967-899"},
+   {"9967-9000", "9967-9999"},
+   {"9968-00", "9968-49"},
+   {"9968-500", "9968-939"},
+   {"9968-9400", "9968-9999"},
+   {"9970-00", "9970-39"},
+   {"9970-400", "9970-899"},
+   {"9970-9000", "9970-9999"},
+   {"9971-0", "9971-5"},
+   {"9971-60", "9971-89"},
+   {"9971-900", "9971-989"},
+   {"9971-9900", "9971-9999"},
+   {"9972-00", "9972-09"},
+   {"9972-1", "9972-1"},
+   {"9972-200", "9972-249"},
+   {"9972-2500", "9972-2999"},
+   {"9972-30", "9972-59"},
+   {"9972-600", "9972-899"},
+   {"9972-9000", "9972-9999"},
+   {"9973-0", "9973-0"},
+   {"9973-10", "9973-69"},
+   {"9973-700", "9973-969"},
+   {"9973-9700", "9973-9999"},
+   {"9974-0", "9974-2"},
+   {"9974-30", "9974-54"},
+   {"9974-550", "9974-749"},
+   {"9974-7500", "9974-9499"},
+   {"9974-95", "9974-99"},
+   {"9975-0", "9975-0"},
+   {"9975-100", "9975-399"},
+   {"9975-4000", "9975-4499"},
+   {"9975-45", "9975-89"},
+   {"9975-900", "9975-949"},
+   {"9975-9500", "9975-9999"},
+   {"9976-0", "9976-5"},
+   {"9976-60", "9976-89"},
+   {"9976-900", "9976-989"},
+   {"9976-9990", "9976-9999"},
+   {"9977-00", "9977-89"},
+   {"9977-900", "9977-989"},
+   {"9977-9900", "9977-9999"},
+   {"9978-00", "9978-29"},
+   {"9978-300", "9978-399"},
+   {"9978-40", "9978-94"},
+   {"9978-950", "9978-989"},
+   {"9978-9900", "9978-9999"},
+   {"9979-0", "9979-4"},
+   {"9979-50", "9979-75"},
+   {"9979-760", "9979-899"},
+   {"9979-9000", "9979-9999"},
+   {"9980-0", "9980-3"},
+   {"9980-40", "9980-89"},
+   {"9980-900", "9980-989"},
+   {"9980-9900", "9980-9999"},
+   {"9981-00", "9981-09"},
+   {"9981-100", "9981-159"},
+   {"9981-1600", "9981-1999"},
+   {"9981-20", "9981-79"},
+   {"9981-800", "9981-949"},
+   {"9981-9500", "9981-9999"},
+   {"9982-00", "9982-79"},
+   {"9982-800", "9982-989"},
+   {"9982-9900", "9982-9999"},
+   {"9983-80", "9983-94"},
+   {"9983-950", "9983-989"},
+   {"9983-9900", "9983-9999"},
+   {"9984-00", "9984-49"},
+   {"9984-500", "9984-899"},
+   {"9984-9000", "9984-9999"},
+   {"9985-0", "9985-4"},
+   {"9985-50", "9985-79"},
+   {"9985-800", "9985-899"},
+   {"9985-9000", "9985-9999"},
+   {"9986-00", "9986-39"},
+   {"9986-400", "9986-899"},
+   {"9986-9000", "9986-9399"},
+   {"9986-940", "9986-969"},
+   {"9986-97", "9986-99"},
+   {"9987-00", "9987-39"},
+   {"9987-400", "9987-879"},
+   {"9987-8800", "9987-9999"},
+   {"9988-0", "9988-2"},
+   {"9988-30", "9988-54"},
+   {"9988-550", "9988-749"},
+   {"9988-7500", "9988-9999"},
+   {"9989-0", "9989-0"},
+   {"9989-100", "9989-199"},
+   {"9989-2000", "9989-2999"},
+   {"9989-30", "9989-59"},
+   {"9989-600", "9989-949"},
+   {"9989-9500", "9989-9999"},
+   {"99901-00", "99901-49"},
+   {"99901-500", "99901-799"},
+   {"99901-80", "99901-99"},
+   {"99903-0", "99903-1"},
+   {"99903-20", "99903-89"},
+   {"99903-900", "99903-999"},
+   {"99904-0", "99904-5"},
+   {"99904-60", "99904-89"},
+   {"99904-900", "99904-999"},
+   {"99905-0", "99905-3"},
+   {"99905-40", "99905-79"},
+   {"99905-800", "99905-999"},
+   {"99906-0", "99906-2"},
+   {"99906-30", "99906-59"},
+   {"99906-600", "99906-699"},
+   {"99906-70", "99906-89"},
+   {"99906-9", "99906-9"},
+   {"99908-0", "99908-0"},
+   {"99908-10", "99908-89"},
+   {"99908-900", "99908-999"},
+   {"99909-0", "99909-3"},
+   {"99909-40", "99909-94"},
+   {"99909-950", "99909-999"},
+   {"99910-0", "99910-2"},
+   {"99910-30", "99910-89"},
+   {"99910-900", "99910-999"},
+   {"99911-00", "99911-59"},
+   {"99911-600", "99911-999"},
+   {"99912-0", "99912-3"},
+   {"99912-400", "99912-599"},
+   {"99912-60", "99912-89"},
+   {"99912-900", "99912-999"},
+   {"99913-0", "99913-2"},
+   {"99913-30", "99913-35"},
+   {"99913-600", "99913-604"},
+   {"99914-0", "99914-4"},
+   {"99914-50", "99914-89"},
+   {"99914-900", "99914-949"},
+   {"99915-0", "99915-4"},
+   {"99915-50", "99915-79"},
+   {"99915-800", "99915-999"},
+   {"99916-0", "99916-2"},
+   {"99916-30", "99916-69"},
+   {"99916-700", "99916-999"},
+   {"99917-0", "99917-2"},
+   {"99917-30", "99917-89"},
+   {"99917-900", "99917-999"},
+   {"99918-0", "99918-3"},
+   {"99918-40", "99918-79"},
+   {"99918-800", "99918-999"},
+   {"99919-0", "99919-2"},
+   {"99919-40", "99919-69"},
+   {"99919-900", "99919-999"},
+   {"99920-0", "99920-4"},
+   {"99920-50", "99920-89"},
+   {"99920-900", "99920-999"},
+   {"99921-0", "99921-1"},
+   {"99921-20", "99921-69"},
+   {"99921-700", "99921-799"},
+   {"99921-8", "99921-8"},
+   {"99921-90", "99921-99"},
+   {"99922-0", "99922-3"},
+   {"99922-40", "99922-69"},
+   {"99922-700", "99922-999"},
+   {"99923-0", "99923-1"},
+   {"99923-20", "99923-79"},
+   {"99923-800", "99923-999"},
+   {"99924-0", "99924-2"},
+   {"99924-30", "99924-79"},
+   {"99924-800", "99924-999"},
+   {"99925-0", "99925-3"},
+   {"99925-40", "99925-79"},
+   {"99925-800", "99925-999"},
+   {"99926-0", "99926-0"},
+   {"99926-10", "99926-59"},
+   {"99926-600", "99926-999"},
+   {"99927-0", "99927-2"},
+   {"99927-30", "99927-59"},
+   {"99927-600", "99927-999"},
+   {"99928-0", "99928-0"},
+   {"99928-10", "99928-79"},
+   {"99928-800", "99928-999"},
+   {"99929-0", "99929-4"},
+   {"99929-50", "99929-79"},
+   {"99929-800", "99929-999"},
+   {"99930-0", "99930-4"},
+   {"99930-50", "99930-79"},
+   {"99930-800", "99930-999"},
+   {"99931-0", "99931-4"},
+   {"99931-50", "99931-79"},
+   {"99931-800", "99931-999"},
+   {"99932-0", "99932-0"},
+   {"99932-10", "99932-59"},
+   {"99932-600", "99932-699"},
+   {"99932-7", "99932-7"},
+   {"99932-80", "99932-99"},
+   {"99933-0", "99933-2"},
+   {"99933-30", "99933-59"},
+   {"99933-600", "99933-999"},
+   {"99934-0", "99934-1"},
+   {"99934-20", "99934-79"},
+   {"99934-800", "99934-999"},
+   {"99935-0", "99935-2"},
+   {"99935-30", "99935-59"},
+   {"99935-600", "99935-799"},
+   {"99935-8", "99935-8"},
+   {"99935-90", "99935-99"},
+   {"99936-0", "99936-0"},
+   {"99936-10", "99936-59"},
+   {"99936-600", "99936-999"},
+   {"99937-0", "99937-1"},
+   {"99937-20", "99937-59"},
+   {"99937-600", "99937-999"},
+   {"99938-0", "99938-1"},
+   {"99938-20", "99938-59"},
+   {"99938-600", "99938-899"},
+   {"99938-90", "99938-99"},
+   {"99939-0", "99939-5"},
+   {"99939-60", "99939-89"},
+   {"99939-900", "99939-999"},
+   {"99940-0", "99940-0"},
+   {"99940-10", "99940-69"},
+   {"99940-700", "99940-999"},
+   {"99941-0", "99941-2"},
+   {"99941-30", "99941-89"},
+   {"99941-900", "99941-999"},
+   {"99942-0", "99942-4"},
+   {"99942-50", "99942-79"},
+   {"99942-800", "99942-999"},
+   {"99943-0", "99943-2"},
+   {"99943-30", "99943-59"},
+   {"99943-600", "99943-999"},
+   {"99944-0", "99944-4"},
+   {"99944-50", "99944-79"},
+   {"99944-800", "99944-999"},
+   {"99945-0", "99945-5"},
+   {"99945-60", "99945-89"},
+   {"99945-900", "99945-999"},
+   {"99946-0", "99946-2"},
+   {"99946-30", "99946-59"},
+   {"99946-600", "99946-999"},
+   {"99947-0", "99947-2"},
+   {"99947-30", "99947-69"},
+   {"99947-700", "99947-999"},
+   {"99948-0", "99948-4"},
+   {"99948-50", "99948-79"},
+   {"99948-800", "99948-999"},
+   {"99949-0", "99949-1"},
+   {"99949-20", "99949-89"},
+   {"99949-900", "99949-999"},
+   {"99950-0", "99950-4"},
+   {"99950-50", "99950-79"},
+   {"99950-800", "99950-999"},
+   {"99951-00", "99951-99"},
+   {"99952-0", "99952-4"},
+   {"99952-50", "99952-79"},
+   {"99952-800", "99952-999"},
+   {"99953-0", "99953-2"},
+   {"99953-30", "99953-79"},
+   {"99953-800", "99953-999"},
+   {"99954-0", "99954-2"},
+   {"99954-30", "99954-69"},
+   {"99954-700", "99954-999"},
+   {NULL, NULL},
+};
diff --git a/contrib/isn/ISMN.h b/contrib/isn/ISMN.h
new file mode 100644 (file)
index 0000000..0451d19
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+ * ISMN.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Information recompiled by Kronuz on November 12, 2004
+ * http://www.ismn-international.org
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/ISMN.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ * M-3452-4680-5 <=> (0)-3452-4680-5 <=> 0345246805 <=> 9790345246805 <=> 979-0-3452-4680-5
+ *
+ *             (M counts as 3)
+ * ISMN         M   3   4    5   2   4   6    8   0
+ * Weight       3   1   3    1   3   1   3    1   3
+ * Product      9 + 3 + 12 + 5 + 6 + 4 + 18 + 8 + 0 = 65
+ *              65 / 10 = 6 remainder 5
+ * Check digit  10 - 5 = 5 
+ * => M-3452-4680-5
+ *
+ * ISMN         9   7    9   0   3   4    5   2   4   6    8   0
+ * Weight       1   3    1   3   1   3    1   3   1   3    1   3
+ * Product      9 + 21 + 9 + 0 + 3 + 12 + 5 + 6 + 4 + 18 + 8 + 0 = 95
+ *              95 / 10 = 9 remainder 5
+ * Check digit  10 - 5 = 5 
+ * => 979-0-3452-4680-5
+ *
+ * Since mod10(9*1 + 7*3 + 9*1 + 0*3) = mod10(M*3) = mod10(3*3) = 9; the check digit remains the same.
+ *
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned ISMN_index[10][2] = {
+   {0,     5},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+   {5,     0},
+};
+const char *ISMN_range[][2] = {
+   {"0-000", "0-099"},
+   {"0-1000", "0-3999"},
+   {"0-40000", "0-69999"},
+   {"0-700000", "0-899999"},
+   {"0-9000000", "0-9999999"},
+   {NULL, NULL}
+};
diff --git a/contrib/isn/ISSN.h b/contrib/isn/ISSN.h
new file mode 100644 (file)
index 0000000..aeafb0c
--- /dev/null
@@ -0,0 +1,49 @@
+/* 
+ * ISSN.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Information recompiled by Kronuz on November 12, 2004
+ * http://www.issn.org/
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/ISSN.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ * 1144-875X <=> 1144875(X) <=> 1144875 <=> (977)1144875 <=> 9771144875(00) <=> 977114487500(7) <=> 977-1144-875-00-7
+ *
+ * 
+ * ISSN         1   1   4    4    8    7    5
+ * Weight       8   7   6    5    4    3    2 
+ * Product      8 + 7 + 24 + 20 + 32 + 21 + 10 = 122
+ *              122 / 11 = 11 remainder 1
+ * Check digit  11 - 1 = 10 = X
+ * => 1144-875X
+ * 
+ * ISSN         9   7    7   1   1   4    4   8    7   5    0   0
+ * Weight       1   3    1   3   1   3    1   3    1   3    1   3
+ * Product      9 + 21 + 7 + 3 + 1 + 12 + 4 + 24 + 7 + 15 + 0 + 0 = 103
+ *              103 / 10 = 10 remainder 3
+ * Check digit  10 - 3 = 7
+ * => 977-1144875-00-7 ??  <- suplemental number (number of the week, month, etc.)
+ *                ^^ 00 for non-daily publications (01=Monday, 02=Tuesday, ...)
+ *
+ * The hyphenation is always in after the four digits of the ISSN code.
+ *
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned ISSN_index[10][2] = {
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+   {0,     1},
+};
+const char *ISSN_range[][2] = {
+   {"0000-000", "9999-999"},
+   {NULL, NULL}
+};
diff --git a/contrib/isn/Makefile b/contrib/isn/Makefile
new file mode 100644 (file)
index 0000000..bfc3a37
--- /dev/null
@@ -0,0 +1,16 @@
+# $PostgreSQL: pgsql/contrib/isn/Makefile,v 1.1 2006/09/09 04:07:52 tgl Exp $
+
+MODULES = isn
+DATA_built = isn.sql
+DATA = uninstall_isn.sql
+DOCS = README.isn
+
+ifdef USE_PGXS
+PGXS = $(shell pg_config --pgxs)
+include $(PGXS)
+else
+subdir = contrib/isn
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/isn/README.isn b/contrib/isn/README.isn
new file mode 100644 (file)
index 0000000..ef24958
--- /dev/null
@@ -0,0 +1,217 @@
+
+EAN13 - UPC - ISBN (books) - ISMN (music) - ISSN (serials)
+----------------------------------------------------------
+
+Copyright Germán Méndez Bravo (Kronuz), 2004 - 2006
+This module is released under the same BSD license as the rest of PostgreSQL.
+
+The information to implement this module was collected through
+several sites, including:
+   http://www.isbn-international.org/
+   http://www.issn.org/
+   http://www.ismn-international.org/
+   http://www.wikipedia.org/
+the prefixes used for hyphenation where also compiled from:
+   http://www.gs1.org/productssolutions/idkeys/support/prefix_list.html
+   http://www.isbn-international.org/en/identifiers.html
+   http://www.ismn-international.org/ranges.html
+Care was taken during the creation of the algorithms and they
+were meticulously verified against the suggested algorithms
+in the official ISBN, ISMN, ISSN User Manuals.
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+THIS MODULE IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
+        OF ANY KIND, EXPRESS OR IMPLIED.
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Content of the Module
+-------------------------------------------------
+
+This directory contains definitions for a few PostgreSQL
+data types, for the following international-standard namespaces:
+EAN13, UPC, ISBN (books), ISMN (music), and ISSN (serials). This module
+is inspired by Garrett A. Wollman's isbn_issn code.
+
+I wanted the database to fully validate numbers and also to use the
+upcoming ISBN-13 and the EAN13 standards, as well as to have it 
+automatically doing hyphenations for ISBN numbers.
+
+This new module validates, and automatically adds the correct 
+hyphenations to the numbers. Also, it supports the new ISBN-13 
+numbers to be used starting in January 2007.
+
+Premises:
+1. ISBN13, ISMN13, ISSN13 numbers are all EAN13 numbers
+2. EAN13 numbers aren't always ISBN13, ISMN13 or ISSN13 (some are)
+3. some ISBN13 numbers can be displayed as ISBN
+4. some ISMN13 numbers can be displayed as ISMN
+5. some ISSN13 numbers can be displayed as ISSN
+6. all UPC, ISBN, ISMN and ISSN can be represented as EAN13 numbers
+
+Note: All types are internally represented as 64 bit integers, 
+      and internally all are consistently interchangeable.
+
+We have the following data types:
+
++ EAN13 for European Article Numbers.
+    This type will always show the EAN13-display format.
+    Te output function for this is -> ean13_out()
+
++ ISBN13 for International Standard Book Numbers to be displayed in 
+  the new EAN13-display format.
++ ISMN13 for International Standard Music Numbers to be displayed in
+  the new EAN13-display format.
++ ISSN13 for International Standard Serial Numbers to be displayed
+  in the new EAN13-display format.
+    These types will always display the long version of the ISxN (EAN13)
+    The output function to do this is -> ean13_out()
+    * The need for these types is just for displaying in different
+      ways the same data:
+      ISBN13 is actually the same as ISBN, ISMN13=ISMN and ISSN13=ISSN.
+  
++ ISBN for International Standard Book Numbers to be displayed in
+  the current short-display format.
++ ISMN for International Standard Music Numbers to be displayed in
+  the current short-display format.
++ ISSN for International Standard Serial Numbers to be displayed
+  in the current short-display format.
+    These types will display the short version of the ISxN (ISxN 10)
+    whenever it's possible, and it will show ISxN 13 when it's
+    impossible to show the short version.
+    The output function to do this is -> isn_out()
+
++ UPC for Universal Product Codes.
+    UPC numbers are a subset of the EAN13 numbers (they are basically
+    EAN13 without the first '0' digit.)
+    The output function to do this is also -> isn_out()
+
+We have the following input functions:
++ To take a string and return an EAN13 -> ean13_in()
++ To take a string and return valid ISBN or ISBN13 numbers -> isbn_in()
++ To take a string and return valid ISMN or ISMN13 numbers -> ismn_in()
++ To take a string and return valid ISSN or ISSN13 numbers -> issn_in()
++ To take a string and return an UPC codes -> upc_in()
+
+We are able to cast from:
++ ISBN13 -> EAN13
++ ISMN13 -> EAN13
++ ISSN13 -> EAN13
+
++ ISBN -> EAN13
++ ISMN -> EAN13
++ ISSN -> EAN13
++ UPC  -> EAN13
+
++ ISBN <-> ISBN13
++ ISMN <-> ISMN13
++ ISSN <-> ISSN13
+
+We have two operator classes (for btree and for hash) so each data type
+can be indexed for faster access.
+
+The C API is implemented as:
+extern Datum isn_out(PG_FUNCTION_ARGS);
+extern Datum ean13_out(PG_FUNCTION_ARGS);
+extern Datum ean13_in(PG_FUNCTION_ARGS);
+extern Datum isbn_in(PG_FUNCTION_ARGS);
+extern Datum ismn_in(PG_FUNCTION_ARGS);
+extern Datum issn_in(PG_FUNCTION_ARGS);
+extern Datum upc_in(PG_FUNCTION_ARGS);
+
+On success:
++ isn_out() takes any of our types and returns a string containing 
+  the shortes possible representation of the number.
+
++ ean13_out() takes any of our types and returns the 
+  EAN13 (long) representation of the number.
+
++ ean13_in() takes a string and return a EAN13. Which, as stated in (2) 
+  could or could not be any of our types, but it certainly is an EAN13 
+  number. Only if the string is a valid EAN13 number, otherwise it fails.
+
++ isbn_in() takes a string and return an ISBN/ISBN13. Only if the string
+  is really a ISBN/ISBN13, otherwise it fails.
+
++ ismn_in() takes a string and return an ISMN/ISMN13. Only if the string
+  is really a ISMN/ISMN13, otherwise it fails.
+
++ issn_in() takes a string and return an ISSN/ISSN13. Only if the string
+  is really a ISSN/ISSN13, otherwise it fails.
+
++ upc_in() takes a string and return an UPC. Only if the string is
+  really a UPC, otherwise it fails.
+
+(on failure, the functions 'ereport' the error)
+
+Testing/Playing Functions
+-------------------------------------------------
+isn_weak(boolean) - Sets the weak input mode. 
+This function is intended for testing use only!
+isn_weak() gets the current status of the weak mode.
+
+"Weak" mode is used to be able to insert "invalid" data to a table. 
+"Invalid" as in the check digit being wrong, not missing numbers.
+
+Why would you want to use the weak mode? well, it could be that
+you have a huge collection of ISBN numbers, and that there are so many of
+them that for weird reasons some have the wrong check digit (perhaps the
+numbers where scanned from a printed list and the OCR got the numbers wrong,
+perhaps the numbers were manually captured... who knows.) Anyway, the thing
+is you might want to clean the mess up, but you still want to be able to have
+all the numbers in your database and maybe use an external tool to access
+the invalid numbers in the database so you can verify the information and
+validate it more easily; as selecting all the invalid numbers in the table.
+
+When you insert invalid numbers in a table using the weak mode, the number
+will be inserted with the corrected check digit, but it will be flagged 
+with an exclamation mark ('!') at the end (i.e. 0-11-000322-5!)
+
+You can also force the insertion of invalid numbers even not in the weak mode,
+appending the '!' character at the end of the number.
+
+To work with invalid numbers, you can use two functions:
+  + make_valid(), which validates an invalid number (deleting the invalid flag)
+  + is_valid(), which checks for the invalid flag presence.
+
+Examples of Use
+-------------------------------------------------
+--Using the types directly:
+   select isbn('978-0-393-04002-9');
+   select isbn13('0901690546');
+   select issn('1436-4522');
+
+--Casting types:
+-- note that you can't cast from ean13 to other type, thus the following
+-- will NOT work: select upc(ean13('0220356483481'));
+   select ean13(upc('220356483481'));
+
+--Create a table with a single column to hold ISBN numbers:
+   create table test ( id isbn );
+   insert into test values('9780393040029');
+
+--Automatically calculating check digits (observe the '?'):
+   insert into test values('220500896?');
+   insert into test values('978055215372?');
+
+   select issn('3251231?');
+  select ismn('979047213542?');    
+
+--Using the weak mode:
+  select isn_weak(true);
+  insert into test values('978-0-11-000533-4');
+  insert into test values('9780141219307');
+  insert into test values('2-205-00876-X');
+  select isn_weak(false);
+  
+  select id from test where not is_valid(id);
+  update test set id=make_valid(id) where id = '2-205-00876-X!';
+  
+  select * from test;
+
+  select isbn13(id) from test;
+
+Contact
+-------------------------------------------------
+Please suggestions or bug reports to kronuz at users.sourceforge.net
+
+Last reviewed on August 23, 2006 by Kronuz.
diff --git a/contrib/isn/UPC.h b/contrib/isn/UPC.h
new file mode 100644 (file)
index 0000000..2491fa3
--- /dev/null
@@ -0,0 +1,28 @@
+/* 
+ * ISSN.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * No information available for UPC prefixes
+ * 
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/UPC.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned UPC_index[10][2] = {
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+   {0,     0},
+};
+const char *UPC_range[][2] = {
+   {NULL, NULL}
+};
diff --git a/contrib/isn/isn.c b/contrib/isn/isn.c
new file mode 100644 (file)
index 0000000..4c4aabb
--- /dev/null
@@ -0,0 +1,910 @@
+/*-------------------------------------------------------------------------
+ *
+ * isn.c
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Copyright (c) 2004-2006, Germán Méndez Bravo (Kronuz)
+ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+PG_MODULE_MAGIC;
+
+#include "isn.h"
+
+#include "EAN13.h"
+#include "ISBN.h"
+#include "ISMN.h"
+#include "ISSN.h"
+#include "UPC.h"
+
+#define MAXEAN13LEN 18
+
+enum isn_type { INVALID, ANY, EAN13, ISBN, ISMN, ISSN, UPC };
+
+static const char *isn_names[] = { "ISN", "ISN", "EAN13", "ISBN", "ISMN", "ISSN", "UPC" };
+
+static bool g_weak = false;
+static bool g_initialized = false;
+
+/* Macros for converting TEXT to and from c-string */
+#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
+#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
+
+
+/***********************************************************************
+ **
+ **        Routines for ISNs.
+ **
+ ** Note:
+ **  In this code, a normalized string is one that is known to be a valid 
+ **  ISN number containing only digits and hyphens and with enough space 
+ **  to hold the full 13 digits plus the maximum of four hyphens.
+ ***********************************************************************/
+
+/*----------------------------------------------------------
+ * Debugging routines.
+ *---------------------------------------------------------*/
+
+/*
+ * Check if the table and its index is correct (just for debugging)
+ */
+#ifdef ISN_DEBUG
+static
+bool check_table(const char *(*TABLE)[2], const unsigned TABLE_index[10][2])
+{
+   const char *aux1, *aux2;
+   int a, b, x=0, y=-1, i=0, j, cnt=0, init=0;
+   
+   if(TABLE == NULL || TABLE_index == NULL) return true;
+
+   while(TABLE[i][0] && TABLE[i][1]) {
+       aux1 = TABLE[i][0];
+       aux2 = TABLE[i][1];
+
+       /* must always start with a digit: */
+       if(!isdigit(*aux1) || !isdigit(*aux2)) goto invalidtable;
+       a = *aux1 - '0';
+       b = *aux2 - '0';
+
+       /* must always have the same format and length: */
+       while(*aux1 && *aux2) {
+           if(!(isdigit(*aux1) && isdigit(*aux2)) && (*aux1!=*aux2 || *aux1 != '-')) 
+               goto invalidtable;
+           aux1++;
+           aux2++;
+       }
+       if(*aux1!=*aux2) goto invalidtable;
+
+       /* found a new range */
+       if(a>y) {
+           /* check current range in the index: */
+           for(j=x;j<=y;j++) {
+               if(TABLE_index[j][0] != init) goto invalidindex;
+               if(TABLE_index[j][1] != i-init) goto invalidindex;
+           }
+           init = i;
+           x = a;
+       } 
+
+       /* Always get the new limit */
+       y = b;
+       if(y
+       i++;
+   }
+
+   return true;
+
+invalidtable:
+   elog(DEBUG1, "invalid table near {\"%s\", \"%s\"} (pos: %d)",
+        TABLE[i][0], TABLE[i][1], i);
+   return false;
+
+invalidindex:
+   elog(DEBUG1, "index %d is invalid", j);
+   return false;
+}
+#endif /* ISN_DEBUG */
+
+/*----------------------------------------------------------
+ * Formatting and conversion routines.
+ *---------------------------------------------------------*/
+
+static
+unsigned dehyphenate(char *bufO, char *bufI)
+{
+   unsigned ret = 0;
+   while(*bufI) {
+       if(isdigit(*bufI)) {
+           *bufO++ = *bufI;
+           ret++;
+       }
+       bufI++;
+   }
+   *bufO = '\0';
+   return ret;
+}
+
+/*
+ * hyphenate --- Try to hyphenate, in-place, the string starting at bufI 
+ *                into bufO using the given hyphenation range TABLE.
+ *                Assumes the input string to be used is of only digits.
+ *
+ * Returns the number of characters acctually hyphenated.
+ */
+static
+unsigned hyphenate(char *bufO, char *bufI, const char *(*TABLE)[2], const unsigned TABLE_index[10][2])
+{
+   unsigned ret = 0;
+   const char *ean_aux1, *ean_aux2, *ean_p;
+   char *firstdig, *aux1, *aux2;
+   unsigned search, upper, lower, step;
+   bool ean_in1, ean_in2;
+
+   /* just compress the string if no further hyphenation is required */
+   if(TABLE == NULL || TABLE_index == NULL) {
+       while(*bufI) {
+           *bufO++ = *bufI++;
+           ret++;
+       }
+       *bufO = '\0';
+       return (ret+1);
+   }
+
+   /* add remaining hyphenations */
+
+   search = *bufI - '0';
+   upper = lower = TABLE_index[search][0];
+   upper += TABLE_index[search][1];
+   lower--;
+
+   step = (upper - lower) / 2;
+   if(step == 0) return 0;
+   search = lower + step;
+
+   firstdig = bufI;
+   ean_in1 = ean_in2 = false;
+   ean_aux1 = TABLE[search][0];
+   ean_aux2 = TABLE[search][1];
+   do {
+       if((ean_in1 || *firstdig>=*ean_aux1) && (ean_in2 || *firstdig<=*ean_aux2)) {
+           if(*firstdig > *ean_aux1) ean_in1 = true;
+           if(*firstdig < *ean_aux2) ean_in2 = true;
+           if(ean_in1 && ean_in2) break;
+
+           firstdig++, ean_aux1++, ean_aux2++;
+           if(!(*ean_aux1 && *ean_aux2 && *firstdig)) break;
+           if(!isdigit(*ean_aux1)) ean_aux1++, ean_aux2++;
+       } else {
+           /* check in what direction we should go and move the pointer accordingly */
+           if(*firstdig < *ean_aux1 && !ean_in1) upper = search;
+           else lower = search;
+
+           step = (upper - lower) / 2;
+           search = lower + step;
+
+           /* Initialize stuff again: */
+           firstdig = bufI;
+           ean_in1 = ean_in2 = false;
+           ean_aux1 = TABLE[search][0];
+           ean_aux2 = TABLE[search][1];
+       }
+   } while(step);
+   
+   if(step) {
+       aux1 = bufO;
+       aux2 = bufI;
+       ean_p = TABLE[search][0];
+       while(*ean_p && *aux2) {
+           if(*ean_p++!='-') *aux1++ = *aux2++;
+           else *aux1++ = '-';
+           ret++;
+       }
+       *aux1++='-';
+       *aux1 = *aux2; /* add a lookahead char */
+       return (ret+1);
+   }
+   return ret;
+}
+
+/*
+ * weight_checkdig -- Receives a buffer with a normalized ISN string number, 
+ *                     and the length to weight.
+ *
+ * Returns the weight of the number (the check digit value, 0-10)
+ */
+static
+unsigned weight_checkdig(char *isn, unsigned size)
+{
+   unsigned weight = 0;
+   while(*isn && size>1) {
+       if(isdigit(*isn)) {
+           weight += size-- * (*isn - '0');
+       }
+       isn++;
+   }
+   weight = weight % 11;
+   if(weight != 0) weight = 11 - weight;
+   return weight;
+}
+
+
+/*
+ * checkdig --- Receives a buffer with a normalized ISN string number, 
+ *               and the length to check.
+ *
+ * Returns the check digit value (0-9)
+ */
+static
+unsigned checkdig(char *num, unsigned size)
+{
+   unsigned check=0, check3=0;
+   unsigned pos = 0;
+   if(*num == 'M') { /* ISMN start with 'M' */
+       check3 = 3;
+       pos = 1;
+   }
+   while(*num && size>1) {
+       if(isdigit(*num)) {
+           if(pos++%2) check3 += *num - '0';
+           else check += *num - '0';
+           size--;
+       }
+       num++;
+   }
+   check = (check + 3*check3) % 10;
+   if(check != 0) check = 10 - check;
+   return check;
+}
+
+/*
+ * ean2isn --- Convert in-place a normalized EAN13 string to the corresponding 
+ *            ISN string number. Assumes the input string is normalized.
+ */
+static inline
+void ean2ISBN(char *isn)
+{
+   char *aux;
+   unsigned check;
+   /* the number should come in this format: 978-0-000-00000-0 */
+   /* Strip the first part and calculate the new check digit */
+   hyphenate(isn, isn+4, NULL, NULL);
+   check = weight_checkdig(isn, 10);
+   aux = strchr(isn, '\0');
+   while(!isdigit(*--aux));
+   if(check == 10) *aux = 'X';
+   else *aux = check + '0';
+}
+static inline
+void ean2ISMN(char *isn)
+{
+   /* the number should come in this format: 979-0-000-00000-0 */
+   /* Just strip the first part and change the first digit ('0') to 'M' */
+   hyphenate(isn, isn+4, NULL, NULL);
+   isn[0] = 'M';
+}
+static inline
+void ean2ISSN(char *isn)
+{
+   unsigned check;
+   /* the number should come in this format: 977-0000-000-00-0 */
+   /* Strip the first part, crop, and calculate the new check digit */
+   hyphenate(isn, isn+4, NULL, NULL);
+   check = weight_checkdig(isn, 8);
+   if(check == 10) isn[8] = 'X';
+   else isn[8] = check + '0';
+   isn[9] = '\0';
+}
+static inline
+void ean2UPC(char *isn)
+{
+   /* the number should come in this format: 000-000000000-0 */
+   /* Strip the first part, crop, and dehyphenate */
+   dehyphenate(isn, isn+1);
+   isn[12] = '\0';
+}
+
+/*
+ * ean2* --- Converts a string of digits into an ean13 number.
+ *            Assumes the input string is a string with only digits 
+ *            on it, and that it's within the range of ean13.
+ *
+ * Returns the ean13 value of the string.
+ */
+static
+ean13 str2ean(const char *num) 
+{
+   ean13 ean = 0;  /* current ean */
+   while(*num) {
+       ean = 10 * ean + ((*num++) - '0');
+   }
+    return (ean<<1); /* also give room to a flag */
+}
+
+/*
+ * ean2string --- Try to convert an ean13 number to an hyphenated string.
+ *                Assumes there's enough space in result to hold
+ *                the string (maximum MAXEAN13LEN+1 bytes)
+ *                This doesn't verify for a valid check digit.
+ *
+ * If shortType is true, the returned string is in the old ISN short format.
+ * If errorOK is false, ereport a useful error message if the string is bad.
+ * If errorOK is true, just return "false" for bad input.
+ */
+static
+bool ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
+{
+   const char *(*TABLE)[2];
+   const unsigned (*TABLE_index)[2];
+   enum isn_type type = INVALID;
+
+   char *firstdig, *aux;
+   unsigned digval;
+   unsigned search;
+   char valid = '\0';              /* was the number initially written with a valid check digit? */
+
+   TABLE_index = ISBN_index;
+
+   if((ean & 1)!=0) valid = '!';
+   ean >>= 1;
+   /* verify it's in the EAN13 range */
+   if(ean > UINT64CONST(9999999999999))
+       goto eantoobig;
+
+   /* convert the number */
+   search = 0;
+   firstdig = aux = result + MAXEAN13LEN;
+   *aux = '\0';        /* terminate string; aux points to last digit */
+   *--aux = valid;     /* append '!' for numbers with invalid but corrected check digit */
+   do {
+       digval = (unsigned)(ean % 10);      /* get the decimal value */ 
+       ean /= 10;                                              /* get next digit */
+       *--aux = (char)(digval + '0');          /* convert to ascii and store */
+       if(++search == 1) *--aux = '-';         /* the check digit is always there */
+   } while(ean);
+   while(search++<13) *--aux = '0';            /* fill the remaining EAN13 with '0' */
+
+   /* The string should be in this form: ???DDDDDDDDDDDD-D" */
+   search = hyphenate(result, result+3, EAN13_range, EAN13_index);
+   
+   /* verify it's a logically valid EAN13 */
+   if(search == 0) {
+       search = hyphenate(result, result+3, NULL, NULL);
+       goto okay;
+   }
+
+   /* find out what type of hyphenation is needed: */
+   if(!strncmp("978-", result, search)) { /* ISBN */
+       /* The string should be in this form: 978-??000000000-0" */
+       type = ISBN;
+       TABLE = ISBN_range;
+       TABLE_index = ISBN_index;
+   } else if(!strncmp("977-", result, search)) { /* ISSN */
+       /* The string should be in this form: 977-??000000000-0" */
+       type = ISSN;
+       TABLE = ISSN_range;
+       TABLE_index = ISSN_index;
+   } else if(!strncmp("979-0", result, search+1)) { /* ISMN */
+       /* The string should be in this form: 979-0?000000000-0" */
+       type = ISMN;
+       TABLE = ISMN_range;
+       TABLE_index = ISMN_index;
+   } else if(*result == '0') { /* UPC */
+       /* The string should be in this form: 000-00000000000-0" */
+       type = UPC;
+       TABLE = UPC_range;
+       TABLE_index = UPC_index;
+   } else {
+       type = EAN13;
+       TABLE = NULL;
+       TABLE_index = NULL;
+   }
+
+   /* verify it's a logically valid EAN13/ISN */
+   digval = search;
+   search = hyphenate(result+digval, result+digval+2, TABLE, TABLE_index);
+
+   /* verify it's a valid EAN13 */
+   if(search == 0) {
+       search = hyphenate(result+digval, result+digval+2, NULL, NULL);
+       goto okay;
+   }
+
+okay:
+   /* convert to the old short type: */
+   if(shortType) 
+       switch(type) {
+           case ISBN:
+               ean2ISBN(result);
+               break;
+           case ISMN:
+               ean2ISMN(result);
+               break;
+           case ISSN:
+               ean2ISSN(result);
+               break;
+           case UPC:
+               ean2UPC(result);
+               break;
+           default:
+               break;
+       }
+   return true;
+
+eantoobig:
+   if(!errorOK)
+   {
+       char    eanbuf[64];
+
+       /*
+        * Format the number separately to keep the machine-dependent
+        * format code out of the translatable message text
+        */
+       snprintf(eanbuf, sizeof(eanbuf), EAN13_FORMAT, ean);
+       ereport(ERROR,
+               (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                errmsg("value \"%s\" is out of range for ISN type",
+                       eanbuf)));
+   }
+   return false;
+}
+
+/*
+ * string2ean --- try to parse a string into an ean13.
+ *
+ * If errorOK is false, ereport a useful error message if the string is bad.
+ * If errorOK is true, just return "false" for bad input.
+ *
+ * if the input string ends with '!' it will always be treated as invalid
+ * (even if the check digit is valid)
+ */
+static
+bool string2ean(const char *str, bool errorOK, ean13 *result,
+               enum isn_type accept)
+{
+   bool digit, last;
+   char buf[17] = "                ";
+   char *aux1 = buf + 3; /* leave space for the first part, in case it's needed */
+   const char *aux2 = str;
+   enum isn_type type = INVALID;
+   unsigned check = 0, rcheck = (unsigned)-1;
+   unsigned length = 0;
+   bool magic = false, valid = true;
+
+   /* recognize and validate the number: */
+   while(*aux2 && length <= 13) {
+       last = (*(aux2+1) == '!' || *(aux2+1) == '\0'); /* is the last character */
+       digit = isdigit(*aux2); /* is current character a digit? */
+       if(*aux2=='?' && last) /* automagically calculate check digit if it's '?' */
+           magic = digit = true;
+       if(length == 0 &&  (*aux2=='M' || *aux2=='m')) {
+           /* only ISMN can be here */
+           if(type != INVALID) goto eaninvalid;
+           type = ISMN;
+           *aux1++ = 'M';
+           length++;
+       } else if(length == 7 && (digit || *aux2=='X' || *aux2=='x') && last) {
+           /* only ISSN can be here */
+           if(type != INVALID) goto eaninvalid;
+           type = ISSN;
+           *aux1++ = toupper(*aux2);
+           length++;
+       } else if(length == 9 && (digit || *aux2=='X' || *aux2=='x') && last) {
+           /* only ISBN and ISMN can be here */
+           if(type != INVALID && type != ISMN) goto eaninvalid;
+           if(type == INVALID) type = ISBN; /* ISMN must start with 'M' */
+           *aux1++ = toupper(*aux2);
+           length++;
+       } else if(length == 11 && digit && last) {
+           /* only UPC can be here */
+           if(type != INVALID) goto eaninvalid;
+           type = UPC;
+           *aux1++ = *aux2;
+           length++;
+       } else if(*aux2 == '-' || *aux2 == ' ') {
+           /* skip, we could validate but I think it's worthless */
+       } else if(*aux2 == '!' && *(aux2+1) == '\0') {
+           /* the invalid check digit sufix was found, set it */
+           if(!magic) valid = false;
+           magic = true;
+       } else if(!digit) {
+           goto eaninvalid;
+       } else {
+           *aux1++ = *aux2;
+           if(++length > 13) goto eantoobig;
+       }
+       aux2++;
+   }
+   *aux1 = '\0'; /* terminate the string */
+
+   /* find the current check digit value */
+   if(length == 13) {
+       /* only EAN13 can be here */
+       if(type != INVALID) goto eaninvalid;
+       type = EAN13;
+       check = buf[15]-'0';
+   } else if(length == 12) {
+       /* only UPC can be here */
+       if(type != UPC) goto eaninvalid;
+       check = buf[14]-'0';
+   } else if(length == 10) {
+       if(type != ISBN && type != ISMN) goto eaninvalid;
+       if(buf[12] == 'X') check = 10;
+       else check = buf[12]-'0';
+   } else if(length == 8) {
+       if(type != INVALID && type != ISSN) goto eaninvalid;
+       type = ISSN;
+       if(buf[10] == 'X') check = 10;
+       else check = buf[10]-'0';
+   } else goto eaninvalid;
+
+   if(type == INVALID) goto eaninvalid;
+
+   /* obtain the real check digit value, validate, and convert to ean13: */ 
+   if(accept == EAN13 && type != accept) goto eanwrongtype;
+   if(accept != ANY && type != EAN13 && type != accept) goto eanwrongtype;
+   switch(type) {
+       case EAN13:
+           valid = (valid && ((rcheck=checkdig(buf+3, 13)) == check || magic));
+           /* now get the subtype of EAN13: */
+           if(buf[3] == '0') type = UPC;
+           else if(!strncmp("977", buf+3, 3)) type = ISSN;
+           else if(!strncmp("978", buf+3, 3)) type = ISBN;
+           else if(!strncmp("9790", buf+3, 4)) type = ISMN;
+           else if(!strncmp("979", buf+3, 3)) type = ISBN;
+           if(accept != EAN13 && accept != ANY && type != accept) goto eanwrongtype;
+           break;
+       case ISMN:
+           strncpy(buf, "9790", 4);  /* this isn't for sure yet, for now ISMN it's only 9790 */
+           valid = (valid && ((rcheck=checkdig(buf+3, 10)) == check || magic));
+           break;
+       case ISBN:
+           strncpy(buf, "978", 3);
+           valid = (valid && ((rcheck=weight_checkdig(buf+3, 10)) == check || magic));
+           break;
+       case ISSN:
+           strncpy(buf+10, "00", 2); /* append 00 as the normal issue publication code */
+           strncpy(buf, "977", 3);
+           valid = (valid && ((rcheck=weight_checkdig(buf+3, 8)) == check || magic));
+           break;
+       case UPC:
+           buf[2] = '0';
+           valid = (valid && ((rcheck=checkdig(buf+2, 13)) == check || magic));
+       default:
+           break;
+   }
+
+   if(!valid && !magic) goto eanbadcheck;
+           
+   for(aux1 = buf; *aux1 && *aux1 <= ' '; aux1++);
+   aux1[12] = checkdig(aux1, 13) + '0';
+   aux1[13] = '\0';
+   
+   *result = str2ean(aux1);
+   *result |= valid?0:1;
+
+   return true;
+
+eanbadcheck: 
+   if(!g_weak) {
+       if(!errorOK) {
+           if(rcheck == (unsigned)-1) {
+               ereport(ERROR,
+                   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                   errmsg("invalid %s number: \"%s\"",
+                           isn_names[accept], str)));
+           } else {
+               ereport(ERROR,
+                   (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                   errmsg("invalid check digit for %s number: \"%s\", should be %c",
+                           isn_names[accept], str, (rcheck==10)?('X'):(rcheck+'0'))));
+           }
+       }
+       return false;
+   }
+
+   if(accept != EAN13 && accept != ANY && type != accept) goto eanwrongtype;
+
+   /* fix the check digit: */
+   for(aux1 = buf; *aux1 && *aux1 <= ' '; aux1++);
+   aux1[12] = checkdig(aux1, 13) + '0';
+   aux1[13] = '\0';
+   *result = str2ean(aux1);
+
+    /* set the "invalid-check-digit-on-input" flag */ 
+   *result |= 1;
+
+   /* just warn about the error when there was a real check digit error: */
+   if(check != rcheck) {
+       if(rcheck == (unsigned)-1) {
+           elog(WARNING, "invalid %s number: \"%s\"",
+               isn_names[accept], str);
+       } else {
+           elog(WARNING, "invalid check digit for %s number: \"%s\", should be %c",
+               isn_names[accept], str, (rcheck==10)?('X'):(rcheck+'0'));
+       }
+   }
+   return true;
+
+eaninvalid:
+   if(!errorOK)
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                errmsg("invalid input syntax for %s number: \"%s\"",
+                       isn_names[accept], str)));
+   return false;
+
+eanwrongtype:
+   if(!errorOK)
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                errmsg("invalid %s type for number: \"%s\"",
+                       isn_names[accept], str)));
+   return false;
+
+eantoobig:
+   if(!errorOK)
+       ereport(ERROR,
+           (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+            errmsg("value \"%s\" is out of range for %s type",
+                   str, isn_names[accept])));
+   return false;
+}
+
+/*----------------------------------------------------------
+ * Exported routines.
+ *---------------------------------------------------------*/
+
+void initialize(void)
+{
+#ifdef ISN_DEBUG
+   if(!check_table(EAN13, EAN13_index))
+       elog(LOG, "EAN13 failed check");
+   if(!check_table(ISBN, ISBN_index))
+       elog(LOG, "ISBN failed check");
+   if(!check_table(ISMN, ISMN_index))
+       elog(LOG, "ISMN failed check");
+   if(!check_table(ISSN, ISSN_index))
+       elog(LOG, "ISSN failed check");
+   if(!check_table(UPC, UPC_index))
+       elog(LOG, "UPC failed check");
+#endif
+   g_initialized = true;
+}
+
+/* isn_out
+ */
+PG_FUNCTION_INFO_V1(isn_out);
+Datum
+isn_out(PG_FUNCTION_ARGS)
+{
+   ean13       val = PG_GETARG_EAN13(0);
+   char       *result;
+   char        buf[MAXEAN13LEN + 1];
+
+   (void) ean2string(val, false, buf, true);
+
+   result = pstrdup(buf);
+   PG_RETURN_CSTRING(result);
+}
+
+/* ean13_out
+ */
+PG_FUNCTION_INFO_V1(ean13_out);
+Datum
+ean13_out(PG_FUNCTION_ARGS)
+{
+   ean13       val = PG_GETARG_EAN13(0);
+   char       *result;
+   char        buf[MAXEAN13LEN + 1];
+
+   (void) ean2string(val, false, buf, false);
+
+   result = pstrdup(buf);
+   PG_RETURN_CSTRING(result);
+}
+
+/* ean13_in
+ */
+PG_FUNCTION_INFO_V1(ean13_in);
+Datum
+ean13_in(PG_FUNCTION_ARGS)
+{
+   const char  *str = PG_GETARG_CSTRING(0);
+   ean13       result;
+
+   (void) string2ean(str, false, &result, EAN13);
+   PG_RETURN_EAN13(result);
+}
+
+/* isbn_in
+ */
+PG_FUNCTION_INFO_V1(isbn_in);
+Datum
+isbn_in(PG_FUNCTION_ARGS)
+{
+   const char  *str = PG_GETARG_CSTRING(0);
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISBN);
+   PG_RETURN_EAN13(result);
+}
+
+/* ismn_in
+ */
+PG_FUNCTION_INFO_V1(ismn_in);
+Datum
+ismn_in(PG_FUNCTION_ARGS)
+{
+   const char  *str = PG_GETARG_CSTRING(0);
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISMN);
+   PG_RETURN_EAN13(result);
+}
+
+/* issn_in
+ */
+PG_FUNCTION_INFO_V1(issn_in);
+Datum
+issn_in(PG_FUNCTION_ARGS)
+{
+   const char  *str = PG_GETARG_CSTRING(0);
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISSN);
+   PG_RETURN_EAN13(result);
+}
+
+/* upc_in
+ */
+PG_FUNCTION_INFO_V1(upc_in);
+Datum
+upc_in(PG_FUNCTION_ARGS)
+{
+   const char  *str = PG_GETARG_CSTRING(0);
+   ean13       result;
+
+   (void) string2ean(str, false, &result, UPC);
+   PG_RETURN_EAN13(result);
+}
+
+/* casting functions
+*/
+PG_FUNCTION_INFO_V1(ean13_cast_to_text);
+Datum
+ean13_cast_to_text(PG_FUNCTION_ARGS)
+{
+   ean13       val = PG_GETARG_EAN13(0);
+   char        buf[MAXEAN13LEN + 1];
+
+   (void) ean2string(val, false, buf, false);
+
+    PG_RETURN_TEXT_P(GET_TEXT(buf));
+}
+
+PG_FUNCTION_INFO_V1(isn_cast_to_text);
+Datum
+isn_cast_to_text(PG_FUNCTION_ARGS)
+{
+   ean13       val = PG_GETARG_EAN13(0);
+   char        buf[MAXEAN13LEN + 1];
+
+   (void) ean2string(val, false, buf, true);
+
+    PG_RETURN_TEXT_P(GET_TEXT(buf));
+}
+
+PG_FUNCTION_INFO_V1(ean13_cast_from_text);
+Datum
+ean13_cast_from_text(PG_FUNCTION_ARGS)
+{
+   const char  *str = GET_STR(PG_GETARG_TEXT_P(0));
+   ean13       result;
+
+   (void) string2ean(str, false, &result, EAN13);
+   PG_RETURN_EAN13(result);
+}
+
+PG_FUNCTION_INFO_V1(isbn_cast_from_text);
+Datum
+isbn_cast_from_text(PG_FUNCTION_ARGS)
+{
+   const char  *str = GET_STR(PG_GETARG_TEXT_P(0));
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISBN);
+   PG_RETURN_EAN13(result);
+}
+
+PG_FUNCTION_INFO_V1(ismn_cast_from_text);
+Datum
+ismn_cast_from_text(PG_FUNCTION_ARGS)
+{
+   const char  *str = GET_STR(PG_GETARG_TEXT_P(0));
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISMN);
+   PG_RETURN_EAN13(result);
+}
+
+PG_FUNCTION_INFO_V1(issn_cast_from_text);
+Datum
+issn_cast_from_text(PG_FUNCTION_ARGS)
+{
+   const char  *str = GET_STR(PG_GETARG_TEXT_P(0));
+   ean13       result;
+
+   (void) string2ean(str, false, &result, ISSN);
+   PG_RETURN_EAN13(result);
+}
+
+PG_FUNCTION_INFO_V1(upc_cast_from_text);
+Datum
+upc_cast_from_text(PG_FUNCTION_ARGS)
+{
+   const char  *str = GET_STR(PG_GETARG_TEXT_P(0));
+   ean13       result;
+
+   (void) string2ean(str, false, &result, UPC);
+   PG_RETURN_EAN13(result);
+}
+
+/* is_valid - returns false if the "invalid-check-digit-on-input" is set
+ */
+PG_FUNCTION_INFO_V1(is_valid);
+Datum
+is_valid(PG_FUNCTION_ARGS)
+{
+   ean13 val = PG_GETARG_EAN13(0);
+   PG_RETURN_BOOL((val & 1) == 0);
+}
+
+/* make_valid - unsets the "invalid-check-digit-on-input" flag
+ */
+PG_FUNCTION_INFO_V1(make_valid);
+Datum
+make_valid(PG_FUNCTION_ARGS)
+{
+   ean13 val = PG_GETARG_EAN13(0);
+   val &= ~((ean13) 1);
+   PG_RETURN_EAN13(val);
+}
+
+#ifdef ISN_WEAK_MODE
+/* this function temporarily sets weak input flag 
+ * (to lose the strictness of check digit acceptance)
+ * It's a helper function, not intended to be used!!
+ */
+PG_FUNCTION_INFO_V1(accept_weak_input);
+Datum
+accept_weak_input(PG_FUNCTION_ARGS)
+{
+   g_weak = PG_GETARG_BOOL(0);
+   PG_RETURN_BOOL(g_weak);
+}
+#else
+PG_FUNCTION_INFO_V1(accept_weak_input);
+Datum
+accept_weak_input(PG_FUNCTION_ARGS)
+{
+   /* function has no effect */
+   PG_RETURN_BOOL(false);
+}
+#endif /* ISN_WEAK_MODE */
+
+PG_FUNCTION_INFO_V1(weak_input_status);
+Datum
+weak_input_status(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_BOOL(g_weak);
+}
diff --git a/contrib/isn/isn.h b/contrib/isn/isn.h
new file mode 100644 (file)
index 0000000..d436983
--- /dev/null
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * isn.h
+ *   PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+ *
+ * Copyright (c) 2004-2006, Germán Méndez Bravo (Kronuz)
+ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *   $PostgreSQL: pgsql/contrib/isn/isn.h,v 1.1 2006/09/09 04:07:52 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef ISN_H
+#define ISN_H
+
+#include "fmgr.h"
+
+#undef ISN_DEBUG
+#define ISN_WEAK_MODE
+
+/*
+ * uint64 is the internal storage format for ISNs.
+ */
+typedef uint64 ean13;
+
+#define EAN13_FORMAT UINT64_FORMAT
+
+#define PG_GETARG_EAN13(n) PG_GETARG_INT64(n)
+#define PG_RETURN_EAN13(x) PG_RETURN_INT64(x)
+
+extern Datum isn_out(PG_FUNCTION_ARGS);
+extern Datum ean13_out(PG_FUNCTION_ARGS);
+extern Datum ean13_in(PG_FUNCTION_ARGS);
+extern Datum isbn_in(PG_FUNCTION_ARGS);
+extern Datum ismn_in(PG_FUNCTION_ARGS);
+extern Datum issn_in(PG_FUNCTION_ARGS);
+extern Datum upc_in(PG_FUNCTION_ARGS);
+
+extern Datum ean13_cast_to_text(PG_FUNCTION_ARGS);
+extern Datum isn_cast_to_text(PG_FUNCTION_ARGS);
+extern Datum ean13_cast_from_text(PG_FUNCTION_ARGS);
+extern Datum isbn_cast_from_text(PG_FUNCTION_ARGS);
+extern Datum ismn_cast_from_text(PG_FUNCTION_ARGS);
+extern Datum issn_cast_from_text(PG_FUNCTION_ARGS);
+extern Datum upc_cast_from_text(PG_FUNCTION_ARGS);
+
+extern Datum is_valid(PG_FUNCTION_ARGS);
+extern Datum make_valid(PG_FUNCTION_ARGS);
+
+extern Datum accept_weak_input(PG_FUNCTION_ARGS);
+extern Datum weak_input_status(PG_FUNCTION_ARGS);
+
+extern void initialize(void);
+
+#endif   /* ISN_H */
diff --git a/contrib/isn/isn.sql.in b/contrib/isn/isn.sql.in
new file mode 100644 (file)
index 0000000..d5ac63d
--- /dev/null
@@ -0,0 +1,2350 @@
+--
+-- PostgreSQL code for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
+--  Copyright (c) 2004-2006, Germán Méndez Bravo (Kronuz)
+--
+-- $PostgreSQL: pgsql/contrib/isn/isn.sql.in,v 1.1 2006/09/09 04:07:52 tgl Exp $
+--
+-- Example:
+--   create table test ( id isbn );
+--   insert into test values('978-0-393-04002-9');
+--
+--   select isbn('978-0-393-04002-9');
+--   select isbn13('0-901690-54-6');
+--
+
+-- Adjust this setting to control where the objects get created.
+SET search_path = public;
+
+BEGIN;
+
+--
+-- Input and output functions and data types:
+--
+---------------------------------------------------
+CREATE FUNCTION ean13_in(cstring)
+   RETURNS ean13
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION ean13_out(ean13)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE ean13 (
+   INPUT = ean13_in,
+   OUTPUT = ean13_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE ean13
+   IS 'International European Article Number (EAN13)';
+
+CREATE FUNCTION isbn13_in(cstring)
+   RETURNS isbn13
+   AS 'MODULE_PATHNAME', 'isbn_in'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION ean13_out(isbn13)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE isbn13 (
+   INPUT = isbn13_in,
+   OUTPUT = ean13_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE isbn13
+   IS 'International Standard Book Number 13 (ISBN13)';
+
+CREATE FUNCTION ismn13_in(cstring)
+   RETURNS ismn13
+   AS 'MODULE_PATHNAME', 'ismn_in'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION ean13_out(ismn13)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE ismn13 (
+   INPUT = ismn13_in,
+   OUTPUT = ean13_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE ismn13
+   IS 'International Standard Music Number 13 (ISMN13)';
+
+CREATE FUNCTION issn13_in(cstring)
+   RETURNS issn13
+   AS 'MODULE_PATHNAME', 'issn_in'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION ean13_out(issn13)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE issn13 (
+   INPUT = issn13_in,
+   OUTPUT = ean13_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE issn13
+   IS 'International Standard Serial Number 13 (ISSN13)';
+
+-- Short format:
+   
+CREATE FUNCTION isbn_in(cstring)
+   RETURNS isbn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION isn_out(isbn)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE isbn (
+   INPUT = isbn_in,
+   OUTPUT = isn_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE isbn
+   IS 'International Standard Book Number (ISBN)';
+
+CREATE FUNCTION ismn_in(cstring)
+   RETURNS ismn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION isn_out(ismn)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE ismn (
+   INPUT = ismn_in,
+   OUTPUT = isn_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE ismn
+   IS 'International Standard Music Number (ISMN)';
+
+CREATE FUNCTION issn_in(cstring)
+   RETURNS issn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION isn_out(issn)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE issn (
+   INPUT = issn_in,
+   OUTPUT = isn_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE issn
+   IS 'International Standard Serial Number (ISSN)';
+
+CREATE FUNCTION upc_in(cstring)
+   RETURNS upc
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION isn_out(upc)
+   RETURNS cstring
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE TYPE upc (
+   INPUT = upc_in,
+   OUTPUT = isn_out,
+   INTERNALLENGTH = 8,
+   ALIGNMENT = double,
+   STORAGE = PLAIN
+);
+COMMENT ON TYPE upc
+   IS 'Universal Product Code (UPC)';
+
+--
+-- Operator functions:
+--
+---------------------------------------------------
+-- EAN13:
+CREATE FUNCTION isnlt(ean13, ean13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, ean13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, ean13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, ean13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, ean13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, ean13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, isbn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, ismn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, issn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, issn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, issn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, issn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, issn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, issn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, isbn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, isbn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, isbn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, isbn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, isbn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, isbn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, ismn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, ismn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, ismn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, ismn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, ismn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, ismn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, issn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, issn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, issn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, issn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, issn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, issn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ean13, upc)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ean13, upc)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ean13, upc)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ean13, upc)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ean13, upc)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ean13, upc)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISBN13:
+CREATE FUNCTION isnlt(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(isbn13, isbn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(isbn13, isbn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISBN:
+CREATE FUNCTION isnlt(isbn, isbn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(isbn, isbn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(isbn, isbn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(isbn, isbn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(isbn, isbn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(isbn, isbn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISMN13:
+CREATE FUNCTION isnlt(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ismn13, ismn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ismn13, ismn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISMN:
+CREATE FUNCTION isnlt(ismn, ismn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(ismn, ismn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(ismn, ismn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(ismn, ismn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(ismn, ismn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(ismn, ismn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISSN13:
+CREATE FUNCTION isnlt(issn13, issn13)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(issn13, issn13)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(issn13, issn13)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(issn13, issn13)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(issn13, issn13)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(issn13, issn13)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION isnlt(issn13, issn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(issn13, issn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(issn13, issn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(issn13, issn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(issn13, issn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(issn13, issn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- ISSN:
+CREATE FUNCTION isnlt(issn, issn)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(issn, issn)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(issn, issn)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(issn, issn)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(issn, issn)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(issn, issn)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+---------------------------------------------------
+-- UPC:
+CREATE FUNCTION isnlt(upc, upc)
+   RETURNS boolean
+   AS 'int8lt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnle(upc, upc)
+   RETURNS boolean
+   AS 'int8le'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isneq(upc, upc)
+   RETURNS boolean
+   AS 'int8eq'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnge(upc, upc)
+   RETURNS boolean
+   AS 'int8ge'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isngt(upc, upc)
+   RETURNS boolean
+   AS 'int8gt'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+CREATE FUNCTION isnne(upc, upc)
+   RETURNS boolean
+   AS 'int8ne'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+--
+-- Now the operators.  Note how some of the parameters to some
+-- of the 'CREATE OPERATOR' commands are commented out.  This
+-- is because they reference as yet undefined operators, and
+-- will be implicitly defined when those are, further down.
+--
+
+--
+-- EAN13 operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = ean13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = issn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel);
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ean13,
+   RIGHTARG = upc,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISBN13 operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = isbn13,
+   RIGHTARG = isbn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISBN operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = isbn,
+   RIGHTARG = isbn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISMN13 operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ismn13,
+   RIGHTARG = ismn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISMN operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = ismn,
+   RIGHTARG = ismn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISSN13 operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = issn13,
+   RIGHTARG = issn13,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = issn13,
+   RIGHTARG = issn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- ISSN operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = issn,
+   RIGHTARG = issn,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- UPC operators:
+--
+---------------------------------------------------
+CREATE OPERATOR < (
+   PROCEDURE = isnlt,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = >,
+   NEGATOR = >=,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR <= (
+   PROCEDURE = isnle,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = >=,
+   NEGATOR = >,
+   RESTRICT = scalarltsel,
+   JOIN = scalarltjoinsel);
+CREATE OPERATOR = (
+   PROCEDURE = isneq,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = =,
+   NEGATOR = <>,
+   RESTRICT = eqsel,
+   JOIN = eqjoinsel);
+CREATE OPERATOR >= (
+   PROCEDURE = isnge,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = <=,
+   NEGATOR = <,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR > (
+   PROCEDURE = isngt,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = <,
+   NEGATOR = <=,
+   RESTRICT = scalargtsel,
+   JOIN = scalargtjoinsel );
+CREATE OPERATOR <> (
+   PROCEDURE = isnne,
+   LEFTARG = upc,
+   RIGHTARG = upc,
+   COMMUTATOR = <>,
+   NEGATOR = =,
+   RESTRICT = neqsel,
+   JOIN = neqjoinsel);
+
+--
+-- Operator classes:
+--
+---------------------------------------------------
+-- EAN13:
+CREATE FUNCTION btean13cmp(ean13, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, isbn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, ismn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, issn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, isbn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, ismn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, issn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btean13cmp(ean13, upc)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ean13_ops DEFAULT
+   FOR TYPE ean13 USING btree AS
+   OPERATOR 1  < (ean13, isbn13),
+   OPERATOR 1  < (ean13, ismn13),
+   OPERATOR 1  < (ean13, issn13),
+   OPERATOR 1  < (ean13, isbn),
+   OPERATOR 1  < (ean13, ismn),
+   OPERATOR 1  < (ean13, issn),
+   OPERATOR 1  < (ean13, upc),
+   OPERATOR 1  <,
+   OPERATOR 2  <= (ean13, isbn13),
+   OPERATOR 2  <= (ean13, ismn13),
+   OPERATOR 2  <= (ean13, issn13),
+   OPERATOR 2  <= (ean13, isbn),
+   OPERATOR 2  <= (ean13, ismn),
+   OPERATOR 2  <= (ean13, issn),
+   OPERATOR 2  <= (ean13, upc),
+   OPERATOR 2  <=,
+   OPERATOR 3  = (ean13, isbn13),
+   OPERATOR 3  = (ean13, ismn13),
+   OPERATOR 3  = (ean13, issn13),
+   OPERATOR 3  = (ean13, isbn),
+   OPERATOR 3  = (ean13, ismn),
+   OPERATOR 3  = (ean13, issn),
+   OPERATOR 3  = (ean13, upc),
+   OPERATOR 3  =,
+   OPERATOR 4  >= (ean13, isbn13),
+   OPERATOR 4  >= (ean13, ismn13),
+   OPERATOR 4  >= (ean13, issn13),
+   OPERATOR 4  >= (ean13, isbn),
+   OPERATOR 4  >= (ean13, ismn),
+   OPERATOR 4  >= (ean13, issn),
+   OPERATOR 4  >= (ean13, upc),
+   OPERATOR 4  >=,
+   OPERATOR 5  > (ean13, isbn13),
+   OPERATOR 5  > (ean13, ismn13),
+   OPERATOR 5  > (ean13, issn13),
+   OPERATOR 5  > (ean13, isbn),
+   OPERATOR 5  > (ean13, ismn),
+   OPERATOR 5  > (ean13, issn),
+   OPERATOR 5  > (ean13, upc),
+   OPERATOR 5  >,
+   FUNCTION 1  btean13cmp(ean13, isbn13),
+   FUNCTION 1  btean13cmp(ean13, ismn13),
+   FUNCTION 1  btean13cmp(ean13, issn13),
+   FUNCTION 1  btean13cmp(ean13, isbn),
+   FUNCTION 1  btean13cmp(ean13, ismn),
+   FUNCTION 1  btean13cmp(ean13, issn),
+   FUNCTION 1  btean13cmp(ean13, upc),
+   FUNCTION 1  btean13cmp(ean13, ean13);
+
+CREATE FUNCTION hashean13(ean13)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ean13_ops DEFAULT
+   FOR TYPE ean13 USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashean13(ean13);
+
+---------------------------------------------------
+-- ISBN13:
+CREATE FUNCTION btisbn13cmp(isbn13, isbn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btisbn13cmp(isbn13, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btisbn13cmp(isbn13, isbn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS isbn13_ops DEFAULT
+   FOR TYPE isbn13 USING btree AS
+-- OPERATOR 1  < (isbn13, ean13),
+   OPERATOR 1  < (isbn13, isbn),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (isbn13, ean13),
+   OPERATOR 2  <= (isbn13, isbn),
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (isbn13, ean13), 
+   OPERATOR 3  = (isbn13, isbn),  
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (isbn13, ean13), 
+   OPERATOR 4  >= (isbn13, isbn),  
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (isbn13, ean13), 
+   OPERATOR 5  > (isbn13, isbn),  
+   OPERATOR 5  >,
+-- FUNCTION 1  btisbn13cmp(isbn13, ean13),
+   FUNCTION 1  btisbn13cmp(isbn13, isbn),
+   FUNCTION 1  btisbn13cmp(isbn13, isbn13);
+
+CREATE FUNCTION hashisbn13(isbn13)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS isbn13_ops DEFAULT
+   FOR TYPE isbn13 USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashisbn13(isbn13);
+
+---------------------------------------------------
+-- ISBN:
+CREATE FUNCTION btisbncmp(isbn, isbn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btisbncmp(isbn, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btisbncmp(isbn, isbn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS isbn_ops DEFAULT
+   FOR TYPE isbn USING btree AS
+-- OPERATOR 1  < (isbn, ean13),
+-- OPERATOR 1  < (isbn, isbn13),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (isbn, ean13),  
+-- OPERATOR 2  <= (isbn, isbn13), 
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (isbn, ean13),  
+-- OPERATOR 3  = (isbn, isbn13), 
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (isbn, ean13),  
+-- OPERATOR 4  >= (isbn, isbn13), 
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (isbn, ean13),  
+-- OPERATOR 5  > (isbn, isbn13), 
+   OPERATOR 5  >,
+-- FUNCTION 1  btisbncmp(isbn, ean13),
+-- FUNCTION 1  btisbncmp(isbn, isbn13),
+   FUNCTION 1  btisbncmp(isbn, isbn);
+
+CREATE FUNCTION hashisbn(isbn)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS isbn_ops DEFAULT
+   FOR TYPE isbn USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashisbn(isbn);
+
+---------------------------------------------------
+-- ISMN13:
+CREATE FUNCTION btismn13cmp(ismn13, ismn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btismn13cmp(ismn13, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btismn13cmp(ismn13, ismn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ismn13_ops DEFAULT
+   FOR TYPE ismn13 USING btree AS
+-- OPERATOR 1  < (ismn13, ean13),
+   OPERATOR 1  < (ismn13, ismn),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (ismn13, ean13),
+   OPERATOR 2  <= (ismn13, ismn),
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (ismn13, ean13), 
+   OPERATOR 3  = (ismn13, ismn),  
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (ismn13, ean13), 
+   OPERATOR 4  >= (ismn13, ismn),  
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (ismn13, ean13), 
+   OPERATOR 5  > (ismn13, ismn),  
+   OPERATOR 5  >,
+-- FUNCTION 1  btismn13cmp(ismn13, ean13),
+   FUNCTION 1  btismn13cmp(ismn13, ismn),
+   FUNCTION 1  btismn13cmp(ismn13, ismn13);
+
+CREATE FUNCTION hashismn13(ismn13)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ismn13_ops DEFAULT
+   FOR TYPE ismn13 USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashismn13(ismn13);
+
+---------------------------------------------------
+-- ISMN:
+CREATE FUNCTION btismncmp(ismn, ismn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btismncmp(ismn, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btismncmp(ismn, ismn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ismn_ops DEFAULT
+   FOR TYPE ismn USING btree AS
+-- OPERATOR 1  < (ismn, ean13),
+-- OPERATOR 1  < (ismn, ismn13),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (ismn, ean13),  
+-- OPERATOR 2  <= (ismn, ismn13), 
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (ismn, ean13),  
+-- OPERATOR 3  = (ismn, ismn13), 
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (ismn, ean13),  
+-- OPERATOR 4  >= (ismn, ismn13), 
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (ismn, ean13),  
+-- OPERATOR 5  > (ismn, ismn13), 
+   OPERATOR 5  >,
+-- FUNCTION 1  btismncmp(ismn, ean13),
+-- FUNCTION 1  btismncmp(ismn, ismn13),
+   FUNCTION 1  btismncmp(ismn, ismn);
+
+CREATE FUNCTION hashismn(ismn)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS ismn_ops DEFAULT
+   FOR TYPE ismn USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashismn(ismn);
+
+---------------------------------------------------
+-- ISSN13:
+CREATE FUNCTION btissn13cmp(issn13, issn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btissn13cmp(issn13, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btissn13cmp(issn13, issn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS issn13_ops DEFAULT
+   FOR TYPE issn13 USING btree AS
+-- OPERATOR 1  < (issn13, ean13),
+   OPERATOR 1  < (issn13, issn),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (issn13, ean13),
+   OPERATOR 2  <= (issn13, issn),
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (issn13, ean13), 
+   OPERATOR 3  = (issn13, issn),  
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (issn13, ean13), 
+   OPERATOR 4  >= (issn13, issn),  
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (issn13, ean13), 
+   OPERATOR 5  > (issn13, issn),  
+   OPERATOR 5  >,
+-- FUNCTION 1  btissn13cmp(issn13, ean13),
+   FUNCTION 1  btissn13cmp(issn13, issn),
+   FUNCTION 1  btissn13cmp(issn13, issn13);
+
+CREATE FUNCTION hashissn13(issn13)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS issn13_ops DEFAULT
+   FOR TYPE issn13 USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashissn13(issn13);
+
+---------------------------------------------------
+-- ISSN:
+CREATE FUNCTION btissncmp(issn, issn)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btissncmp(issn, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btissncmp(issn, issn13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS issn_ops DEFAULT
+   FOR TYPE issn USING btree AS
+-- OPERATOR 1  < (issn, ean13),
+-- OPERATOR 1  < (issn, issn13),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (issn, ean13),  
+-- OPERATOR 2  <= (issn, issn13), 
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (issn, ean13),  
+-- OPERATOR 3  = (issn, issn13), 
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (issn, ean13),  
+-- OPERATOR 4  >= (issn, issn13), 
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (issn, ean13),  
+-- OPERATOR 5  > (issn, issn13), 
+   OPERATOR 5  >,
+-- FUNCTION 1  btissncmp(issn, ean13),
+-- FUNCTION 1  btissncmp(issn, issn13),
+   FUNCTION 1  btissncmp(issn, issn);
+
+CREATE FUNCTION hashissn(issn)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS issn_ops DEFAULT
+   FOR TYPE issn USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashissn(issn);
+
+---------------------------------------------------
+-- UPC:
+CREATE FUNCTION btupccmp(upc, upc)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+CREATE FUNCTION btupccmp(upc, ean13)
+   RETURNS int4
+   AS 'btint8cmp'
+   LANGUAGE 'internal'
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS upc_ops DEFAULT
+   FOR TYPE upc USING btree AS
+-- OPERATOR 1  < (upc, ean13),
+   OPERATOR 1  <,
+-- OPERATOR 2  <= (upc, ean13),  
+   OPERATOR 2  <=,
+-- OPERATOR 3  = (upc, ean13),  
+   OPERATOR 3  =,
+-- OPERATOR 4  >= (upc, ean13),  
+   OPERATOR 4  >=,
+-- OPERATOR 5  > (upc, ean13),  
+   OPERATOR 5  >,
+-- FUNCTION 1  btupccmp(upc, ean13),
+   FUNCTION 1  btupccmp(upc, upc);
+
+CREATE FUNCTION hashupc(upc)
+   RETURNS int4
+   AS 'hashint8'
+   LANGUAGE 'internal' 
+   IMMUTABLE STRICT;
+
+CREATE OPERATOR CLASS upc_ops DEFAULT
+   FOR TYPE upc USING hash AS
+   OPERATOR 1  =,
+   FUNCTION 1  hashupc(upc);
+
+--
+-- Type casts:
+--
+---------------------------------------------------
+CREATE FUNCTION ean13(text)
+RETURNS ean13
+AS 'MODULE_PATHNAME', 'ean13_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION isbn13(text)
+RETURNS isbn13
+AS 'MODULE_PATHNAME', 'isbn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION ismn13(text)
+RETURNS ismn13
+AS 'MODULE_PATHNAME', 'ismn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION issn13(text)
+RETURNS issn13
+AS 'MODULE_PATHNAME', 'issn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION isbn(text)
+RETURNS isbn
+AS 'MODULE_PATHNAME', 'isbn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION ismn(text)
+RETURNS ismn
+AS 'MODULE_PATHNAME', 'ismn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION issn(text)
+RETURNS issn
+AS 'MODULE_PATHNAME', 'issn_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION upc(text)
+RETURNS upc
+AS 'MODULE_PATHNAME', 'upc_cast_from_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(ean13)
+RETURNS text
+AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(isbn13)
+RETURNS text
+AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(ismn13)
+RETURNS text
+AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(issn13)
+RETURNS text
+AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(isbn)
+RETURNS text
+AS 'MODULE_PATHNAME', 'isn_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(ismn)
+RETURNS text
+AS 'MODULE_PATHNAME', 'isn_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(issn)
+RETURNS text
+AS 'MODULE_PATHNAME', 'isn_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE FUNCTION text(upc)
+RETURNS text
+AS 'MODULE_PATHNAME', 'isn_cast_to_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE CAST (isbn13 AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (isbn AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (ismn13 AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (ismn AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (issn13 AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (issn AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (upc AS ean13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (isbn AS isbn13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (isbn13 AS isbn) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (ismn AS ismn13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (ismn13 AS ismn) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (issn AS issn13) WITHOUT FUNCTION AS ASSIGNMENT;
+CREATE CAST (issn13 AS issn) WITHOUT FUNCTION AS ASSIGNMENT;
+
+CREATE CAST (text AS ean13) WITH FUNCTION ean13(text);
+CREATE CAST (text AS isbn13) WITH FUNCTION isbn13(text);
+CREATE CAST (text AS ismn13) WITH FUNCTION ismn13(text);
+CREATE CAST (text AS issn13) WITH FUNCTION issn13(text);
+CREATE CAST (text AS isbn) WITH FUNCTION isbn(text);
+CREATE CAST (text AS ismn) WITH FUNCTION ismn(text);
+CREATE CAST (text AS issn) WITH FUNCTION issn(text);
+CREATE CAST (text AS upc) WITH FUNCTION upc(text);
+
+CREATE CAST (ean13 AS text) WITH FUNCTION text(ean13);
+CREATE CAST (isbn13 AS text) WITH FUNCTION text(isbn13);
+CREATE CAST (ismn13 AS text) WITH FUNCTION text(ismn13);
+CREATE CAST (issn13 AS text) WITH FUNCTION text(issn13);
+CREATE CAST (isbn AS text) WITH FUNCTION text(isbn);
+CREATE CAST (ismn AS text) WITH FUNCTION text(ismn);
+CREATE CAST (issn AS text) WITH FUNCTION text(issn);
+CREATE CAST (upc AS text) WITH FUNCTION text(upc);
+
+--
+-- Validation stuff for lose types:
+--
+CREATE FUNCTION make_valid(ean13)
+   RETURNS ean13
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(isbn13)
+   RETURNS isbn13
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(ismn13)
+   RETURNS ismn13
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(issn13)
+   RETURNS issn13
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(isbn)
+   RETURNS isbn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(ismn)
+   RETURNS ismn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(issn)
+   RETURNS issn
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION make_valid(upc)
+   RETURNS upc
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+
+CREATE FUNCTION is_valid(ean13)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(isbn13)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(ismn13)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(issn13)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(isbn)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(ismn)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(issn)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+CREATE FUNCTION is_valid(upc)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+
+--
+-- isn_weak(boolean) - Sets the weak input mode. 
+-- This function is intended for testing use only!
+--
+CREATE FUNCTION isn_weak(boolean)
+   RETURNS boolean
+   AS 'MODULE_PATHNAME', 'accept_weak_input'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+
+--
+-- isn_weak() - Gets the weak input mode status
+--
+CREATE FUNCTION isn_weak()
+   RETURNS boolean
+   AS 'MODULE_PATHNAME', 'weak_input_status'
+   LANGUAGE 'C'
+   IMMUTABLE STRICT;
+
+COMMIT;
diff --git a/contrib/isn/uninstall_isn.sql b/contrib/isn/uninstall_isn.sql
new file mode 100644 (file)
index 0000000..529aca3
--- /dev/null
@@ -0,0 +1,18 @@
+--
+-- Drop the actual types (in cascade):
+--
+---------------------------------------------------
+SET search_path = public;
+
+DROP TYPE ean13 CASCADE;
+DROP TYPE isbn13 CASCADE;
+DROP TYPE ismn13 CASCADE;
+DROP TYPE issn13 CASCADE;
+DROP TYPE isbn CASCADE;
+DROP TYPE ismn CASCADE;
+DROP TYPE issn CASCADE;
+DROP TYPE upc CASCADE;
+
+DROP FUNCTION isn_weak();
+DROP FUNCTION isn_weak(boolean);
+