mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Add contrib/isn module for ISBN/ISSN/EAN13/etc product numbers, and
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.
This commit is contained in:
		@@ -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
 | 
					subdir = contrib
 | 
				
			||||||
top_builddir = ..
 | 
					top_builddir = ..
 | 
				
			||||||
@@ -15,7 +15,7 @@ WANTED_DIRS = \
 | 
				
			|||||||
		hstore		\
 | 
							hstore		\
 | 
				
			||||||
		intagg		\
 | 
							intagg		\
 | 
				
			||||||
		intarray	\
 | 
							intarray	\
 | 
				
			||||||
		isbn_issn	\
 | 
							isn		\
 | 
				
			||||||
		lo		\
 | 
							lo		\
 | 
				
			||||||
		ltree		\
 | 
							ltree		\
 | 
				
			||||||
		oid2name	\
 | 
							oid2name	\
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,9 +64,9 @@ intarray -
 | 
				
			|||||||
	Index support for arrays of int4, using GiST
 | 
						Index support for arrays of int4, using GiST
 | 
				
			||||||
	by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov <oleg@sai.msu.su>
 | 
						by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov <oleg@sai.msu.su>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
isbn_issn -
 | 
					isn -
 | 
				
			||||||
	PostgreSQL type extensions for ISBN (books) and ISSN (serials)
 | 
						PostgreSQL type extensions for ISBN, ISSN, ISMN, EAN13 product numbers
 | 
				
			||||||
	by Garrett A. Wollman <wollman@khavrinen.lcs.mit.edu>
 | 
						by Germ<EFBFBD>n M<>ndez Bravo (Kronuz) <kronuz@hotmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lo -
 | 
					lo -
 | 
				
			||||||
	Large Object maintenance
 | 
						Large Object maintenance
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					 | 
				
			||||||
@@ -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
 | 
					 | 
				
			||||||
@@ -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));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -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);
 | 
					 | 
				
			||||||
@@ -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;
 | 
					 | 
				
			||||||
							
								
								
									
										147
									
								
								contrib/isn/EAN13.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								contrib/isn/EAN13.h
									
									
									
									
									
										Normal file
									
								
							@@ -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}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										732
									
								
								contrib/isn/ISBN.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										732
									
								
								contrib/isn/ISBN.h
									
									
									
									
									
										Normal file
									
								
							@@ -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},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										52
									
								
								contrib/isn/ISMN.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								contrib/isn/ISMN.h
									
									
									
									
									
										Normal file
									
								
							@@ -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}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										49
									
								
								contrib/isn/ISSN.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								contrib/isn/ISSN.h
									
									
									
									
									
										Normal file
									
								
							@@ -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}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										16
									
								
								contrib/isn/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								contrib/isn/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										217
									
								
								contrib/isn/README.isn
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								contrib/isn/README.isn
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					EAN13 - UPC - ISBN (books) - ISMN (music) - ISSN (serials)
 | 
				
			||||||
 | 
					----------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright Germ<72>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.
 | 
				
			||||||
							
								
								
									
										28
									
								
								contrib/isn/UPC.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								contrib/isn/UPC.h
									
									
									
									
									
										Normal file
									
								
							@@ -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}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										910
									
								
								contrib/isn/isn.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										910
									
								
								contrib/isn/isn.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,910 @@
 | 
				
			|||||||
 | 
					/*-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * isn.c
 | 
				
			||||||
 | 
					 *	  PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2004-2006, Germ<72>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<x) goto invalidtable;
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								contrib/isn/isn.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								contrib/isn/isn.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/*-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * isn.h
 | 
				
			||||||
 | 
					 *	  PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2004-2006, Germ<72>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 */
 | 
				
			||||||
							
								
								
									
										2350
									
								
								contrib/isn/isn.sql.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2350
									
								
								contrib/isn/isn.sql.in
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										18
									
								
								contrib/isn/uninstall_isn.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								contrib/isn/uninstall_isn.sql
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user