]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
From: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
authorMarc G. Fournier <scrappy@hub.org>
Mon, 17 Aug 1998 03:35:05 +0000 (03:35 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Mon, 17 Aug 1998 03:35:05 +0000 (03:35 +0000)
Here is some more contrib-fodder, based on TIH's IP address type,
for ISBN and ISSN identifiers (which I just happened to need to keep
track of the things in my library).

contrib/README
contrib/isbn_issn/Makefile [new file with mode: 0644]
contrib/isbn_issn/README [new file with mode: 0644]
contrib/isbn_issn/isbn.c [new file with mode: 0644]
contrib/isbn_issn/isbn.sql [new file with mode: 0644]
contrib/isbn_issn/issn.c [new file with mode: 0644]
contrib/isbn_issn/issn.sql [new file with mode: 0644]

index bf4d10ebc565e64b57247dd1aace2d34bf49171f..800c9344a6bcfa74f083923849c36a406cd82f12 100644 (file)
@@ -35,6 +35,10 @@ ip_and_mac -
        PostgreSQL type extensions for IP and MAC addresses
        by Tom Ivar Helbekkmo <tih@Hamartun.Priv.NO>
 
+isbn_issn -
+       PostgreSQL type extensions for ISBN (books) and ISSN (serials)
+       by Garrett A. Wollman <wollman@khavrinen.lcs.mit.edu>
+
 linux -
        Start postgres back end system
        by Thomas Lockhart <lockhart@alumni.caltech.edu>
@@ -80,3 +84,5 @@ userlock -
        User locks
        by Massimo Dal Zotto <dz@cs.unitn.it>
 
+
+
diff --git a/contrib/isbn_issn/Makefile b/contrib/isbn_issn/Makefile
new file mode 100644 (file)
index 0000000..baccaf2
--- /dev/null
@@ -0,0 +1,25 @@
+#
+#      PostgreSQL types for ISBN and ISSN identifiers.
+#
+#      $Id: Makefile,v 1.1 1998/08/17 03:35:04 scrappy Exp $
+
+all: isbn.so issn.so
+
+isbn.so: isbn.o
+       ld -Bshareable -o isbn.so isbn.o
+
+isbn.o: isbn.c
+       cc -g -O -fPIC -I/usr/local/pgsql/include -c isbn.c
+
+issn.so: issn.o
+       ld -Bshareable -o issn.so issn.o
+
+issn.o: issn.c
+       cc -g -O -fPIC -I/usr/local/pgsql/include -c issn.c
+
+install: isbn.so issn.so
+       install -c isbn.so issn.so /usr/local/pgsql/modules
+
+#
+#      eof
+#
diff --git a/contrib/isbn_issn/README b/contrib/isbn_issn/README
new file mode 100644 (file)
index 0000000..6b29eb9
--- /dev/null
@@ -0,0 +1,18 @@
+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.c b/contrib/isbn_issn/isbn.c
new file mode 100644 (file)
index 0000000..ed608f3
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *     PostgreSQL type definitions for ISBNs.
+ *
+ *     $Id: isbn.c,v 1.1 1998/08/17 03:35:04 scrappy Exp $
+ */
+
+#include <stdio.h>
+
+#include <postgres.h>
+#include <utils/palloc.h>
+
+/*
+ *     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;
+       char       *cp;
+       int                     count;
+
+       if (strlen(str) != 13) {
+               elog(ERROR, "isbn_in: invalid ISBN \"%s\"", str);
+               return (NULL);
+       }
+       if (isbn_sum(str) != 0) {
+               elog(ERROR, "isbn_in: purported ISBN \"%s\" failed checksum",
+                    str);
+               return (NULL);
+       }
+
+       result = (isbn *) palloc(sizeof(isbn));
+
+       strncpy(result->num, str, 13);
+       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));
+}
+
+/*
+ *     eof
+ */
diff --git a/contrib/isbn_issn/isbn.sql b/contrib/isbn_issn/isbn.sql
new file mode 100644 (file)
index 0000000..4889aaf
--- /dev/null
@@ -0,0 +1,116 @@
+--
+--     PostgreSQL code for ISBNs.
+--
+--     $Id: isbn.sql,v 1.1 1998/08/17 03:35:05 scrappy Exp $
+--
+
+load '/usr/local/pgsql/modules/isbn.so';
+
+--
+--     Input and output functions and the type itself:
+--
+
+create function isbn_in(opaque)
+       returns opaque
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_out(opaque)
+       returns opaque
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create type isbn (
+       internallength = 16,
+       externallength = 13,
+       input = isbn_in,
+       output = isbn_out
+);
+
+--
+--     The various boolean tests:
+--
+
+create function isbn_lt(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_le(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_eq(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_ge(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_gt(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+create function isbn_ne(isbn, isbn)
+       returns bool
+       as '/usr/local/pgsql/modules/isbn.so'
+       language 'c';
+
+--
+--     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
+);
+
+--
+--     eof
+--
diff --git a/contrib/isbn_issn/issn.c b/contrib/isbn_issn/issn.c
new file mode 100644 (file)
index 0000000..8f5aa22
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *     PostgreSQL type definitions for ISSNs.
+ *
+ *     $Id: issn.c,v 1.1 1998/08/17 03:35:05 scrappy Exp $
+ */
+
+#include <stdio.h>
+
+#include <postgres.h>
+#include <utils/palloc.h>
+
+/*
+ *     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;
+       char       *cp;
+       int                     count;
+
+       if (strlen(str) != 9) {
+               elog(ERROR, "issn_in: invalid ISSN \"%s\"", str);
+               return (NULL);
+       }
+       if (issn_sum(str) != 0) {
+               elog(ERROR, "issn_in: purported ISSN \"%s\" failed checksum",
+                    str);
+               return (NULL);
+       }
+
+       result = (issn *) palloc(sizeof(issn));
+
+       strncpy(result->num, str, 9);
+       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));
+}
+
+/*
+ *     eof
+ */
diff --git a/contrib/isbn_issn/issn.sql b/contrib/isbn_issn/issn.sql
new file mode 100644 (file)
index 0000000..c1fac91
--- /dev/null
@@ -0,0 +1,116 @@
+--
+--     PostgreSQL code for ISSNs.
+--
+--     $Id: issn.sql,v 1.1 1998/08/17 03:35:05 scrappy Exp $
+--
+
+load '/usr/local/pgsql/modules/issn.so';
+
+--
+--     Input and output functions and the type itself:
+--
+
+create function issn_in(opaque)
+       returns opaque
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_out(opaque)
+       returns opaque
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create type issn (
+       internallength = 16,
+       externallength = 9,
+       input = issn_in,
+       output = issn_out
+);
+
+--
+--     The various boolean tests:
+--
+
+create function issn_lt(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_le(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_eq(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_ge(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_gt(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+create function issn_ne(issn, issn)
+       returns bool
+       as '/usr/local/pgsql/modules/issn.so'
+       language 'c';
+
+--
+--     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
+);
+
+--
+--     eof
+--