Commit 3fa676a7 authored by Marc G. Fournier's avatar Marc G. Fournier

From: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>

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).
parent efc9a91d
......@@ -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>
#
# 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
#
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
/*
* 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
*/
--
-- 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
--
/*
* 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
*/
--
-- 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
--
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment