/contrib patch from Karel.

This commit is contained in:
Bruce Momjian 2000-06-15 18:55:34 +00:00
parent 82c4733116
commit f7f177d372
73 changed files with 1156 additions and 4508 deletions

View File

@ -1,27 +1,59 @@
# Makefile for contrib code
#
# The following subdirs don't have a Makefile:
# The PostgreSQL contrib tree Makefile
#
# apache_logging
# linux
# mSQL-interface
# noupdate
# unixdate
# Portions Copyright (c) 1999-2000, PostgreSQL, Inc
#
# The following subdirs give make errors:
# $Header: /cvsroot/pgsql/contrib/Makefile,v 1.4 2000/06/15 18:54:29 momjian Exp $
#
# earthdistance
# os2client
TOPDIR = ..
include Makefile.global
WANTED_DIRS = array \
earthdistance \
findoidjoins \
fulltextindex \
isbn_issn \
likeplanning \
linux \
lo \
mSQL-interface \
miscutil \
noupdate \
pg_dumplo \
pgbench \
soundex \
spi \
string \
tips \
tools \
unixdate \
userlock \
vacuumlo
# odbc
# os2client
all:
for dir in *; do \
for dir in $(WANTED_DIRS); do \
if [ -e $$dir/Makefile ]; then \
$(MAKE) -C $$dir $@ ; \
fi; \
done
.DEFAULT:
for dir in *; do \
install:
../config/mkinstalldirs $(CONTRIB_BINDIR) $(CONTRIB_MODDIR) $(CONTRIB_DOCDIR) $(CONTRIB_SQLDIR) $(CONTRIB_EXAMPLESDIR)
for dir in $(WANTED_DIRS); do \
if [ -e $$dir/Makefile ]; then \
$(MAKE) -C $$dir $@ ; \
fi; \
done
$(INSTALL) $(INSTL_LIB_OPTS) Contrib.index $(CONTRIB_DOCDIR);
.DEFAULT:
for dir in $(WANTED_DIRS); do \
if [ -e $$dir/Makefile ]; then \
$(MAKE) -C $$dir $@ ; \
fi; \

View File

@ -1,94 +1,81 @@
This directory contains the contribution functions or tools.
---------------------------------------------------------------------------
The PostgreSQL contrib tree
~~~~~~~~~~~~~~~~~~~~~~~~~~~
apache_logging -
Getting Apache to log to PostgreSQL
by Terry Mackintosh <terry@terrym.com>
FIXME:
os2client
odbc
spi/preprocessor
tools
array -
Array iterator functions
by Massimo Dal Zotto <dz@cs.unitn.it>
- in each directory must be Makefile, possible Makefile template
is below this text,
bit -
Bit type
by Adriaan Joubert <a.joubert@albourne.com>
--------
#
# $Header: /cvsroot/pgsql/contrib/README,v 1.18 2000/06/15 18:54:29 momjian Exp $
#
datetime -
Date & time functions
by Massimo Dal Zotto <dz@cs.unitn.it>
TOPDIR=../..
earthdistance -
Operator for computing earth distance for two points
by Hal Snyder <hal@vailsys.com>
include ../Makefile.global
findoidjoins -
Finds the joins used by oid columns by examining the actual
values in the oid columns and row oids.
by Bruce Momjian <root@candle.pha.pa.us>
NAME = some_name
fulltextindex -
Full text indexing using triggers
by Maarten Boekhold <maartenb@dutepp0.et.tudelft.nl>
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
isbn_issn -
PostgreSQL type extensions for ISBN (books) and ISSN (serials)
by Garrett A. Wollman <wollman@khavrinen.lcs.mit.edu>
CFLAGS += -I. $(CFLAGS_SL)
likeplanning -
Scripts to enable/disable new planning code for LIKE and regexp
pattern match operators. These will go away again once the code
is mature enough to enable by default.
by Tom Lane <tgl@sss.pgh.pa.us>
OTHER_CLEAN = $(SQLS)
linux -
Start postgres back end system
by Thomas Lockhart <lockhart@alumni.caltech.edu>
all: $(MODS) $(SQLS)
lo -
Large Object maintenance
by Peter Mount <peter@retep.org.uk>
%.sql: %.sql.in
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
miscutil -
Postgres assert checking and various utility functions
by Dal Zotto <dz@cs.unitn.it>
mSQL-interface -
mSQL API translation library
by Aldrin Leal <aldrin@americasnet.com>
install: install_doc install_sql install_mod install_bin install_example
noupdate -
trigger to prevent updates on single columns
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
pg_dumplo -
Dump large objects
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
soundex -
Prototype for soundex function
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
spi -
A general trigger function autoinc() and so on.
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
string -
C-like input/output conversion routines for strings
by Massimo Dal Zotto <dz@cs.unitn.it>
install_example:
for inst_file in $(EXAMPLES); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_EXAMPLESDIR); \
done
tools -
Assorted developer tools
by Massimo Dal Zotto <dz@cs.unitn.it>
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
unixdate -
Conversions from integer to datetime
by Thomas Lockhart <lockhart@alumni.caltech.edu>
clean:
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
userlock -
User locks
by Massimo Dal Zotto <dz@cs.unitn.it>
vacuumlo -
Remove orphaned large objects
by Peter T Mount <peter@retep.org.uk>
pgbench -
TPC-B like benchmarking tool
by Tatsuo Ishii <t-ishii@sra.co.jp>
ifeq (depend,$(wildcard depend))
include depend
endif
-----------

View File

@ -1,3 +0,0 @@
drop table access;
CREATE TABLE access (host char(200), ident char(200), authuser char(200), accdate datetime, request char(500), ttime int2, status int2, bytes int4) archive = none;
grant all on access to nobody;

View File

@ -1,12 +0,0 @@
# This is mostly the same as the default, except for no square brakets around
# the time or the extra timezone info, also added the download time, 3rd from
# the end, number of seconds.
LogFormat "insert into access values ( '%h', '%l', '%u', '%{%d/%b/%Y:%H:%M:%S}t', '%r', %T, %s, %b );"
# The above format ALMOST eleminates the need to use sed, except that I noticed
# that when a frameset page is called, then the bytes transfered is '-', which
# will choke the insert, so replaced it with '-1'.
TransferLog '| su -c "sed \"s/, - );$/, -1 );/\" | /usr/local/pgsql/bin/psql www_log" nobody'

View File

@ -1,65 +1,53 @@
#-------------------------------------------------------------------------
#
# Makefile --
# $Header: /cvsroot/pgsql/contrib/array/Attic/Makefile,v 1.8 2000/06/15 18:54:31 momjian Exp $
#
# Makefile for array iterator module.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
NAME = array_iterator
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = array_iterator
OTHER_CLEAN = $(SQLS)
SQLDEFS = $(MODNAME).sql
MODULE = $(MODNAME)$(DLSUFFIX)
MODDIR = $(LIBDIR)/modules
SQLDIR = $(LIBDIR)/sql
all: module sql
module: $(MODULE)
sql: $(SQLDEFS)
install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
cp -p $(MODULE) $(MODDIR)/
strip $(MODDIR)/$(MODULE)
cp -p $(SQLDEFS) $(SQLDIR)/
install-doc:
if [ -d "$(DOCDIR)" ]; then \
cp -p *.doc $(DOCDIR); \
else \
cp -p *.doc $(SQLDIR); \
fi
$(MODDIR):
mkdir -p $@
$(SQLDIR):
mkdir -p $@
all: $(MODS) $(SQLS)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
install: install_doc install_sql install_mod
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f *~ $(MODULE) $(MODNAME).sql
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend

49
contrib/array/README Normal file
View File

@ -0,0 +1,49 @@
Array iterator functions, by Massimo Dal Zotto <dz@cs.unitn.it>
Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
This software is distributed under the GNU General Public License
either version 2, or (at your option) any later version.
This loadable module defines a new class of functions which take
an array and a scalar value, iterate a scalar operator over the
elements of the array and the value, and compute a result as
the logical OR or AND of the iteration results.
For example array_int4eq returns true if some of the elements
of an array of int4 is equal to the given value:
array_int4eq({1,2,3}, 1) --> true
array_int4eq({1,2,3}, 4) --> false
If we have defined T array types and O scalar operators we can
define T x O x 2 array functions, each of them has a name like
"array_[all_]<basetype><operation>" and takes an array of type T
iterating the operator O over all the elements. Note however
that some of the possible combination are invalid, for example
the array_int4_like because there is no like operator for int4.
We can then define new operators based on these functions and use
them to write queries with qualification clauses based on the
values of some of the elements of an array.
For example to select rows having some or all element of an array
attribute equal to a given value or matching a regular expression:
create table t(id int4[], txt text[]);
-- select tuples with some id element equal to 123
select * from t where t.id *= 123;
-- select tuples with some txt element matching '[a-z]'
select * from t where t.txt *~ '[a-z]';
-- select tuples with all txt elements matching '^[A-Z]'
select * from t where t.txt[1:3] **~ '^[A-Z]';
The scheme is quite general, each operator which operates on a base type
can be iterated over the elements of an array. It seem to work well but
defining each new operators requires writing a different C function.
Furthermore in each function there are two hardcoded OIDs which reference
a base type and a procedure. Not very portable. Can anyone suggest a
better and more portable way to do it ?
See also array_iterator.sql for an example on how to use this module.

View File

@ -1,45 +0,0 @@
# Makefile
# For the bit/varbit data types
SRCDIR= ../../src
include $(SRCDIR)/Makefile.global
INSTALLDIR= $(LIBDIR)
MODDIR= $(INSTALLDIR)/modules
SQLDIR= $(INSTALLDIR)/sql
TARGETS= varbit.sql varbit$(DLSUFFIX)
# vartest
SOURCE= varbit.c varbit_glue.c
OBJ= $(SOURCE:.c=.o)
CFLAGS += -g
all: $(TARGETS)
vartest: varbit.o vartest.o
$(CC) -o $@ varbit.o vartest.o
install:
$(MAKE) all
-test -d $(INSTALLDIR) || $(INSTALL) -d $(INSTALLDIR)
-test -d ${MODDIR} || $(INSTALL) -d ${MODDIR}
-test -d ${SQLDIR} || $(INSTALL) -d ${SQLDIR}
$(INSTALL) -m 555 $(filter %$(DLSUFFIX), $(TARGETS)) $(MODDIR)
$(INSTALL) -m 664 $(filter %.sql, $(TARGETS)) $(SQLDIR)
%.sql: %.source
if [ -z "$$USER" ]; then USER=$$LOGNAME; fi; \
if [ -z "$$USER" ]; then USER=`whoami`; fi; \
if [ -z "$$USER" ]; then echo 'Cannot deduce $$USER.'; exit 1; fi; \
rm -f $@; \
C=`pwd`; \
O=${MODDIR}; \
sed -e "s:_CWD_:$$C:g" \
-e "s:_OBJWD_:$$O:g" \
-e "s:_DLSUFFIX_:$(DLSUFFIX):g" \
-e "s/_USER_/$$USER/g" < $< > $@
clean:
rm -f $(TARGETS) varbit.o

View File

@ -1,891 +0,0 @@
/*-------------------------------------------------------------------------
*
* varbit.c
* Functions for the built-in type bit() and varying bit().
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/contrib/bit/Attic/varbit.c,v 1.3 2000/04/12 17:14:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "varbit.h"
#include "access/htup.h"
/*#include "catalog/pg_type.h" */
/*#include "utils/builtins.h" */
/*
Prefixes:
zp -- zero-padded fixed length bit string
var -- varying bit string
attypmod -- contains the length of the bit string in bits, or for
varying bits the maximum length.
The data structure contains the following elements:
header -- length of the whole data structure (incl header)
in bytes. (as with all varying length datatypes)
data section -- private data section for the bits data structures
bitlength -- lenght of the bit string in bits
bitdata -- least significant byte first string
*/
/*
* zpbitin -
* converts a string to the internal representation of a bitstring.
* The length is determined by the number of bits required plus
* VARHDRSZ bytes or from atttypmod.
* (XXX dummy is here because we pass typelem as the second argument
* for array_in. copied this, no idea what it means??)
*/
bits8 *
zpbitin(char *s, int dummy, int32 atttypmod)
{
bits8 *result; /* the bits string that was read in */
char *sp; /* pointer into the character string */
bits8 *r;
int len, /* Length of the whole data structure */
bitlen, /* Number of bits in the bit string */
slen; /* Length of the input string */
int bit_not_hex = 0;/* 0 = hex string 1=bit string */
int bc,
ipad;
bits8 x = 0;
if (s == NULL)
return (bits8 *) NULL;
/* Check that the first character is a b or an x */
if (s[0] == 'b' || s[0] == 'B')
bit_not_hex = 1;
else if (s[0] == 'x' || s[0] == 'X')
bit_not_hex = 0;
else
elog(ERROR, "zpbitin: %s is not a valid bitstring", s);
slen = strlen(s) - 1;
/* Determine bitlength from input string */
bitlen = slen;
if (!bit_not_hex)
bitlen *= 4;
/*
* Sometimes atttypmod is not supplied. If it is supplied we need to
* make sure that the bitstring fits. Note that the number of infered
* bits can be larger than the number of actual bits needed, but only
* if we are reading a hex string and not by more than 3 bits, as a
* hex string gives and accurate length upto 4 bits
*/
if (atttypmod == -1)
atttypmod = bitlen;
else if ((bitlen > atttypmod && bit_not_hex) ||
(bitlen > atttypmod + 3 && !bit_not_hex))
elog(ERROR, "zpbitin: bit string of size %d cannot be written into bits(%d)",
bitlen, atttypmod);
len = VARBITDATALEN(atttypmod);
if (len > MaxAttrSize)
elog(ERROR, "zpbitin: length of bit() must be less than %ld",
(MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE);
result = (bits8 *) palloc(len);
/* set to 0 so that *r is always initialised and strin is zero-padded */
memset(result, 0, len);
VARSIZE(result) = len;
VARBITLEN(result) = atttypmod;
/*
* We need to read the bitstring from the end, as we store it least
* significant byte first. s points to the byte before the beginning
* of the bitstring
*/
sp = s + 1;
r = VARBITS(result);
if (bit_not_hex)
{
/* Parse the bit representation of the string */
/* We know it fits, as bitlen was compared to atttypmod */
x = BITHIGH;
for (bc = 0; sp != s + slen + 1; sp++, bc++)
{
if (*sp == '1')
*r |= x;
if (bc == 7)
{
bc = 0;
x = BITHIGH;
r++;
}
else
x >>= 1;
}
}
else
{
/* Parse the hex representation of the string */
for (bc = 0; sp != s + slen + 1; sp++)
{
if (*sp >= '0' && *sp <= '9')
x = (bits8) (*sp - '0');
else if (*sp >= 'A' && *sp <= 'F')
x = (bits8) (*sp - 'A') + 10;
else if (*sp >= 'a' && *sp <= 'f')
x = (bits8) (*sp - 'a') + 10;
else
elog(ERROR, "Cannot parse %c as a hex digit", *sp);
if (bc)
{
bc = 0;
*r++ |= x;
}
else
{
bc++;
*r = x << 4;
}
}
}
if (bitlen > atttypmod)
{
/* Check that this fitted */
r = (bits8 *) (result + len - 1);
ipad = VARBITPAD(result);
/*
* The bottom ipad bits of the byte pointed to by r need to be
* zero
*/
/*
* printf("Byte %X shift %X %d\n",*r,(*r << (8-ipad)) & BITMASK,
* (*r << (8-ipad)) & BITMASK > 0);
*/
if (((*r << (BITSPERBYTE - ipad)) & BITMASK) > 0)
elog(ERROR, "zpbitin: bit string too large for bit(%d) data type",
atttypmod);
}
return result;
}
/* zpbitout -
* for the time being we print everything as hex strings, as this is likely
* to be more compact than bit strings, and consequently much more efficient
* for long strings
*/
char *
zpbitout(bits8 *s)
{
char *result,
*r;
bits8 *sp;
int i,
len,
bitlen;
if (s == NULL)
{
result = (char *) palloc(2);
result[0] = '-';
result[1] = '\0';
}
else
{
bitlen = VARBITLEN(s);
len = bitlen / 4 + (bitlen % 4 > 0 ? 1 : 0);
result = (char *) palloc(len + 4);
sp = VARBITS(s);
r = result;
*r++ = 'X';
*r++ = '\'';
/* we cheat by knowing that we store full bytes zero padded */
for (i = 0; i < len; i += 2, sp++)
{
*r++ = HEXDIG((*sp) >> 4);
*r++ = HEXDIG((*sp) & 0xF);
}
/*
* Go back one step if we printed a hex number that was not part
* of the bitstring anymore
*/
if (i == len + 1)
r--;
*r++ = '\'';
*r = '\0';
}
return result;
}
/* zpbitsout -
* Prints the string a bits
*/
char *
zpbitsout(bits8 *s)
{
char *result,
*r;
bits8 *sp;
bits8 x;
int i,
k,
len;
if (s == NULL)
{
result = (char *) palloc(2);
result[0] = '-';
result[1] = '\0';
}
else
{
len = VARBITLEN(s);
result = (char *) palloc(len + 4);
sp = VARBITS(s);
r = result;
*r++ = 'B';
*r++ = '\'';
for (i = 0; i < len - BITSPERBYTE; i += BITSPERBYTE, sp++)
{
x = *sp;
for (k = 0; k < BITSPERBYTE; k++)
{
*r++ = (x & BITHIGH) ? '1' : '0';
x <<= 1;
}
}
x = *sp;
for (k = i; k < len; k++)
{
*r++ = (x & BITHIGH) ? '1' : '0';
x <<= 1;
}
*r++ = '\'';
*r = '\0';
}
return result;
}
/*
* varbitin -
* converts a string to the internal representation of a bitstring.
*/
bits8 *
varbitin(char *s, int dummy, int32 atttypmod)
{
bits8 *result; /* The resulting bit string */
char *sp; /* pointer into the character string */
bits8 *r;
int len, /* Length of the whole data structure */
bitlen, /* Number of bits in the bit string */
slen; /* Length of the input string */
int bit_not_hex = 0;
int bc,
ipad;
bits8 x = 0;
if (s == NULL)
return (bits8 *) NULL;
/* Check that the first character is a b or an x */
if (s[0] == 'b' || s[0] == 'B')
bit_not_hex = 1;
else if (s[0] == 'x' || s[0] == 'X')
bit_not_hex = 0;
else
elog(ERROR, "zpbitin: %s is not a valid bitstring", s);
slen = strlen(s) - 1;
/* Determine bitlength from input string */
bitlen = slen;
if (!bit_not_hex)
bitlen *= 4;
/*
* Sometimes atttypmod is not supplied. If it is supplied we need to
* make sure that the bitstring fits. Note that the number of infered
* bits can be larger than the number of actual bits needed, but only
* if we are reading a hex string and not by more than 3 bits, as a
* hex string gives and accurate length upto 4 bits
*/
if (atttypmod > -1)
if ((bitlen > atttypmod && bit_not_hex) ||
(bitlen > atttypmod + 3 && !bit_not_hex))
elog(ERROR, "varbitin: bit string of size %d cannot be written into varying bits(%d)",
bitlen, atttypmod);
len = VARBITDATALEN(bitlen);
if (len > MaxAttrSize)
elog(ERROR, "varbitin: length of bit() must be less than %ld",
(MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE);
result = (bits8 *) palloc(len);
/* set to 0 so that *r is always initialised and strin is zero-padded */
memset(result, 0, len);
VARSIZE(result) = len;
VARBITLEN(result) = bitlen;
/*
* We need to read the bitstring from the end, as we store it least
* significant byte first. s points to the byte before the beginning
* of the bitstring
*/
sp = s + 1;
r = VARBITS(result);
if (bit_not_hex)
{
/* Parse the bit representation of the string */
x = BITHIGH;
for (bc = 0; sp != s + slen + 1; sp++, bc++)
{
if (*sp == '1')
*r |= x;
if (bc == 7)
{
bc = 0;
x = BITHIGH;
r++;
}
else
x >>= 1;
}
}
else
{
for (bc = 0; sp != s + slen + 1; sp++)
{
if (*sp >= '0' && *sp <= '9')
x = (bits8) (*sp - '0');
else if (*sp >= 'A' && *sp <= 'F')
x = (bits8) (*sp - 'A') + 10;
else if (*sp >= 'a' && *sp <= 'f')
x = (bits8) (*sp - 'a') + 10;
else
elog(ERROR, "Cannot parse %c as a hex digit", *sp);
if (bc)
{
bc = 0;
*r++ |= x;
}
else
{
bc++;
*r = x << 4;
}
}
}
if (bitlen > atttypmod)
{
/* Check that this fitted */
r = (bits8 *) (result + len - 1);
ipad = VARBITPAD(result);
/*
* The bottom ipad bits of the byte pointed to by r need to be
* zero
*/
if (((*r << (BITSPERBYTE - ipad)) & BITMASK) > 0)
elog(ERROR, "varbitin: bit string too large for varying bit(%d) data type",
atttypmod);
}
return result;
}
/*
the zpbitout routines are fine for varying bits as well
*/
/*
* Comparison operators
*
* We only need one set of comparison operators for bitstrings, as the lengths
* are stored in the same way for zero-padded and varying bit strings.
*
* Note that the standard is not unambiguous about the comparison between
* zero-padded bit strings and varying bitstrings. If the same value is written
* into a zero padded bitstring as into a varying bitstring, but the zero
* padded bitstring has greater length, it will be bigger.
*
* Zeros from the beginning of a bitstring cannot simply be ignored, as they
* may be part of a bit string and may be significant.
*/
bool
biteq(bits8 *arg1, bits8 *arg2)
{
int bitlen1,
bitlen2;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
if (bitlen1 != bitlen2)
return (bool) 0;
/* bit strings are always stored in a full number of bytes */
return memcmp((void *) VARBITS(arg1), (void *) VARBITS(arg2),
VARBITBYTES(arg1)) == 0;
}
bool
bitne(bits8 *arg1, bits8 *arg2)
{
int bitlen1,
bitlen2;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
if (bitlen1 != bitlen2)
return (bool) 1;
/* bit strings are always stored in a full number of bytes */
return memcmp((void *) VARBITS(arg1), (void *) VARBITS(arg2),
VARBITBYTES(arg1)) != 0;
}
/* bitcmp
*
* Compares two bitstrings and returns -1, 0, 1 depending on whether the first
* string is smaller, equal, or bigger than the second. All bits are considered
* and additional zero bits may make one string smaller/larger than the other,
* even if their zero-padded values would be the same.
* Anything is equal to undefined.
*/
int
bitcmp(bits8 *arg1, bits8 *arg2)
{
int bitlen1,
bytelen1,
bitlen2,
bytelen2;
int cmp;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
bytelen1 = VARBITBYTES(arg1);
bytelen2 = VARBITBYTES(arg2);
cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
if (cmp == 0)
{
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
if (bitlen1 != bitlen2)
return bitlen1 < bitlen2 ? -1 : 1;
}
return cmp;
}
bool
bitlt(bits8 *arg1, bits8 *arg2)
{
return (bool) (bitcmp(arg1, arg2) == -1);
}
bool
bitle(bits8 *arg1, bits8 *arg2)
{
return (bool) (bitcmp(arg1, arg2) <= 0);
}
bool
bitge(bits8 *arg1, bits8 *arg2)
{
return (bool) (bitcmp(arg1, arg2) >= 0);
}
bool
bitgt(bits8 *arg1, bits8 *arg2)
{
return (bool) (bitcmp(arg1, arg2) == 1);
}
/* bitcat
* Concatenation of bit strings
*/
bits8 *
bitcat(bits8 *arg1, bits8 *arg2)
{
int bitlen1,
bitlen2,
bytelen,
bit1pad,
bit2shift;
bits8 *result;
bits8 *pr,
*pa;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return NULL;
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
bytelen = VARBITDATALEN(bitlen1 + bitlen2);
result = (bits8 *) palloc(bytelen * sizeof(bits8));
VARSIZE(result) = bytelen;
VARBITLEN(result) = bitlen1 + bitlen2;
printf("%d %d %d \n", VARBITBYTES(arg1), VARBITLEN(arg1), VARBITPAD(arg1));
/* Copy the first bitstring in */
memcpy(VARBITS(result), VARBITS(arg1), VARBITBYTES(arg1));
/* Copy the second bit string */
bit1pad = VARBITPAD(arg1);
if (bit1pad == 0)
{
memcpy(VARBITS(result) + VARBITBYTES(arg1), VARBITS(arg2),
VARBITBYTES(arg2));
}
else if (bitlen2 > 0)
{
/* We need to shift all the results to fit */
bit2shift = BITSPERBYTE - bit1pad;
pa = VARBITS(arg2);
pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
for (; pa < VARBITEND(arg2); pa++)
{
*pr |= ((*pa >> bit2shift) & BITMASK);
pr++;
if (pr < VARBITEND(result))
*pr = (*pa << bit1pad) & BITMASK;
}
}
return result;
}
/* bitsubstr
* retrieve a substring from the bit string.
* Note, s is 1-based.
* SQL draft 6.10 9)
*/
bits8 *
bitsubstr(bits8 *arg, int32 s, int32 l)
{
int bitlen,
rbitlen,
len,
ipad = 0,
ishift,
i;
int e,
s1,
e1;
bits8 *result;
bits8 mask,
*r,
*ps;
if (!PointerIsValid(arg))
return NULL;
bitlen = VARBITLEN(arg);
e = s + l;
s1 = Max(s, 1);
e1 = Min(e, bitlen + 1);
if (s1 > bitlen || e1 < 1)
{
/* Need to return a null string */
len = VARBITDATALEN(0);
result = (bits8 *) palloc(len);
VARBITLEN(result) = 0;
VARSIZE(result) = len;
}
else
{
/*
* OK, we've got a true substring starting at position s1-1 and
* ending at position e1-1
*/
rbitlen = e1 - s1;
len = VARBITDATALEN(rbitlen);
result = (bits8 *) palloc(len);
VARBITLEN(result) = rbitlen;
VARSIZE(result) = len;
len -= VARHDRSZ + VARBITHDRSZ;
/* Are we copying from a byte boundary? */
if ((s1 - 1) % BITSPERBYTE == 0)
{
/* Yep, we are copying bytes */
memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITSPERBYTE, len);
}
else
{
/* Figure out how much we need to shift the sequence by */
ishift = (s1 - 1) % BITSPERBYTE;
r = VARBITS(result);
ps = VARBITS(arg) + (s1 - 1) / BITSPERBYTE;
for (i = 0; i < len; i++)
{
*r = (*ps << ishift) & BITMASK;
if ((++ps) < VARBITEND(arg))
*r |= *ps >> (BITSPERBYTE - ishift);
r++;
}
}
/* Do we need to pad at the end? */
ipad = VARBITPAD(result);
if (ipad > 0)
{
mask = BITMASK << ipad;
*(VARBITS(result) + len - 1) &= mask;
}
}
return result;
}
/* bitand
* perform a logical AND on two bit strings. The result is automatically
* truncated to the shorter bit string
*/
bits8 *
bitand(bits8 *arg1, bits8 *arg2)
{
int len,
i;
bits8 *result;
bits8 *p1,
*p2,
*r;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
len = Min(VARSIZE(arg1), VARSIZE(arg2));
result = (bits8 *) palloc(len);
VARSIZE(result) = len;
VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
p1 = (bits8 *) VARBITS(arg1);
p2 = (bits8 *) VARBITS(arg2);
r = (bits8 *) VARBITS(result);
for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
*r++ = *p1++ & *p2++;
/* Padding is not needed as & of 0 pad is 0 */
return result;
}
/* bitor
* perform a logical OR on two bit strings. The result is automatically
* truncated to the shorter bit string.
*/
bits8 *
bitor(bits8 *arg1, bits8 *arg2)
{
int len,
i;
bits8 *result;
bits8 *p1,
*p2,
*r;
bits8 mask;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
len = Min(VARSIZE(arg1), VARSIZE(arg2));
result = (bits8 *) palloc(len);
VARSIZE(result) = len;
VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
p1 = (bits8 *) VARBITS(arg1);
p2 = (bits8 *) VARBITS(arg2);
r = (bits8 *) VARBITS(result);
for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
*r++ = *p1++ | *p2++;
/* Pad the result */
mask = BITMASK << VARBITPAD(result);
*r &= mask;
return result;
}
/* bitxor
* perform a logical XOR on two bit strings. The result is automatically
* truncated to the shorter bit string.
*/
bits8 *
bitxor(bits8 *arg1, bits8 *arg2)
{
int len,
i;
bits8 *result;
bits8 *p1,
*p2,
*r;
bits8 mask;
if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
return (bool) 0;
len = Min(VARSIZE(arg1), VARSIZE(arg2));
result = (bits8 *) palloc(len);
VARSIZE(result) = len;
VARBITLEN(result) = Min(VARBITLEN(arg1), VARBITLEN(arg2));
p1 = (bits8 *) VARBITS(arg1);
p2 = (bits8 *) VARBITS(arg2);
r = (bits8 *) VARBITS(result);
for (i = 0; i < Min(VARBITBYTES(arg1), VARBITBYTES(arg2)); i++)
*r++ = *p1++ ^ *p2++;
/* Pad the result */
mask = BITMASK << VARBITPAD(result);
*r &= mask;
return result;
}
/* bitnot
* perform a logical NOT on a bit strings.
*/
bits8 *
bitnot(bits8 *arg)
{
bits8 *result;
bits8 *p,
*r;
bits8 mask;
if (!PointerIsValid(arg))
return (bool) 0;
result = (bits8 *) palloc(VARSIZE(arg));
VARSIZE(result) = VARSIZE(arg);
VARBITLEN(result) = VARBITLEN(arg);
p = (bits8 *) VARBITS(arg);
r = (bits8 *) VARBITS(result);
for (; p < VARBITEND(arg); p++, r++)
*r = ~*p;
/* Pad the result */
mask = BITMASK << VARBITPAD(result);
*r &= mask;
return result;
}
/* bitshiftleft
* do a left shift (i.e. to the beginning of the string) of the bit string
*/
bits8 *
bitshiftleft(bits8 *arg, int shft)
{
int byte_shift,
ishift,
len;
bits8 *result;
bits8 *p,
*r;
if (!PointerIsValid(arg))
return (bool) 0;
/* Negative shift is a shift to the right */
if (shft < 0)
return bitshiftright(arg, -shft);
result = (bits8 *) palloc(VARSIZE(arg));
VARSIZE(result) = VARSIZE(arg);
VARBITLEN(result) = VARBITLEN(arg);
r = (bits8 *) VARBITS(result);
byte_shift = shft / BITSPERBYTE;
ishift = shft % BITSPERBYTE;
p = ((bits8 *) VARBITS(arg)) + byte_shift;
if (ishift == 0)
{
/* Special case: we can do a memcpy */
len = VARBITBYTES(arg) - byte_shift;
memcpy(r, p, len);
memset(r + len, 0, byte_shift);
}
else
{
for (; p < VARBITEND(arg); r++)
{
*r = *p << ishift;
if ((++p) < VARBITEND(arg))
*r |= *p >> (BITSPERBYTE - ishift);
}
for (; r < VARBITEND(result); r++)
*r = (bits8) 0;
}
return result;
}
/* bitshiftright
* do a right shift (i.e. to the beginning of the string) of the bit string
*/
bits8 *
bitshiftright(bits8 *arg, int shft)
{
int byte_shift,
ishift,
len;
bits8 *result;
bits8 *p,
*r;
if (!PointerIsValid(arg))
return (bits8 *) 0;
/* Negative shift is a shift to the left */
if (shft < 0)
return bitshiftleft(arg, -shft);
result = (bits8 *) palloc(VARSIZE(arg));
VARSIZE(result) = VARSIZE(arg);
VARBITLEN(result) = VARBITLEN(arg);
r = (bits8 *) VARBITS(result);
byte_shift = shft / BITSPERBYTE;
ishift = shft % BITSPERBYTE;
p = (bits8 *) VARBITS(arg);
/* Set the first part of the result to 0 */
memset(r, 0, byte_shift);
if (ishift == 0)
{
/* Special case: we can do a memcpy */
len = VARBITBYTES(arg) - byte_shift;
memcpy(r + byte_shift, p, len);
}
else
{
r += byte_shift;
*r = 0; /* Initialise first byte */
for (; r < VARBITEND(result); p++)
{
*r |= *p >> ishift;
if ((++r) < VARBITEND(result))
*r = (*p << (BITSPERBYTE - ishift)) & BITMASK;
}
}
return result;
}

View File

@ -1,29 +0,0 @@
create table bit_example (a bit, b bit);
copy bit_example from stdin;
X0F X10
X1F X11
X2F X12
X3F X13
X8F X04
X000F X0010
X0123 XFFFF
X2468 X2468
XFA50 X05AF
X12345 XFFF
\.
select a,b,a||b as "a||b", bitsubstr(a,4,4) as "sub(a,4,4)",
bitsubstr(b,2,4) as "sub(b,2,4)",
bitsubstr(b,5,5) as "sub(b,5,5)"
from bit_example;
select a,b,~a as "~ a",~b as "~ b",a & b as "a & b",
a|b as "a | b", a^b as "a ^ b" from bit_example;
select a,b,a<b as "a<b",a<=b as "a<=b",a=b as "a=b",
a>=b as "a>=b",a>b as "a>b",a<=>b as "a<=>b" from bit_example;
select a,a<<4 as "a<<4",b,b>>2 as "b>>2" from bit_example;
select a,b,a||b as "a||b", bitsubstr(a,4,4) as "sub(a,4,4)",
bitsubstr(b,2,4) as "sub(b,2,4)",
bitsubstr(b,5,5) as "sub(b,5,5)"
from bit_example;
drop table bit_example;

View File

@ -1,36 +0,0 @@
DROP FUNCTION biteq(bits,bits);
DROP OPERATOR = (bits,bits);
DROP FUNCTION bitne(bits,bits);
DROP OPERATOR <> (bits,bits);
DROP FUNCTION bitlt(bits,bits);
DROP OPERATOR < (bits,bits);
DROP FUNCTION bitle(bits,bits);
DROP OPERATOR <= (bits,bits);
DROP FUNCTION bitgt(bits,bits);
DROP OPERATOR > (bits,bits);
DROP FUNCTION bitge(bits,bits);
DROP OPERATOR >= (bits,bits);
DROP FUNCTION bitcmp(bits,bits);
DROP OPERATOR <=> (bits,bits);
DROP FUNCTION bitor(bits,bits);
DROP OPERATOR | (bits,bits);
DROP FUNCTION bitand(bits,bits);
DROP OPERATOR & (bits,bits);
DROP FUNCTION bitxor(bits,bits);
DROP OPERATOR ^ (bits,bits);
DROP FUNCTION bitnot(bits);
DROP OPERATOR ~ (none,bits);
DROP FUNCTION bitshiftleft(bits,int4);
DROP OPERATOR << (bits,int4);
DROP FUNCTION bitshiftright(bits,int4);
DROP OPERATOR >> (bits,int4);
DROP FUNCTION bitsubstr(bits,integer,integer);
DROP OPERATOR || (bits,bits);
DROP FUNCTION bitcat(bits,bits);
DROP FUNCTION varbit_in(opaque);
DROP FUNCTION varbit_out(opaque);
DROP TYPE bits;

View File

@ -1,73 +0,0 @@
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <float.h> /* faked on sunos4 */
#include <math.h>
#include "postgres.h"
#ifdef HAVE_LIMITS_H
#include <limits.h>
#ifndef MAXINT
#define MAXINT INT_MAX
#endif
#else
#ifdef HAVE_VALUES_H
#include <values.h>
#endif
#endif
#include "fmgr.h"
#include "utils/timestamp.h"
#include "utils/builtins.h"
#define HEXDIG(z) (z)<10 ? ((z)+'0') : ((z)-10+'A')
/* Modeled on struct varlena from postgres.h, bu data type is bits8 */
struct varbita
{
int32 vl_len;
bits8 vl_dat[1];
};
#define BITSPERBYTE 8
#define VARBITHDRSZ sizeof(int32)
/* Number of bits in this bit string */
#define VARBITLEN(PTR) (((struct varbita *)VARDATA(PTR))->vl_len)
/* Pointer tp the first byte containing bit string data */
#define VARBITS(PTR) (((struct varbita *)VARDATA(PTR))->vl_dat)
/* Number of bytes in the data section of a bit string */
#define VARBITBYTES(PTR) (VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ)
/* Padding of the bit string at the end */
#define VARBITPAD(PTR) (VARBITBYTES(PTR)*BITSPERBYTE - VARBITLEN(PTR))
/* Number of bytes needed to store a bit string of a given length */
#define VARBITDATALEN(BITLEN) (BITLEN/BITSPERBYTE + \
(BITLEN%BITSPERBYTE > 0 ? 1 : 0) + \
VARHDRSZ + VARBITHDRSZ)
/* pointer beyond the end of the bit string (like end() in STL containers) */
#define VARBITEND(PTR) ((bits8 *) (PTR + VARSIZE(PTR)))
/* Mask that will cover exactly one byte, i.e. BITSPERBYTE bits */
#define BITMASK 0xFF
#define BITHIGH 0x80
bits8 *zpbitin(char *s, int dummy, int32 atttypmod);
char *zpbitout(bits8 *s);
char *zpbitsout(bits8 *s);
bits8 *varbitin(char *s, int dummy, int32 atttypmod);
bool biteq(bits8 *arg1, bits8 *arg2);
bool bitne(bits8 *arg1, bits8 *arg2);
bool bitge(bits8 *arg1, bits8 *arg2);
bool bitgt(bits8 *arg1, bits8 *arg2);
bool bitle(bits8 *arg1, bits8 *arg2);
bool bitlt(bits8 *arg1, bits8 *arg2);
int bitcmp(bits8 *arg1, bits8 *arg2);
bits8 *bitand(bits8 *arg1, bits8 *arg2);
bits8 *bitor(bits8 *arg1, bits8 *arg2);
bits8 *bitxor(bits8 *arg1, bits8 *arg2);
bits8 *bitnot(bits8 *arg);
bits8 *bitshiftright(bits8 *arg, int shft);
bits8 *bitshiftleft(bits8 *arg, int shft);
bits8 *bitcat(bits8 *arg1, bits8 *arg2);
bits8 *bitsubstr(bits8 *arg, int32 s, int32 l);

View File

@ -1,171 +0,0 @@
LOAD '_OBJWD_/varbit.so';
CREATE FUNCTION varbitin(opaque)
RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'c';
CREATE FUNCTION zpbitout(opaque)
RETURNS opaque
AS '_OBJWD_/varbit.so'
LANGUAGE 'c';
CREATE TYPE bit (
internallength = -1,
input = varbitin,
output = zpbitout
);
CREATE FUNCTION bitcat(bit,bit) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR || (
leftarg = bit,
rightarg = bit,
procedure = bitcat
);
CREATE FUNCTION bitsubstr(bit,integer,integer) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE FUNCTION biteq(bit,bit) RETURNS bool
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR = (
leftarg = bit,
rightarg = bit,
procedure = biteq,
negator = <>,
commutator = =
);
CREATE FUNCTION bitne(bit,bit) RETURNS bool
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR <> (
leftarg = bit,
rightarg = bit,
procedure = bitne,
negator = =,
commutator = <>
);
CREATE FUNCTION bitlt(bit,bit) RETURNS bool
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR < (
leftarg = bit,
rightarg = bit,
procedure = bitlt
);
CREATE FUNCTION bitle(bit,bit) RETURNS bool
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR <= (
leftarg = bit,
rightarg = bit,
procedure = bitle
);
CREATE FUNCTION bitgt(bit,bit) RETURNS bool
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR > (
leftarg = bit,
rightarg = bit,
procedure = bitgt,
negator = <=,
commutator = <
);
CREATE FUNCTION bitge(bit,bit) RETURNS bool
as '_OBJWD_/varbit.so'
language 'C';
CREATE OPERATOR >= (
leftarg = bit,
rightarg = bit,
procedure = bitge,
negator = <,
commutator = <=
);
CREATE FUNCTION bitcmp(bit,bit) RETURNS integer
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR <=> (
leftarg = bit,
rightarg = bit,
procedure = bitcmp
);
CREATE FUNCTION bitor(bit,bit) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR | (
leftarg = bit,
rightarg = bit,
procedure = bitor,
commutator = |
);
CREATE FUNCTION bitand(bit,bit) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR & (
leftarg = bit,
rightarg = bit,
procedure = bitand,
commutator = &
);
CREATE FUNCTION bitxor(bit,bit) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR ^ (
leftarg = bit,
rightarg = bit,
procedure = bitxor
);
CREATE FUNCTION bitnot(bit) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR ~ (
rightarg = bit,
procedure = bitnot
);
CREATE FUNCTION bitshiftleft(bit,integer) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR << (
leftarg = bit,
rightarg = integer,
procedure = bitshiftleft
);
CREATE FUNCTION bitshiftright(bit,integer) RETURNS bit
AS '_OBJWD_/varbit.so'
LANGUAGE 'C';
CREATE OPERATOR >> (
leftarg = bit,
rightarg = integer,
procedure = bitshiftright
);

View File

@ -1,24 +0,0 @@
/* Glue file to use varbit before it is properly integrated with postgres */
#include "varbit.h"
bits8 *varbit_in(char *s);
char *varbit_out(bits8 *s);
bits8 *
varbit_in(char *s)
{
return varbitin(s, 0, -1);
}
/*char *
varbit_out (bits8 *s) {
return zpbitout(s);
}
*/
char *
varbit_out(bits8 *s)
{
return zpbitsout(s);
}

View File

@ -1,184 +0,0 @@
#include "postgres.h"
#include "varbit.h"
#include <stdio.h>
void print_details(unsigned char *s);
const int numb = 8;
/*
const char *b[] = { "B0010", "B11011011", "B0001", "X3F12", "X27", "B",
"X11", "B100111"};
int atttypmod[] = {-1, -1, -1,-1,-1,-1,-1,-1 };
*/
const char *b[] = {"B0010", "B11011011", "B10001", "X3D12", "X27", "B",
"X11", "B100111"};
int atttypmod[] = {7, 9, 6, 18, 11, 6, -1, -1};
void
print_details(unsigned char *s)
{
int i;
printf("Length in bytes : %d\n", VARSIZE(s));
printf("Length of bitstring: %d\n", VARBITLEN(s));
for (i = 8; i < VARSIZE(s); i++)
printf("%X%X ", s[i] >> 4, s[i] & 0xF);
printf("\n");
}
int
main()
{
int i,
j;
char *s[numb];
for (i = 0; i < numb; i++)
{
printf("Input: %s\n", b[i]);
s[i] = zpbitin(b[i], 0, atttypmod[i]);
//print_details(s[i]);
printf("%s = %s\n", zpbitout(s[i]), zpbitsout(s[i]));
}
printf("\nCOMPARISONS:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s <=> %s = %d\n", zpbitsout(s[i]), zpbitsout(s[j]),
bitcmp(s[i], s[j]));
printf("\nCONCATENATION:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s || %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitcat(s[i], s[j])));
printf("\nSUBSTR:\n");
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 1, 8,
zpbitsout(bitsubstr(s[3], 1, 8)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 9, 8,
zpbitsout(bitsubstr(s[3], 9, 8)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 1, 9,
zpbitsout(bitsubstr(s[3], 1, 9)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 3, 5,
zpbitsout(bitsubstr(s[3], 3, 5)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 3, 9,
zpbitsout(bitsubstr(s[3], 3, 9)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 3, 17,
zpbitsout(bitsubstr(s[3], 3, 17)));
printf("\nLOGICAL AND:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s & %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitand(s[i], s[j])));
printf("\nLOGICAL OR:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s | %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitor(s[i], s[j])));
printf("\nLOGICAL XOR:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s ^ %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitxor(s[i], s[j])));
printf("\nLOGICAL NOT:\n");
for (i = 0; i < numb; i++)
printf("~%s = %s\n", zpbitsout(s[i]), zpbitsout(bitnot(s[i])));
printf("\nSHIFT LEFT:\n");
for (i = 0; i < numb; i++)
{
printf("%s\n", zpbitsout(s[i]));
for (j = 0; j <= VARBITLEN(s[i]); j++)
printf("\t%3d\t%s\n", j, zpbitsout(bitshiftleft(s[i], j)));
}
printf("\nSHIFT RIGHT:\n");
for (i = 0; i < numb; i++)
{
printf("%s\n", zpbitsout(s[i]));
for (j = 0; j <= VARBITLEN(s[i]); j++)
printf("\t%3d\t%s\n", j, zpbitsout(bitshiftright(s[i], j)));
}
printf("\n\n ********** VARYING **********\n");
for (i = 0; i < numb; i++)
{
printf("Input: %s\n", b[i]);
s[i] = varbitin(b[i], 0, atttypmod[i]);
/* print_details(s); */
printf("%s\n", zpbitout(s[i]));
printf("%s\n", zpbitsout(s[i]));
}
printf("\nCOMPARISONS:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s <=> %s = %d\n", zpbitsout(s[i]), zpbitsout(s[j]),
bitcmp(s[i], s[j]));
printf("\nCONCATENATION:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s || %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitcat(s[i], s[j])));
printf("\nSUBSTR:\n");
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 1, 8,
zpbitsout(bitsubstr(s[3], 1, 8)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 9, 8,
zpbitsout(bitsubstr(s[3], 9, 8)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 1, 9,
zpbitsout(bitsubstr(s[3], 1, 9)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 3, 5,
zpbitsout(bitsubstr(s[3], 3, 5)));
printf("%s (%d,%d) => %s\n", zpbitsout(s[3]), 3, 9,
zpbitsout(bitsubstr(s[3], 3, 9)));
printf("%s (%d,%d) => %s (%s)\n", zpbitsout(s[3]), 3, 17,
zpbitsout(bitsubstr(s[3], 3, 17)), zpbitsout(bitsubstr(s[3], 3, 17)));
printf("\nLOGICAL AND:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s & %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitand(s[i], s[j])));
printf("\nLOGICAL OR:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s | %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitor(s[i], s[j])));
printf("\nLOGICAL XOR:\n");
for (i = 0; i < numb; i++)
for (j = i + 1; j < numb; j++)
printf("%s ^ %s = %s\n", zpbitsout(s[i]), zpbitsout(s[j]),
zpbitsout(bitxor(s[i], s[j])));
printf("\nLOGICAL NOT:\n");
for (i = 0; i < numb; i++)
printf("~%s = %s\n", zpbitsout(s[i]), zpbitsout(bitnot(s[i])));
printf("\nSHIFT LEFT:\n");
for (i = 0; i < numb; i++)
{
printf("%s\n", zpbitsout(s[i]));
for (j = 0; j <= VARBITLEN(s[i]); j++)
printf("\t%3d\t%s\n", j, zpbitsout(bitshiftleft(s[i], j)));
}
printf("\nSHIFT RIGHT:\n");
for (i = 0; i < numb; i++)
{
printf("%s\n", zpbitsout(s[i]));
for (j = 0; j <= VARBITLEN(s[i]); j++)
printf("\t%3d\t%s\n", j, zpbitsout(bitshiftright(s[i], j)));
}
}

View File

@ -1,66 +0,0 @@
#-------------------------------------------------------------------------
#
# Makefile --
#
# Makefile for new datetime module.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
include $(SRCDIR)/Makefile.global
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = datetime_functions
SQLDEFS = $(MODNAME).sql
MODULE = $(MODNAME)$(DLSUFFIX)
MODDIR = $(LIBDIR)/modules
SQLDIR = $(LIBDIR)/sql
all: module sql
module: $(MODULE)
sql: $(SQLDEFS)
install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
cp -p $(MODULE) $(MODDIR)/
strip $(MODDIR)/$(MODULE)
cp -p $(SQLDEFS) $(SQLDIR)/
install-doc:
if [ -d "$(DOCDIR)" ]; then \
cp -p *.doc $(DOCDIR); \
else \
cp -p *.doc $(SQLDIR); \
fi
$(MODDIR):
mkdir -p $@
$(SQLDIR):
mkdir -p $@
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
clean:
rm -f *~ $(MODULE) $(MODNAME).sql
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,281 +0,0 @@
/*
* datetime_functions.c --
*
* This file defines new functions for the time and date data types.
*
* Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
*
* Date2mjd code contributed by Reiner Dassing <dassing@wettzell.ifag.de>
*
* This software is distributed under the GNU General Public License
* either version 2, or (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <limits.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#include "postgres.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/nabstime.h"
#include "utils/datetime.h"
#include "access/xact.h"
#include "datetime_functions.h"
/* Constant to replace calls to date2j(2000,1,1) */
#define JDATE_2000 2451545
/*
* decode_24h_time()
*
* Decode time string 00:00:00 through 24:00:00.
*/
static int
decode_24h_time(char *str, struct tm * tm, double *fsec)
{
char *cp;
tm->tm_hour = strtol(str, &cp, 10);
if (*cp != ':')
return -1;
str = cp + 1;
tm->tm_min = strtol(str, &cp, 10);
if (*cp == '\0')
{
tm->tm_sec = 0;
*fsec = 0;
}
else if (*cp != ':')
return -1;
else
{
str = cp + 1;
tm->tm_sec = strtol(str, &cp, 10);
if (*cp == '\0')
*fsec = 0;
else if (*cp == '.')
{
str = cp;
*fsec = strtod(str, &cp);
if (cp == str)
return -1;
}
else
return -1;
}
/* do a sanity check */
if ((tm->tm_hour < 0) || (tm->tm_hour > 24)
|| (tm->tm_min < 0) || (tm->tm_min > 59)
|| (tm->tm_sec < 0) || (tm->tm_sec > 59)
|| (*fsec < 0))
return -1;
return 0;
}
/*
* A modified version of time_in which allows the value 24:00:00 for
* time and converts it to TimeADT data type forcing seconds to 0.
* This can be useful if you need to handle TimeADT values limited
* to hh:mm like in timetables.
*/
TimeADT *
hhmm_in(char *str)
{
TimeADT *time;
double fsec;
struct tm tt,
*tm = &tt;
if (!PointerIsValid(str))
elog(ERROR, "Bad (null) time external representation");
if (decode_24h_time(str, tm, &fsec) != 0)
elog(ERROR, "Bad time external representation '%s'", str);
if ((tm->tm_hour < 0) || (tm->tm_hour > 24)
|| ((tm->tm_hour == 24)
&& ((tm->tm_min != 0) || (tm->tm_sec != 0) || (fsec != 0.0))))
{
elog(ERROR,
"Time must be limited to values 00:00:00 through 24:00:00 "
"in \"%s\"",
str);
}
time = palloc(sizeof(TimeADT));
*time = ((((tm->tm_hour * 60) + tm->tm_min) * 60));
return (time);
}
/*
* A modified version of time_out which converts from TimeADT data type
* omitting the seconds field when it is 0.
* Useful if you need to handle TimeADT values limited to hh:mm.
*/
char *
hhmm_out(TimeADT *time)
{
char *result;
struct tm tt,
*tm = &tt;
char buf[MAXDATELEN + 1];
if (!PointerIsValid(time))
return NULL;
tm->tm_hour = (*time / (60 * 60));
tm->tm_min = (((int) (*time / 60)) % 60);
tm->tm_sec = (((int) *time) % 60);
if (tm->tm_sec == 0)
sprintf(buf, "%02d:%02d", tm->tm_hour, tm->tm_min);
else
sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
result = palloc(strlen(buf) + 1);
strcpy(result, buf);
return (result);
}
TimeADT *
hhmm(TimeADT *time)
{
TimeADT *result = palloc(sizeof(TimeADT));
*result = (((int) *time) / 60 * 60);
return (result);
}
TimeADT *
time_difference(TimeADT *time1, TimeADT *time2)
{
TimeADT *time = palloc(sizeof(TimeADT));
*time = (*time1 - *time2);
return (time);
}
int4
time_hours(TimeADT *time)
{
return (((int) *time) / 3600);
}
int4
time_minutes(TimeADT *time)
{
return ((((int) *time) / 60) % 60);
}
int4
time_seconds(TimeADT *time)
{
return (((int) *time) % 60);
}
int4
as_minutes(TimeADT *time)
{
return (((int) *time) / 60);
}
int4
as_seconds(TimeADT *time)
{
return ((int) *time);
}
int4
date_day(DateADT val)
{
int year,
month,
day;
j2date(val + JDATE_2000, &year, &month, &day);
return (day);
}
int4
date_month(DateADT val)
{
int year,
month,
day;
j2date(val + JDATE_2000, &year, &month, &day);
return (month);
}
int4
date_year(DateADT val)
{
int year,
month,
day;
j2date(val + JDATE_2000, &year, &month, &day);
return (year);
}
TimeADT *
currenttime()
{
TimeADT *result = palloc(sizeof(TimeADT));
struct tm *tm;
time_t current_time;
current_time = time(NULL);
tm = localtime(&current_time);
*result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec);
return (result);
}
DateADT
currentdate()
{
DateADT date;
struct tm tt,
*tm = &tt;
GetCurrentTime(tm);
date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - JDATE_2000);
return (date);
}
int4
date2mjd(DateADT val)
{
int result;
result = val + JDATE_2000 - 2400000.5;
return result;
}
/* end of file */
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/

View File

@ -1,28 +0,0 @@
#ifndef DATETIME_FUNCTIONS_H
#define DATETIME_FUNCTIONS_H
TimeADT *hhmm_in(char *str);
char *hhmm_out(TimeADT *time);
TimeADT *hhmm(TimeADT *time);
TimeADT *time_difference(TimeADT *time1, TimeADT *time2);
int4 time_hours(TimeADT *time);
int4 time_minutes(TimeADT *time);
int4 time_seconds(TimeADT *time);
int4 as_minutes(TimeADT *time);
int4 as_seconds(TimeADT *time);
int4 date_day(DateADT val);
int4 date_month(DateADT val);
int4 date_year(DateADT val);
TimeADT *currenttime(void);
DateADT currentdate(void);
int4 date2mjd(DateADT val);
#endif
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/

View File

@ -1,100 +0,0 @@
-- datetime_functions.sql --
--
-- SQL code to define the new date and time functions and operators
--
-- Copyright (c) 1998, Massimo Dal Zotto <dz@cs.unitn.it>
--
-- This file is distributed under the GNU General Public License
-- either version 2, or (at your option) any later version.
-- Define the new time functions.
--
create function hhmm_in(opaque) returns time
as 'MODULE_PATHNAME'
language 'c';
create function hhmm_out(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function hhmm(time) returns time
as 'MODULE_PATHNAME'
language 'c';
create function time_difference(time,time) returns time
as 'MODULE_PATHNAME'
language 'c';
create function time_hours(time) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function time_minutes(time) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function time_seconds(time) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function as_minutes(time) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function as_seconds(time) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function date_day(date) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function date_month(date) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function date_year(date) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function currenttime() returns time
as 'MODULE_PATHNAME'
language 'c';
create function currentdate() returns date
as 'MODULE_PATHNAME'
language 'c';
-- Define new operator - for time.
--
create operator - (
leftarg=time,
rightarg=time,
procedure=time_difference);
-- Define functions to switch from time to hhmm representation.
--
-- select hhmm_mode();
-- select time_mode();
--
create function hhmm_mode() returns text
as 'update pg_type set typinput =''hhmm_in'' where typname=''time'';
update pg_type set typoutput=''hhmm_out'' where typname=''time'';
select ''hhmm_mode''::text;'
language 'sql';
create function time_mode() returns text
as 'update pg_type set typinput =''time_in'' where typname=''time'';
update pg_type set typoutput=''time_out'' where typname=''time'';
select ''time_mode''::text;'
language 'sql';
-- Use these to do the updates manually
--
-- update pg_type set typinput ='hhmm_in' where typname='time';
-- update pg_type set typoutput='hhmm_out' where typname='time';
--
-- update pg_type set typinput ='time_in' where typname='time';
-- update pg_type set typoutput='time_out' where typname='time';
-- end of file

View File

@ -1,15 +1,53 @@
# PGLIB is probably /usr/local/pgsql/lib
#
# $Header: /cvsroot/pgsql/contrib/earthdistance/Makefile,v 1.2 2000/06/15 18:54:46 momjian Exp $
#
PGINCLUDE=${PGLIB}/../include
CFLAGS+=-I${PGINCLUDE}
TOPDIR=../..
install-earthdistance: ${PGLIB}/earthdistance.so
include ../Makefile.global
${PGLIB}/earthdistance.so: earthdistance.so
sudo install -C -g bin -o bin earthdistance.so ${PGLIB}
NAME = earthdistance
earthdistance.so: earthdistance.o
$(LD) -o $@ -Bshareable $<
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
earthdistance.o: earthdistance.c
$(CC) -o $@ -c $(CFLAGS) $<
CFLAGS += -I. $(CFLAGS_SL)
OTHER_CLEAN = $(SQLS)
all: $(MODS) $(SQLS)
%.sql: %.sql.in
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
install: install_doc install_sql install_mod
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -7,8 +7,11 @@
#include <utils/palloc.h> /* for palloc */
/* Earth's radius is in statute miles. */
const EARTH_RADIUS = 3958.747716;
const TWO_PI = 2.0 * M_PI;
const int EARTH_RADIUS = 3958.747716;
const int TWO_PI = 2.0 * M_PI;
double *geo_distance(Point *pt1, Point *pt2);
/******************************************************
*

View File

@ -1,23 +0,0 @@
--------------- geo_distance
DROP FUNCTION geo_distance (point, point);
CREATE FUNCTION geo_distance (point, point) RETURNS float8
AS '/usr/local/pgsql/lib/earthdistance.so' LANGUAGE 'c';
SELECT geo_distance ('(1,2)'::point, '(3,4)'::point);
--------------- geo_distance as operator <@>
DROP OPERATOR <@> (point, point);
CREATE OPERATOR <@> (
leftarg = point,
rightarg = point,
procedure = geo_distance,
commutator = <@>
);
-- ( 87.6, 41.8) is in Chicago
-- (106.7, 35.1) is in Albuquerque
-- The cities are about 1100 miles apart
SELECT '(87.6,41.8)'::point <@> '(106.7,35.1)'::point;

View File

@ -1,23 +1,50 @@
#
# Makefile, requires src/interfaces/libpgeasy
# $Header: /cvsroot/pgsql/contrib/findoidjoins/Attic/Makefile,v 1.5 2000/06/15 18:54:49 momjian Exp $
#
#
INSTALLDIR = /usr/local/pgsql
TARGET = findoidjoins
PGEASY = ../../src/interfaces/libpgeasy
CFLAGS = -g -Wall -I. -I$(PGEASY) -I$(INSTALLDIR)/include
LIBPGEASY = $(PGEASY)/libpgeasy.a
LDFLAGS = -L$(INSTALLDIR)/lib -lpq
TOPDIR=../..
all : $(TARGET)
include ../Makefile.global
findoidjoins: findoidjoins.c $(LIBPGEASY)
gcc -o $@ $(CFLAGS) $^ $(LDFLAGS)
NAME = findoidjoins
PROGRAM = $(NAME)
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS =
BINS = $(PROGRAM) make_oidjoins_check
EXAMPLES=
MODS =
CFLAGS += -I$(LIBPGEASYDIR) -I$(LIBPQDIR)
OTHER_CLEAN =
all: $(PROGRAM)
$(PROGRAM): $(OBJS) $(LIBPGEASYDIR)/libpgeasy.a
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPGEASY)
install: install_doc nstall_bin
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f *.o $(TARGET) log core
install:
install -s -o bin -g bin $(TARGET) $(INSTALLDIR)/bin
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,97 +0,0 @@
The following data was generated by the 'timings.sh' script included
in this directory. It uses a very large table with music-related
articles as a source for the fti-table. The tables used are:
product : contains product information : 540.429 rows
artist_fti : fti table for product : 4.501.321 rows
clustered : same as above, only clustered : 4.501.321 rows
A sequential scan of the artist_fti table (and thus also the clustered table)
takes around 6:16 minutes....
Unfortunately I cannot probide anybody else with this test-date, since I
am not allowed to redistribute the data (it's a database being sold by
a couple of wholesale companies). Anyways, it's megabytes, so you probably
wouldn't want it in this distribution anyways.
I haven't tested this with less data.
The test-machine is a Pentium 133, 64 MB, Linux 2.0.32 with the database
on a 'QUANTUM BIGFOOT_CY4320A, 4134MB w/67kB Cache, CHS=8960/15/63'. This
is a very slow disk.
The postmaster was running with:
postmaster -i -b /usr/local/pgsql/bin/postgres -S 1024 -B 256 \
-o -o /usr/local/pgsql/debug-output -F -d 1
('trashing' means a 'select count(*) from artist_fti' to completely trash
any disk-caches and buffers....)
TESTING ON UNCLUSTERED FTI
trashing
1: ^lapton and ^ric : 0.050u 0.000s 5m37.484s 0.01%
2: ^lapton and ^ric : 0.050u 0.030s 5m32.447s 0.02%
3: ^lapton and ^ric : 0.030u 0.020s 5m28.822s 0.01%
trashing
1: ^lling and ^tones : 0.020u 0.030s 0m54.313s 0.09%
2: ^lling and ^tones : 0.040u 0.030s 0m5.057s 1.38%
3: ^lling and ^tones : 0.010u 0.050s 0m2.072s 2.89%
trashing
1: ^aughan and ^evie : 0.020u 0.030s 0m26.241s 0.19%
2: ^aughan and ^evie : 0.050u 0.010s 0m1.316s 4.55%
3: ^aughan and ^evie : 0.030u 0.020s 0m1.029s 4.85%
trashing
1: ^lling : 0.040u 0.010s 0m55.104s 0.09%
2: ^lling : 0.030u 0.030s 0m4.716s 1.27%
3: ^lling : 0.040u 0.010s 0m2.157s 2.31%
trashing
1: ^stev and ^ray and ^vaugh : 0.040u 0.000s 1m5.630s 0.06%
2: ^stev and ^ray and ^vaugh : 0.050u 0.020s 1m3.561s 0.11%
3: ^stev and ^ray and ^vaugh : 0.050u 0.010s 1m5.923s 0.09%
trashing
1: ^lling (no join) : 0.050u 0.020s 0m24.139s 0.28%
2: ^lling (no join) : 0.040u 0.040s 0m1.087s 7.35%
3: ^lling (no join) : 0.020u 0.030s 0m0.772s 6.48%
trashing
1: ^vaughan (no join) : 0.040u 0.030s 0m9.075s 0.77%
2: ^vaughan (no join) : 0.030u 0.010s 0m0.609s 6.56%
3: ^vaughan (no join) : 0.040u 0.010s 0m0.503s 9.94%
trashing
1: ^rol (no join) : 0.020u 0.030s 0m49.898s 0.10%
2: ^rol (no join) : 0.030u 0.020s 0m3.136s 1.59%
3: ^rol (no join) : 0.030u 0.020s 0m1.231s 4.06%
TESTING ON CLUSTERED FTI
trashing
1: ^lapton and ^ric : 0.020u 0.020s 2m17.120s 0.02%
2: ^lapton and ^ric : 0.030u 0.020s 2m11.767s 0.03%
3: ^lapton and ^ric : 0.040u 0.010s 2m8.128s 0.03%
trashing
1: ^lling and ^tones : 0.020u 0.030s 0m18.179s 0.27%
2: ^lling and ^tones : 0.030u 0.010s 0m1.897s 2.10%
3: ^lling and ^tones : 0.040u 0.010s 0m1.619s 3.08%
trashing
1: ^aughan and ^evie : 0.070u 0.010s 0m11.765s 0.67%
2: ^aughan and ^evie : 0.040u 0.010s 0m1.198s 4.17%
3: ^aughan and ^evie : 0.030u 0.020s 0m0.872s 5.73%
trashing
1: ^lling : 0.040u 0.000s 0m28.623s 0.13%
2: ^lling : 0.030u 0.010s 0m2.339s 1.70%
3: ^lling : 0.030u 0.010s 0m1.975s 2.02%
trashing
1: ^stev and ^ray and ^vaugh : 0.020u 0.010s 0m17.667s 0.16%
2: ^stev and ^ray and ^vaugh : 0.030u 0.010s 0m3.745s 1.06%
3: ^stev and ^ray and ^vaugh : 0.030u 0.020s 0m3.439s 1.45%
trashing
1: ^lling (no join) : 0.020u 0.040s 0m2.218s 2.70%
2: ^lling (no join) : 0.020u 0.020s 0m0.506s 7.90%
3: ^lling (no join) : 0.030u 0.030s 0m0.510s 11.76%
trashing
1: ^vaughan (no join) : 0.040u 0.050s 0m2.048s 4.39%
2: ^vaughan (no join) : 0.030u 0.020s 0m0.332s 15.04%
3: ^vaughan (no join) : 0.040u 0.010s 0m0.318s 15.72%
trashing
1: ^rol (no join) : 0.020u 0.030s 0m2.384s 2.09%
2: ^rol (no join) : 0.020u 0.030s 0m0.676s 7.39%
3: ^rol (no join) : 0.020u 0.030s 0m0.697s 7.17%

View File

@ -1,24 +1,58 @@
SRCDIR= ../../src
#
# $Header: /cvsroot/pgsql/contrib/fulltextindex/Attic/Makefile,v 1.3 2000/06/15 18:54:51 momjian Exp $
#
include $(SRCDIR)/Makefile.global
TOPDIR=../..
CONTRIBDIR=$(LIBDIR)/contrib
include ../Makefile.global
CFLAGS+= $(CFLAGS_SL)
NAME = fti
TARGETS= fti$(DLSUFFIX)
CLEANFILES+= $(TARGETS)
CURDIR=`pwd`
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS = fti.pl
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
all:: $(TARGETS)
CFLAGS += -I. $(CFLAGS_SL)
%.sql: %.source
rm -f $@; \
sed -e "s:_CURRENTDIR_:$(CURDIR):g" \
-e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@
OTHER_CLEAN = $(SQLS)
clean:
rm -f $(TARGETS) *.o
all: $(MODS) $(SQLS)
dist:
tar cf fti.tar README BENCH Makefile fti.c timings.sh
%.sql: %.sql.in
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
install: install_doc install_sql install_mod install_bin
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -94,4 +94,104 @@ Method 1 is very slow, 2 a lot faster, and for very large tables, 3 is
preferred.
BENCH:
~~~~~
Maarten Boekhold <maartenb@dutepp0.et.tudelft.nl>
The following data was generated by the 'timings.sh' script included
in this directory. It uses a very large table with music-related
articles as a source for the fti-table. The tables used are:
product : contains product information : 540.429 rows
artist_fti : fti table for product : 4.501.321 rows
clustered : same as above, only clustered : 4.501.321 rows
A sequential scan of the artist_fti table (and thus also the clustered table)
takes around 6:16 minutes....
Unfortunately I cannot probide anybody else with this test-date, since I
am not allowed to redistribute the data (it's a database being sold by
a couple of wholesale companies). Anyways, it's megabytes, so you probably
wouldn't want it in this distribution anyways.
I haven't tested this with less data.
The test-machine is a Pentium 133, 64 MB, Linux 2.0.32 with the database
on a 'QUANTUM BIGFOOT_CY4320A, 4134MB w/67kB Cache, CHS=8960/15/63'. This
is a very slow disk.
The postmaster was running with:
postmaster -i -b /usr/local/pgsql/bin/postgres -S 1024 -B 256 \
-o -o /usr/local/pgsql/debug-output -F -d 1
('trashing' means a 'select count(*) from artist_fti' to completely trash
any disk-caches and buffers....)
TESTING ON UNCLUSTERED FTI
trashing
1: ^lapton and ^ric : 0.050u 0.000s 5m37.484s 0.01%
2: ^lapton and ^ric : 0.050u 0.030s 5m32.447s 0.02%
3: ^lapton and ^ric : 0.030u 0.020s 5m28.822s 0.01%
trashing
1: ^lling and ^tones : 0.020u 0.030s 0m54.313s 0.09%
2: ^lling and ^tones : 0.040u 0.030s 0m5.057s 1.38%
3: ^lling and ^tones : 0.010u 0.050s 0m2.072s 2.89%
trashing
1: ^aughan and ^evie : 0.020u 0.030s 0m26.241s 0.19%
2: ^aughan and ^evie : 0.050u 0.010s 0m1.316s 4.55%
3: ^aughan and ^evie : 0.030u 0.020s 0m1.029s 4.85%
trashing
1: ^lling : 0.040u 0.010s 0m55.104s 0.09%
2: ^lling : 0.030u 0.030s 0m4.716s 1.27%
3: ^lling : 0.040u 0.010s 0m2.157s 2.31%
trashing
1: ^stev and ^ray and ^vaugh : 0.040u 0.000s 1m5.630s 0.06%
2: ^stev and ^ray and ^vaugh : 0.050u 0.020s 1m3.561s 0.11%
3: ^stev and ^ray and ^vaugh : 0.050u 0.010s 1m5.923s 0.09%
trashing
1: ^lling (no join) : 0.050u 0.020s 0m24.139s 0.28%
2: ^lling (no join) : 0.040u 0.040s 0m1.087s 7.35%
3: ^lling (no join) : 0.020u 0.030s 0m0.772s 6.48%
trashing
1: ^vaughan (no join) : 0.040u 0.030s 0m9.075s 0.77%
2: ^vaughan (no join) : 0.030u 0.010s 0m0.609s 6.56%
3: ^vaughan (no join) : 0.040u 0.010s 0m0.503s 9.94%
trashing
1: ^rol (no join) : 0.020u 0.030s 0m49.898s 0.10%
2: ^rol (no join) : 0.030u 0.020s 0m3.136s 1.59%
3: ^rol (no join) : 0.030u 0.020s 0m1.231s 4.06%
TESTING ON CLUSTERED FTI
trashing
1: ^lapton and ^ric : 0.020u 0.020s 2m17.120s 0.02%
2: ^lapton and ^ric : 0.030u 0.020s 2m11.767s 0.03%
3: ^lapton and ^ric : 0.040u 0.010s 2m8.128s 0.03%
trashing
1: ^lling and ^tones : 0.020u 0.030s 0m18.179s 0.27%
2: ^lling and ^tones : 0.030u 0.010s 0m1.897s 2.10%
3: ^lling and ^tones : 0.040u 0.010s 0m1.619s 3.08%
trashing
1: ^aughan and ^evie : 0.070u 0.010s 0m11.765s 0.67%
2: ^aughan and ^evie : 0.040u 0.010s 0m1.198s 4.17%
3: ^aughan and ^evie : 0.030u 0.020s 0m0.872s 5.73%
trashing
1: ^lling : 0.040u 0.000s 0m28.623s 0.13%
2: ^lling : 0.030u 0.010s 0m2.339s 1.70%
3: ^lling : 0.030u 0.010s 0m1.975s 2.02%
trashing
1: ^stev and ^ray and ^vaugh : 0.020u 0.010s 0m17.667s 0.16%
2: ^stev and ^ray and ^vaugh : 0.030u 0.010s 0m3.745s 1.06%
3: ^stev and ^ray and ^vaugh : 0.030u 0.020s 0m3.439s 1.45%
trashing
1: ^lling (no join) : 0.020u 0.040s 0m2.218s 2.70%
2: ^lling (no join) : 0.020u 0.020s 0m0.506s 7.90%
3: ^lling (no join) : 0.030u 0.030s 0m0.510s 11.76%
trashing
1: ^vaughan (no join) : 0.040u 0.050s 0m2.048s 4.39%
2: ^vaughan (no join) : 0.030u 0.020s 0m0.332s 15.04%
3: ^vaughan (no join) : 0.040u 0.010s 0m0.318s 15.72%
trashing
1: ^rol (no join) : 0.020u 0.030s 0m2.384s 2.09%
2: ^rol (no join) : 0.020u 0.030s 0m0.676s 7.39%
3: ^rol (no join) : 0.020u 0.030s 0m0.697s 7.17%

View File

@ -1,204 +0,0 @@
#!/usr/bin/perl
#
# This script substracts all substrings out of a specific column in a table
# and generates output that can be loaded into a new table with the
# psql '\copy' command. The new table should have the following structure:
#
# create table tab (
# string text,
# id oid
# );
#
# Note that you cannot use 'copy' (the SQL-command) directly, because
# there's no '\.' included at the end of the output.
#
# The output can be fed through the UNIX commands 'uniq' and 'sort'
# to generate the smallest and sorted output to populate the fti-table.
#
# Example:
#
# fti.pl -u -d mydb -t mytable -c mycolumn -f myfile
# sort -o myoutfile myfile
# uniq myoutfile sorted-file
#
# psql -u mydb
#
# \copy my_fti_table from myfile
#
# create index fti_idx on my_fti_table (string,id);
#
# create function fti() returns opaque as
# '/path/to/fti/file/fti.so'
# language 'newC';
#
# create trigger my_fti_trigger after update or insert or delete
# on mytable
# for each row execute procedure fti(my_fti_table, mycolumn);
#
# Make sure you have an index on mytable(oid) to be able to do somewhat
# efficient substring searches.
#use lib '/usr/local/pgsql/lib/perl5/';
use lib '/mnt/web/guide/postgres/lib/perl5/site_perl';
use Pg;
use Getopt::Std;
$PGRES_EMPTY_QUERY = 0 ;
$PGRES_COMMAND_OK = 1 ;
$PGRES_TUPLES_OK = 2 ;
$PGRES_COPY_OUT = 3 ;
$PGRES_COPY_IN = 4 ;
$PGRES_BAD_RESPONSE = 5 ;
$PGRES_NONFATAL_ERROR = 6 ;
$PGRES_FATAL_ERROR = 7 ;
$[ = 0; # make sure string offsets start at 0
sub break_up {
my $string = pop @_;
@strings = split(/\W+/, $string);
@subs = ();
foreach $s (@strings) {
$len = length($s);
next if ($len < 4);
$lpos = $len-1;
while ($lpos >= 3) {
$fpos = $lpos - 3;
while ($fpos >= 0) {
$sub = substr($s, $fpos, $lpos - $fpos + 1);
push(@subs, $sub);
$fpos = $fpos - 1;
}
$lpos = $lpos - 1;
}
}
return @subs;
}
sub connect_db {
my $dbname = shift @_;
my $user = shift @_;
my $passwd = shift @_;
if (!defined($dbname) || $dbname eq "") {
return 1;
}
$connect_string = "dbname=$dbname";
if ($user ne "") {
if ($passwd eq "") {
return 0;
}
$connect_string = "$connect_string user=$user password=$passwd ".
"authtype=password";
}
$PG_CONN = PQconnectdb($connect_string);
if (PQstatus($PG_CONN)) {
print STDERR "Couldn't make connection with database!\n";
print STDERR PQerrorMessage($PG_CONN), "\n";
return 0;
}
return 1;
}
sub quit_prog {
close(OUT);
unlink $opt_f;
if (defined($PG_CONN)) {
PQfinish($PG_CONN);
}
exit 1;
}
sub get_username {
print "Username: ";
chop($n = <STDIN>);
return $n;;
}
sub get_password {
print "Password: ";
system("stty -echo < /dev/tty");
chop($pwd = <STDIN>);
print "\n";
system("stty echo < /dev/tty");
return $pwd;
}
sub main {
getopts('d:t:c:f:u');
if (!$opt_d || !$opt_t || !$opt_c || !$opt_f) {
print STDERR "usage: $0 [-u] -d database -t table -c column ".
"-f output-file\n";
return 1;
}
if (defined($opt_u)) {
$uname = get_username();
$pwd = get_password();
} else {
$uname = "";
$pwd = "";
}
$SIG{'INT'} = 'quit_prog';
if (!connect_db($opt_d, $uname, $pwd)) {
print STDERR "Connecting to database failed!\n";
return 1;
}
if (!open(OUT, ">$opt_f")) {
print STDERR "Couldnt' open file '$opt_f' for output!\n";
return 1;
}
PQexec($PG_CONN, "begin");
$query = "declare C cursor for select $opt_c, oid from $opt_t";
$res = PQexec($PG_CONN, $query);
if (!$res || (PQresultStatus($res) != $PGRES_COMMAND_OK)) {
print STDERR "Error declaring cursor!\n";
print STDERR PQerrorMessage($PG_CONN), "\n";
PQfinish($PG_CONN);
return 1;
}
PQclear($res);
$query = "fetch in C";
while (($res = PQexec($PG_CONN, $query)) &&
(PQresultStatus($res) == $PGRES_TUPLES_OK) &&
(PQntuples($res) == 1)) {
$col = PQgetvalue($res, 0, 0);
$oid = PQgetvalue($res, 0, 1);
@subs = break_up($col);
foreach $i (@subs) {
print OUT "$i\t$oid\n";
}
}
if (!$res || (PQresultStatus($res) != PGRES_TUPLES_OK)) {
print STDERR "Error retrieving data from backend!\n";
print STDERR PQerrorMEssage($PG_CONN), "\n";
PQfinish($PG_CONN);
return 1;
}
PQclear($res);
PQfinish($PG_CONN);
return 0;
}
exit main();

View File

@ -1,18 +1,54 @@
#
# PostgreSQL types for ISBN and ISSN identifiers.
# $Header: /cvsroot/pgsql/contrib/isbn_issn/Attic/Makefile,v 1.3 2000/06/15 18:54:53 momjian Exp $
#
# $Id: Makefile,v 1.2 2000/05/29 05:44:26 tgl Exp $
SRCDIR= ../../src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
CFLAGS+= $(CFLAGS_SL)
NAME = isbn_issn
all: isbn$(DLSUFFIX) issn$(DLSUFFIX)
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
install: isbn$(DLSUFFIX) issn$(DLSUFFIX)
install -c isbn$(DLSUFFIX) issn$(DLSUFFIX) /usr/local/pgsql/modules
CFLAGS += -I. $(CFLAGS_SL)
OTHER_CLEAN = $(SQLS)
all: $(MODS) $(SQLS)
%.sql: %.sql.in
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
install: install_doc install_sql install_mod
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f isbn$(DLSUFFIX) issn$(DLSUFFIX) *.o
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,3 +1,7 @@
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()

View File

@ -1,199 +0,0 @@
/*
* PostgreSQL type definitions for ISBNs.
*
* $Id: isbn.c,v 1.3 2000/05/29 05:44:26 tgl Exp $
*/
#include <stdio.h>
#include <postgres.h>
#include <utils/palloc.h>
/*
* This is the internal storage format for ISBNs.
* NB: This is an intentional type pun with builtin type `char16'.
*/
typedef struct isbn
{
char num[13];
char pad[3];
} isbn;
/*
* Various forward declarations:
*/
isbn *isbn_in(char *str);
char *isbn_out(isbn * addr);
bool isbn_lt(isbn * a1, isbn * a2);
bool isbn_le(isbn * a1, isbn * a2);
bool isbn_eq(isbn * a1, isbn * a2);
bool isbn_ge(isbn * a1, isbn * a2);
bool isbn_gt(isbn * a1, isbn * a2);
bool isbn_ne(isbn * a1, isbn * a2);
int4 isbn_cmp(isbn * a1, isbn * a2);
int4 isbn_sum(char *str);
/*
* ISBN reader.
*/
isbn *
isbn_in(char *str)
{
isbn *result;
if (strlen(str) != 13)
{
elog(ERROR, "isbn_in: invalid ISBN \"%s\"", str);
return (NULL);
}
if (isbn_sum(str) != 0)
{
elog(ERROR, "isbn_in: purported ISBN \"%s\" failed checksum",
str);
return (NULL);
}
result = (isbn *) palloc(sizeof(isbn));
strncpy(result->num, str, 13);
memset(result->pad, ' ', 3);
return (result);
}
/*
* The ISBN checksum is defined as follows:
*
* Number the digits from 1 to 9 (call this N).
* Compute the sum, S, of N * D_N.
* The check digit, C, is the value which satisfies the equation
* S + 10*C === 0 (mod 11)
* The value 10 for C is written as `X'.
*
* For our purposes, we want the complete sum including the check
* digit; if this is zero, then the checksum passed. We also check
* the syntactic validity if the provided string, and return 12
* if any errors are found.
*/
int4
isbn_sum(char *str)
{
int4 sum = 0,
dashes = 0,
val;
int i;
for (i = 0; str[i] && i < 13; i++)
{
switch (str[i])
{
case '-':
if (++dashes > 3)
return 12;
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = str[i] - '0';
break;
case 'X':
case 'x':
val = 10;
break;
default:
return 12;
}
sum += val * (i + 1 - dashes);
}
return (sum % 11);
}
/*
* ISBN output function.
*/
char *
isbn_out(isbn * num)
{
char *result;
if (num == NULL)
return (NULL);
result = (char *) palloc(14);
result[0] = '\0';
strncat(result, num->num, 13);
return (result);
}
/*
* Boolean tests for magnitude.
*/
bool
isbn_lt(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) < 0);
};
bool
isbn_le(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) <= 0);
};
bool
isbn_eq(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) == 0);
};
bool
isbn_ge(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) >= 0);
};
bool
isbn_gt(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) > 0);
};
bool
isbn_ne(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13) != 0);
};
/*
* Comparison function for sorting:
*/
int4
isbn_cmp(isbn * a1, isbn * a2)
{
return (strncmp(a1->num, a2->num, 13));
}
/*
* eof
*/

View File

@ -1,116 +0,0 @@
--
-- PostgreSQL code for ISBNs.
--
-- $Id: isbn.sql,v 1.1 1998/08/17 03:35:05 scrappy Exp $
--
load '/usr/local/pgsql/modules/isbn.so';
--
-- Input and output functions and the type itself:
--
create function isbn_in(opaque)
returns opaque
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_out(opaque)
returns opaque
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create type isbn (
internallength = 16,
externallength = 13,
input = isbn_in,
output = isbn_out
);
--
-- The various boolean tests:
--
create function isbn_lt(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_le(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_eq(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_ge(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_gt(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
create function isbn_ne(isbn, isbn)
returns bool
as '/usr/local/pgsql/modules/isbn.so'
language 'c';
--
-- Now the operators. Note how some of the parameters to some
-- of the 'create operator' commands are commented out. This
-- is because they reference as yet undefined operators, and
-- will be implicitly defined when those are, further down.
--
create operator < (
leftarg = isbn,
rightarg = isbn,
-- negator = >=,
procedure = isbn_lt
);
create operator <= (
leftarg = isbn,
rightarg = isbn,
-- negator = >,
procedure = isbn_le
);
create operator = (
leftarg = isbn,
rightarg = isbn,
commutator = =,
-- negator = <>,
procedure = isbn_eq
);
create operator >= (
leftarg = isbn,
rightarg = isbn,
negator = <,
procedure = isbn_ge
);
create operator > (
leftarg = isbn,
rightarg = isbn,
negator = <=,
procedure = isbn_gt
);
create operator <> (
leftarg = isbn,
rightarg = isbn,
negator = =,
procedure = isbn_ne
);
--
-- eof
--

View File

@ -1,190 +0,0 @@
/*
* PostgreSQL type definitions for ISSNs.
*
* $Id: issn.c,v 1.3 2000/05/29 05:44:26 tgl Exp $
*/
#include <stdio.h>
#include <postgres.h>
#include <utils/palloc.h>
/*
* This is the internal storage format for ISSNs.
* NB: This is an intentional type pun with builtin type `char16'.
*/
typedef struct issn
{
char num[9];
char pad[7];
} issn;
/*
* Various forward declarations:
*/
issn *issn_in(char *str);
char *issn_out(issn * addr);
bool issn_lt(issn * a1, issn * a2);
bool issn_le(issn * a1, issn * a2);
bool issn_eq(issn * a1, issn * a2);
bool issn_ge(issn * a1, issn * a2);
bool issn_gt(issn * a1, issn * a2);
bool issn_ne(issn * a1, issn * a2);
int4 issn_cmp(issn * a1, issn * a2);
int4 issn_sum(char *str);
/*
* ISSN reader.
*/
issn *
issn_in(char *str)
{
issn *result;
if (strlen(str) != 9)
{
elog(ERROR, "issn_in: invalid ISSN \"%s\"", str);
return (NULL);
}
if (issn_sum(str) != 0)
{
elog(ERROR, "issn_in: purported ISSN \"%s\" failed checksum",
str);
return (NULL);
}
result = (issn *) palloc(sizeof(issn));
strncpy(result->num, str, 9);
memset(result->pad, ' ', 7);
return (result);
}
/*
* The ISSN checksum works just like the ISBN sum, only different
* (of course!).
* Here, the weights start at 8 and decrease.
*/
int4
issn_sum(char *str)
{
int4 sum = 0,
dashes = 0,
val;
int i;
for (i = 0; str[i] && i < 9; i++)
{
switch (str[i])
{
case '-':
if (++dashes > 1)
return 12;
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = str[i] - '0';
break;
case 'X':
case 'x':
val = 10;
break;
default:
return 12;
}
sum += val * (8 - (i - dashes));
}
return (sum % 11);
}
/*
* ISSN output function.
*/
char *
issn_out(issn * num)
{
char *result;
if (num == NULL)
return (NULL);
result = (char *) palloc(14);
result[0] = '\0';
strncat(result, num->num, 9);
return (result);
}
/*
* Boolean tests for magnitude.
*/
bool
issn_lt(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) < 0);
};
bool
issn_le(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) <= 0);
};
bool
issn_eq(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) == 0);
};
bool
issn_ge(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) >= 0);
};
bool
issn_gt(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) > 0);
};
bool
issn_ne(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9) != 0);
};
/*
* Comparison function for sorting:
*/
int4
issn_cmp(issn * a1, issn * a2)
{
return (strncmp(a1->num, a2->num, 9));
}
/*
* eof
*/

View File

@ -1,116 +0,0 @@
--
-- PostgreSQL code for ISSNs.
--
-- $Id: issn.sql,v 1.1 1998/08/17 03:35:05 scrappy Exp $
--
load '/usr/local/pgsql/modules/issn.so';
--
-- Input and output functions and the type itself:
--
create function issn_in(opaque)
returns opaque
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_out(opaque)
returns opaque
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create type issn (
internallength = 16,
externallength = 9,
input = issn_in,
output = issn_out
);
--
-- The various boolean tests:
--
create function issn_lt(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_le(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_eq(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_ge(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_gt(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
create function issn_ne(issn, issn)
returns bool
as '/usr/local/pgsql/modules/issn.so'
language 'c';
--
-- Now the operators. Note how some of the parameters to some
-- of the 'create operator' commands are commented out. This
-- is because they reference as yet undefined operators, and
-- will be implicitly defined when those are, further down.
--
create operator < (
leftarg = issn,
rightarg = issn,
-- negator = >=,
procedure = issn_lt
);
create operator <= (
leftarg = issn,
rightarg = issn,
-- negator = >,
procedure = issn_le
);
create operator = (
leftarg = issn,
rightarg = issn,
commutator = =,
-- negator = <>,
procedure = issn_eq
);
create operator >= (
leftarg = issn,
rightarg = issn,
negator = <,
procedure = issn_ge
);
create operator > (
leftarg = issn,
rightarg = issn,
negator = <=,
procedure = issn_gt
);
create operator <> (
leftarg = issn,
rightarg = issn,
negator = =,
procedure = issn_ne
);
--
-- eof
--

View File

@ -1,39 +1,60 @@
#
# PostgreSQL lo type
# $Header: /cvsroot/pgsql/contrib/lo/Makefile,v 1.3 2000/06/15 18:54:56 momjian Exp $
#
# Makefile pinched from the ip-mac contrib package
#
# $Id: Makefile,v 1.2 2000/05/29 05:44:27 tgl Exp $
SRCDIR= ../../src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
CONTRIBDIR=$(LIBDIR)/modules
NAME = lo
CFLAGS+= $(CFLAGS_SL)
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
ifdef REFINT_VERBOSE
CFLAGS+= -DREFINT_VERBOSE
endif
TARGETS= lo$(DLSUFFIX) lo.sql
OTHER_CLEAN = $(SQLS)
CLEANFILES+= $(TARGETS)
all: $(MODS) $(SQLS)
all:: $(TARGETS)
install:: all $(CONTRIBDIR)
for f in *$(DLSUFFIX); do $(INSTALL) -c $$f $(CONTRIBDIR)/$$f; done
$(CONTRIBDIR):
mkdir -p $(CONTRIBDIR)
%.sql: %.sql.in
rm -f $@; \
C=`pwd`; \
sed -e "s:_OBJWD_:$(CONTRIBDIR):g" \
-e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
install: install_doc install_sql install_mod
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif
clean:
rm -f $(TARGETS) *.o

View File

@ -1,8 +1,6 @@
PostgreSQL type extension for managing Large Objects
----------------------------------------------------
$Id: README,v 1.1 1998/06/16 07:07:11 momjian Exp $
Overview
One of the problems with the JDBC driver (and this affects the ODBC driver

View File

@ -1,21 +0,0 @@
--
-- This removes the type (and a test table)
-- It's used just for development
--
-- remove our test table
drop table a;
-- now drop any sql based functions associated with the lo type
drop function oid(lo);
-- now drop the type
drop type lo;
-- as the type is gone, remove the C based functions
drop function lo_in(opaque);
drop function lo_out(opaque);
drop function lo(oid);
drop function lo_manage();
-- the lo stuff is now removed from the system

View File

@ -1,11 +1,8 @@
--
-- PostgreSQL code for LargeObjects
--
-- $Id: lo.sql.in,v 1.2 2000/05/29 01:59:02 tgl Exp $
-- $Id: lo.sql.in,v 1.3 2000/06/15 18:54:56 momjian Exp $
--
load '_OBJWD_/lo_DLSUFFIX_';
--
-- Create the data type
--
@ -13,13 +10,13 @@ load '_OBJWD_/lo_DLSUFFIX_';
-- used by the lo type, it takes an oid and returns an lo object
create function lo_in(opaque)
returns opaque
as '_OBJWD_/lo_DLSUFFIX_'
as 'MODULE_PATHNAME'
language 'c';
-- used by the lo type, it returns the oid of the object
create function lo_out(opaque)
returns opaque
as '_OBJWD_/lo_DLSUFFIX_'
as 'MODULE_PATHNAME'
language 'c';
-- finally the type itself
@ -33,20 +30,20 @@ create type lo (
-- this returns the oid associated with a lo object
create function lo_oid(lo)
returns oid
as '_OBJWD_/lo_DLSUFFIX_'
as 'MODULE_PATHNAME'
language 'c';
-- this allows us to convert an oid to a managed lo object
-- ie: insert into test values (lo_import('/fullpath/file')::lo);
create function lo(oid)
returns lo
as '_OBJWD_/lo_DLSUFFIX_'
as 'MODULE_PATHNAME'
language 'c';
-- This is used in triggers
create function lo_manage()
returns opaque
as '_OBJWD_/lo_DLSUFFIX_'
as 'MODULE_PATHNAME'
language 'newC';
-- This allows us to map lo to oid

View File

@ -1,57 +0,0 @@
--
-- This runs some common tests against the type
--
-- It's used just for development
--
-- ignore any errors here - simply drop the table if it already exists
drop table a;
-- create the test table
create table a (fname name,image lo);
-- insert a null object
insert into a values ('null');
-- insert an empty large object
insert into a values ('empty','');
-- insert a large object based on a file
insert into a values ('/etc/group',lo_import('/etc/group')::lo);
-- now select the table
select * from a;
-- this select also returns an oid based on the lo column
select *,image::oid from a;
-- now test the trigger
create trigger t_a before update or delete on a for each row execute procedure lo_manage(image);
-- insert
insert into a values ('aa','');
select * from a where fname like 'aa%';
-- update
update a set image=lo_import('/etc/group')::lo where fname='aa';
select * from a where fname like 'aa%';
-- update the 'empty' row which should be null
update a set image=lo_import('/etc/hosts')::lo where fname='empty';
select * from a where fname like 'empty%';
update a set image=null where fname='empty';
select * from a where fname like 'empty%';
-- delete the entry
delete from a where fname='aa';
select * from a where fname like 'aa%';
-- This deletes the table contents. Note, if you comment this out, and
-- expect the drop table to remove the objects, think again. The trigger
-- doesn't get thrown by drop table.
delete from a;
-- finally drop the table
drop table a;
-- end of tests

View File

@ -1,3 +1,4 @@
Hello! :)
(Sorry for my english. But if i wrote in portuguese, you wouldn't

View File

@ -1,65 +1,52 @@
#-------------------------------------------------------------------------
#
# Makefile --
# $Header: /cvsroot/pgsql/contrib/miscutil/Attic/Makefile,v 1.8 2000/06/15 18:55:01 momjian Exp $
#
# Makefile for the misc_util module.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
NAME = misc_utils
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = misc_utils
OTHER_CLEAN = $(SQLS)
SQLDEFS = $(MODNAME).sql
MODULE = $(MODNAME)$(DLSUFFIX)
MODDIR = $(LIBDIR)/modules
SQLDIR = $(LIBDIR)/sql
all: module sql
module: $(MODULE)
sql: $(SQLDEFS)
install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
cp -p $(MODULE) $(MODDIR)/
strip $(MODDIR)/$(MODULE)
cp -p $(SQLDEFS) $(SQLDIR)/
install-doc:
if [ -d "$(DOCDIR)" ]; then \
cp -p *.doc $(DOCDIR); \
else \
cp -p *.doc $(SQLDIR); \
fi
$(MODDIR):
mkdir -p $@
$(SQLDIR):
mkdir -p $@
all: $(MODS) $(SQLS)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
install: install_doc install_sql install_mod
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f *~ $(MODULE) $(MODNAME).sql
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend

43
contrib/miscutil/README Normal file
View File

@ -0,0 +1,43 @@
Miscellaneous utility functions for PostgreSQL.
Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
This software is distributed under the GNU General Public License
either version 2, or (at your option) any later version.
query_limit(n)
sets a limit on the maximum numbers of query returned from
a backend. It can be used to limit the result size retrieved
by the application for poor input data or to avoid accidental
table product while playying with sql.
backend_pid()
return the pid of our corresponding backend.
unlisten(relname)
unlisten from a relation or from all relations if the argument
is null, empty or '*'.
It is now obsoleted by the new unlisten command but still useful
if you want unlisten a name computed by the query.
Note that a listen/notify relname can be any ascii string, not
just valid relation names.
min(x,y)
max(x,y)
return the min or max bteween two integers.
assert_enable(bool)
enable/disable assert checkings in the backend, if it has been
compiled with USE_ASSERT_CHECKING.
assert_test(bool)
test the assert enable/disable code, if the backend has been
compiled with ASSERT_CHECKING_TEST.
--
Massimo Dal Zotto <dz@cs.unitn.it>

20
contrib/noupdate/README Normal file
View File

@ -0,0 +1,20 @@
noupdate
~~~~~~~~
- trigger to prevent updates on single columns.
Example:
~~~~~~~
CREATE TABLE TEST ( COL1 INT, COL2 INT, COL3 INT );
CREATE TRIGGER BT BEFORE UPDATE ON TEST FOR EACH ROW
EXECUTE PROCEDURE
noup ('COL1');
-- Now Try
INSERT INTO TEST VALUES (10,20,30);
UPDATE TEST SET COL1 = 5;

View File

@ -1,9 +0,0 @@
CREATE TABLE TEST ( COL1 INT, COL2 INT, COL3 INT );
CREATE TRIGGER BT BEFORE UPDATE ON TEST FOR EACH ROW
EXECUTE PROCEDURE
noup ('COL1');
-- Now Try
INSERT INTO TEST VALUES (10,20,30);
UPDATE TEST SET COL1 = 5;

View File

@ -1,7 +0,0 @@
DROP FUNCTION noup ();
CREATE FUNCTION noup ()
RETURNS opaque
AS '_OBJWD_/noup_DLSUFFIX_'
LANGUAGE 'newC'
;

View File

@ -1,145 +0,0 @@
-- ODBC.sql
--
--
-- Character string manipulation
--
--
-- Extensions for ODBC compliance in v7.0.
-- In the current driver, ODBC functions must map directly into a
-- Postgres function. So in some cases we must create a compatible
-- function.
--
-- truncate on the left
CREATE FUNCTION ltrunc(text, integer)
RETURNS text
AS 'SELECT substring($1 FROM 1 FOR $2)'
LANGUAGE 'SQL';
-- truncate on the right
CREATE FUNCTION rtrunc(text, integer)
RETURNS text
AS 'SELECT substring($1 FROM (char_length($1)-($2)+1) FOR $2)'
LANGUAGE 'SQL';
CREATE FUNCTION space(integer)
RETURNS text
AS 'SELECT lpad('''', $1, '' '')'
LANGUAGE 'SQL';
--
-- Mathematical functions
--
CREATE FUNCTION truncate(numeric,integer)
RETURNS numeric
AS 'SELECT trunc($1, $2)'
LANGUAGE 'SQL';
--
-- Date/time functions for v7.0
--
CREATE FUNCTION curdate()
RETURNS date
AS 'SELECT CAST(''now'' AS date)'
LANGUAGE 'SQL';
CREATE FUNCTION curtime()
RETURNS time
AS 'SELECT CAST(''now'' AS time)'
LANGUAGE 'SQL';
CREATE FUNCTION dayname(timestamp)
RETURNS text
AS 'SELECT to_char($1,''Day'')'
LANGUAGE 'SQL';
CREATE FUNCTION dayofmonth(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''day'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION dayofweek(timestamp)
RETURNS integer
AS 'SELECT ( CAST(date_part(''dow'', $1) AS integer) + 1)'
LANGUAGE 'SQL';
CREATE FUNCTION dayofyear(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''doy'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION hour(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''hour'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION minute(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''minute'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION odbc_month(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''month'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION monthname(timestamp)
RETURNS text
AS 'SELECT to_char($1, ''Month'')'
LANGUAGE 'SQL';
CREATE FUNCTION quarter(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''quarter'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION second(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''second'', $1) AS integer)'
LANGUAGE 'SQL';
/*
-- The first argument is an integer constant denoting the units
-- of the second argument. Until we know the actual values, we
-- cannot implement these. - thomas 2000-04-11
CREATE FUNCTION timestampadd(integer,integer,timestamp)
RETURNS timestamp
AS 'SELECT CAST(($3 + ($2 * $1)) AS timestamp)'
LANGUAGE 'SQL';
CREATE FUNCTION timestampdiff(integer,integer,timestamp)
RETURNS timestamp
AS 'SELECT CAST(($3 + ($2 * $1)) AS timestamp)'
LANGUAGE 'SQL';
*/
CREATE FUNCTION week(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''week'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE FUNCTION year(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''year'', $1) AS integer)'
LANGUAGE 'SQL';
--
-- System functions.
--
/*
CREATE FUNCTION database()
RETURNS text
AS 'SELECT ...'
LANGUAGE 'SQL';
*/
CREATE FUNCTION odbc_user()
RETURNS text
AS 'SELECT CAST(USER AS text)'
LANGUAGE 'SQL';

View File

@ -1,86 +0,0 @@
#-------------------------------------------------------------------------
#
# Makefile
# Makefile for libpq library
#
# Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/contrib/os2client/Attic/Makefile,v 1.2 2000/03/19 21:59:30 tgl Exp $
#
#-------------------------------------------------------------------------
SO_MAJOR_VERSION=1
SO_MINOR_VERSION=1
SRCDIR= ../../src
INTERFACES= $(SRCDIR)/interfaces/libpq
PORTNAME=OS2
CC=gcc
CFLAGS=-I. -I$(SRCDIR)/include
CFLAGS+=-DFRONTEND -DTCPIPV4 -DHAVE_CRYPT_H
CP= copy
AR=ar
AROPT=rc
RANLIB= ar s
LDFLAGS= -L.
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-lobj.o fe-print.o \
dllist.o pqsignal.o pqcomprim.o
EXEOBJS= psql.o stringutils.o
all: libpq.a psql
fe-auth.o: $(INTERFACES)/fe-auth.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-auth.c
fe-connect.o: $(INTERFACES)/fe-connect.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-connect.c
fe-exec.o: $(INTERFACES)/fe-exec.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-exec.c
fe-lobj.o: $(INTERFACES)/fe-lobj.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-lobj.c
fe-misc.o: $(INTERFACES)/fe-misc.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-misc.c
fe-print.o: $(INTERFACES)/fe-print.c
$(CC) $(CFLAGS) -c $(INTERFACES)/fe-print.c
pqsignal.o: $(INTERFACES)/pqsignal.c
$(CC) $(CFLAGS) -c $(INTERFACES)/pqsignal.c
dllist.o: $(SRCDIR)/backend/lib/dllist.c
$(CC) $(CFLAGS) -c $(SRCDIR)/backend/lib/dllist.c
pqcomprim.o: $(SRCDIR)/backend/libpq/pqcomprim.c
$(CC) $(CFLAGS) -c $(SRCDIR)/backend/libpq/pqcomprim.c
libpq.a: $(OBJS)
$(AR) $(AROPT) libpq.a $(OBJS)
$(RANLIB) libpq.a
psql: $(EXEOBJS)
$(CC) -o psql.exe $(EXEOBJS) $(LDFLAGS) -llibpq -lsocket -lufc
psql.o: $(SRCDIR)/bin/psql/psql.c
$(CC) $(CFLAGS) -I$(INTERFACES) -c $(SRCDIR)/bin/psql/psql.c
stringutils.o: $(SRCDIR)/bin/psql/stringutils.c
$(CC) $(CFLAGS) -I$(INTERFACES) -c $(SRCDIR)/bin/psql/stringutils.c
clean:
rm -f libpq.a $(OBJS) $(EXEOBJS) psql.exe dllist.c pqcomprim.c

View File

@ -1,50 +0,0 @@
19981029 libpq.a and psql.exe Version 6.4 for OS/2
---------------------------------------------------
Requirements:
emx 0.9c or newer under OS/2
GNU crypt library for emx+gcc version 2.0.6 (available from
ftp://ftp.leo.org/pub/comp/os/os2/leo/crypt/gnuufc.zip)
Also a patch is needed for sys/socket.h around line 291. The lines
with the pluses need to be added, the other lines are already there
and are only for reference:
#define MT_IFADDR 13
+#ifndef MAXSOCKETS
+#define MAXSOCKETS 2048
+#endif
struct mbstat {
u_short m_mbufs;
u_short m_clusters;
Possible problems:
You will also need to #define TCPIPV4
Make sure both socket.a and ufc.a are linked in to the executable
AFTER libpq.a.
The following include files will be needed in order to use the library.
You only need to include one (libpq-fe.h) but these need to be present:
postgres_ext.h
libpq/pqcomm.h
lib/dllist.h"
c.h
Good luck and enjoy!!
Vince Vielhaber <vev@michvhf.com>

View File

@ -1,26 +0,0 @@
#ifndef TCPIPV4
#define TCPIPV4
#endif /* */
#ifndef MAXSOCKETS
#define MAXSOCKETS 2048
#endif /* */
/*
* DEF_PGPORT is the TCP port number on which the Postmaster listens by
* default. This can be overriden by command options, environment variables,
* and the postconfig hook. (set by build script)
*/
#define DEF_PGPORT "5432"
#define HAVE_TERMIOS_H
#define HAVE_ENDIAN_H
#define SOCKET_SIZE_TYPE size_t
#define strcasecmp(s1, s2) stricmp(s1, s2)

Binary file not shown.

Binary file not shown.

View File

@ -1,26 +1,50 @@
#
# $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/Makefile,v 1.2 2000/06/15 18:55:10 momjian Exp $
#
PROGRAM = pg_dumplo
OBJECTS = pg_dumplo.o
TOPDIR=../..
CFLAGS = -Wall -fpic -g
CC = gcc
RM = rm -f
INCLUDE = -I/usr/include/postgresql
LIBS =-lpq
include ../Makefile.global
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE)
LINK = $(CC) $(CFLAGS) -o $@ $(LIBS)
NAME = pg_dumplo
PROGRAM = $(NAME)
OBJS = main.o lo_export.o lo_import.o utils.o
DOCS = $(NAME).doc
SQLS =
BINS = $(PROGRAM)
EXAMPLES=
MODS =
all: $(PROGRAM)
CFLAGS += -I$(LIBPQDIR)
$(PROGRAM): $(OBJECTS)
$(LINK) $(OBJECTS)
OTHER_CLEAN =
.c.o: $<
$(COMPILE) -c $<
all: $(PROGRAM)
$(PROGRAM): $(OBJS) $(LIBPQDIR)/libpq.a
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ)
install: install_doc install_bin
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) -f *~ $(OBJECTS) $(PROGRAM)
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,18 +1,117 @@
pg_dumplo - PostgreSQL large object dumper
How to use pg_dumplo?
=====================
Hmm... documentation is not available. For more information
see the help ( pg_dumplo -h ) and examples in this help.
(c) 2000, Pavel Janík ml. <Pavel.Janik@linux.cz>
Compilation:
- you need the PostgreSQL's devel. libs
- and type: 'make'
Karel Zak <zakkr@zf.jcu.cz>
Q: How do you use pg_dumplo?
============================
A: This is a small demo of backing up the database table with Large Objects:
We will create a demo database and a small and useless table `lo' inside
it:
SnowWhite:$ createdb test
CREATE DATABASE
Ok, our database with the name 'test' is created. Now we should create demo
table which will contain only one column with the name 'id' which will hold
the oid number of Large Object:
SnowWhite:$ psql test
Welcome to psql, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
test=# CREATE TABLE lo (id oid);
CREATE
test=# \lo_import /etc/aliases
lo_import 19338
test=# INSERT INTO lo VALUES (19338);
INSERT 19352 1
test=# select * from lo;
id
-------
19338
(1 row)
test=# \q
In the above example you can see that we have also imported one "Large
Object" - the file /etc/aliases. It has an oid of 19338 so we have inserted
this oid number to the database table lo to the column id. The final SELECT
shows that we have one record in the table.
Now we can demonstrate the work of pg_dumplo. We will create dump directory
which will contain the whole dump of large objects (/tmp/dump):
mkdir -p /tmp/dump
Now we can dump all large objects from the database `test' which has an oid
stored in the column `id' in the table `lo':
SnowWhite:$ pg_dumplo -s /tmp/dump -d test -l lo.id
pg_dumplo: dump lo.id (1 large obj)
Voila, we have the dump of all Large Objects in our directory:
SnowWhite:$ tree /tmp/dump/
/tmp/dump/
`-- test
|-- lo
| `-- id
| `-- 19338
`-- lo_dump.index
3 directories, 2 files
SnowWhite:$
Isn't it nice :-) Yes, it is, but we are on the half of our way. We should
also be able to recreate the contents of the table lo and the Large Object
database when something went wrong. It is very easy, we will demonstrate
this via dropping the database and recreating it from scratch with
pg_dumplo:
SnowwWite:$ dropdb test
DROP DATABASE
SnowWhite:$ createdb test
CREATE DATABASE
Ok, our database with the name `test' is created again. We should also
create the table `lo' again:
SnowWhite:$ psql test
Welcome to psql, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
test=# CREATE TABLE lo (id oid);
CREATE
test=# \q
SnowWhite:$
Now the database with the table `lo' is created again, but we do not have
any information stored in it. But have the dump of complete Large Object
database, so we can recreate the contents of the whole database from the
directory /tmp/dump:
SnowWhite:$ pg_dumplo -s /tmp/dump -d test -i
19338 lo id test/lo/id/19338
SnowWhite:$
And this is everything.
Summary: In this small example we have shown that pg_dumplo can be used to
completely dump the database's Large Objects very easily.

View File

@ -1 +0,0 @@
0.0.4

View File

@ -1,379 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <libpq-fe.h>
#include <libpq/libpq-fs.h>
#define _GNU_SOURCE
#include <getopt.h>
extern int errno;
#define QUERY_BUFSIZ (8*1024)
#define DIR_UMASK 0755
#define FILE_UMASK 0666
#define TRUE 1
#define FALSE 0
#define RE_OK 0
#define RE_ERROR 1
typedef struct {
char *table,
*attr;
long lo_oid;
} lo_attr;
void usage()
{
printf("\nPostgreSQL large objects dump");
printf("\npg_lo_dump <option>\n\n");
printf("-h --help this help\n");
printf("-u --user='username' username for connection to server\n");
printf("-p --password='password' password for connection to server\n");
printf("-d --db='database' database name\n");
printf("-t --host='hostname' server hostname\n");
printf("-l <table.attr ...> dump attribute (columns) with LO to dump tree\n");
printf("-i --import import large obj dump tree to DB\n");
printf("-s --space=<dir> directory with dupm tree (for dump/import)\n");
printf("\nExample (dump): pg_lo_dump -d my_db -s /my_dump/dir/ -l t1.a t1.b t2.a\n");
printf("Example (import): pg_lo_dump -i -d my_db -s /my_dump/dir/\n");
printf("\nNote: * option '-l' must be last option!\n");
printf(" * option '-i' (--import) make new large obj in DB, not rewrite old,\n");
printf(" import UPDATE oid numbers in table.attr only.\n");
printf("\n\n");
}
typedef enum {
ARG_USER,
ARG_PWD,
ARG_DB,
ARG_HELP,
ARG_HOST
} _ARG_;
/*-----
* Init and allocate lo_attr structs
*
* ! data is **argv
*-----
*/
lo_attr *init_loa(char **data, int max, int start)
{
lo_attr *l,
*ll;
char **d,
*loc,
buff[128];
if ((l = (lo_attr *) malloc(max * sizeof(lo_attr))) == NULL) {
fprintf(stderr, "%s: can't allocate memory\n", data[0]);
exit(RE_ERROR);
}
for(d=data+start, ll=l; *d != NULL; d++, ll++) {
strncpy(buff, *d, 128);
if ((loc = strchr(buff, '.')) == NULL) {
fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", data[0], buff);
exit(RE_ERROR);
}
*loc = '\0';
ll->table = strdup(buff);
ll->attr = strdup(++loc);
}
ll++;
ll->table = ll->attr = (char *) NULL;
return l;
}
/*-----
* Check PG result
*-----
*/
int check_res(PGresult *res, PGconn *conn)
{
if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "%s\n",PQerrorMessage(conn));
PQclear(res);
return FALSE;
}
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
fprintf(stderr, "Tuples is not OK.\n");
PQclear(res);
return FALSE;
}
return TRUE;
}
/*-----
* LO dump
*-----
*/
void dump_lo(PGconn *conn, char *space, lo_attr *loa, char *db, char *prog)
{
PGresult *res;
lo_attr *ploa;
FILE *majorfile;
char *dir,
path[BUFSIZ],
Qbuff[QUERY_BUFSIZ];
dir = space ? space : getenv("PWD");
sprintf(path, "%s/%s", dir, db);
if (mkdir(path, DIR_UMASK) == -1) {
if (errno != EEXIST) {
perror(path);
exit(RE_ERROR);
}
}
sprintf(path, "%s/lo_dump.index", path);
if ((majorfile = fopen(path, "w")) == NULL) {
perror(path);
exit(RE_ERROR);
} else {
time_t t;
time(&t);
fprintf(majorfile, "#\n# This is the PostgreSQL large object dump index\n#\n");
fprintf(majorfile, "#\tDate: %s", ctime(&t));
fprintf(majorfile, "#\tHost: %s\n", PQhost(conn) ? PQhost(conn) : "localhost");
fprintf(majorfile, "#\tDatabase: %s\n", db);
fprintf(majorfile, "#\tUser: %s\n", PQuser(conn));
fprintf(majorfile, "#\n# oid\ttable\tattribut\tinfile\n");
}
for(ploa=loa; ploa->table != NULL; ploa++) {
/* query */
sprintf(Qbuff, "SELECT %s FROM %s WHERE %s!=0",
ploa->attr, ploa->table, ploa->attr);
res = PQexec(conn, Qbuff);
if (check_res(res, conn)) {
int tuples = PQntuples(res),
t;
char *val;
/* Make DIR/FILE */
if (tuples) {
sprintf(path, "%s/%s/%s", dir, db, ploa->table);
if (mkdir(path, DIR_UMASK) == -1) {
if (errno != EEXIST) {
perror(path);
exit(RE_ERROR);
}
}
sprintf(path, "%s/%s", path, ploa->attr);
if (mkdir(path, DIR_UMASK) == -1) {
if (errno != EEXIST) {
perror(path);
exit(RE_ERROR);
}
}
fprintf(stderr, "%s: dump %s.%s (%d lagre obj)\n", prog,
ploa->table, ploa->attr, tuples);
}
for(t=0; t<tuples; t++) {
val = PQgetvalue(res, t, 0);
if (!val)
continue;
sprintf(path, "%s/%s/%s/%s/%s", dir, db, ploa->table, ploa->attr, val);
if (lo_export(conn, (Oid) atol(val), path) < 0)
fprintf(stderr, "%s\n", PQerrorMessage(conn));
else
fprintf(majorfile, "%s\t%s\t%s\t%s/%s/%s/%s\n", val,
ploa->table, ploa->attr, db, ploa->table, ploa->attr, val);
}
}
}
fclose(majorfile);
}
/*-----
* LO import
*-----
*/
void import_lo(PGconn *conn, char *space, char *db, char *prog)
{
PGresult *res;
lo_attr loa;
FILE *majorfile;
long new_oid;
char *dir,
tab[128], attr[128],
path[BUFSIZ], lo_path[BUFSIZ],
Qbuff[QUERY_BUFSIZ];
dir = space ? space : getenv("PWD");
sprintf(path, "%s/%s", dir, db);
sprintf(path, "%s/lo_dump.index", path);
if ((majorfile = fopen(path, "r")) == NULL) {
perror(path);
exit(RE_ERROR);
}
while(fgets(Qbuff, QUERY_BUFSIZ, majorfile)) {
if (*Qbuff == '#')
continue;
fprintf(stdout, Qbuff);
sscanf(Qbuff, "%ld\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path);
loa.table = tab;
loa.attr = attr;
sprintf(lo_path, "%s/%s", dir, path);
/* import large obj */
if ((new_oid = lo_import(conn, lo_path)) <= 0) {
fprintf(stderr, "%s\n",PQerrorMessage(conn));
PQexec(conn, "ROLLBACK");
fprintf(stderr, "\nROLLBACK\n");
exit(RE_ERROR);
}
/* query */
sprintf(Qbuff, "UPDATE %s SET %s=%ld WHERE %s=%ld",
loa.table, loa.attr, new_oid, loa.attr, loa.lo_oid);
/*fprintf(stderr, Qbuff);*/
res = PQexec(conn, Qbuff);
if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "%s\n",PQerrorMessage(conn));
PQclear(res);
PQexec(conn, "ROLLBACK");
fprintf(stderr, "\nROLLBACK\n");
exit(RE_ERROR);
}
}
fclose(majorfile);
}
/*-----
* The mother of all C functions
*-----
*/
int main(int argc, char **argv)
{
PGconn *conn;
lo_attr *loa =NULL;
char *user =NULL,
*pwd =NULL,
*db =NULL,
*host =NULL,
*space =NULL;
int import =FALSE;
/* Parse argv */
if (argc) {
int arg, l_index=0;
extern int optind;
typedef enum {
ARG_USER,
ARG_PWD,
ARG_DB,
ARG_HELP,
ARG_IMPORT,
ARG_SPACE,
ARG_HOST
} _ARG_;
struct option l_opt[] = {
{ "help", 0, 0, ARG_HELP },
{ "user", 1, 0, ARG_USER },
{ "pwd", 1, 0, ARG_PWD },
{ "db", 1, 0, ARG_DB },
{ "host", 1, 0, ARG_HOST },
{ "space", 1, 0, ARG_SPACE },
{ "import", 0, 0, ARG_IMPORT },
{ NULL, 0, 0, 0 }
};
while((arg = getopt_long(argc, argv, "hu:p:d:l:t:is:", l_opt, &l_index)) != -1) {
switch(arg) {
case ARG_HELP:
case 'h':
usage();
exit(RE_OK);
case ARG_USER:
case 'u':
user = strdup(optarg);
break;
case ARG_HOST:
case 't':
host = strdup(optarg);
break;
case ARG_PWD:
case 'p':
pwd = strdup(optarg);
break;
case ARG_DB:
case 'd':
db = strdup(optarg);
break;
case ARG_SPACE:
case 's':
space = strdup(optarg);
break;
case ARG_IMPORT:
case 'i':
import = TRUE;
break;
case 'l':
loa = init_loa(argv, argc-1, optind-1);
break;
}
}
}
if (!space && !getenv("PWD")) {
fprintf(stderr, "%s: can't set directory (not set '-s' or $PWD).\n", argv[0]);
exit(RE_ERROR);
}
/* Make PG connection */
conn = PQsetdbLogin(host, NULL, NULL, NULL, db, user, pwd);
/* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "%s\n",PQerrorMessage(conn));
exit(RE_ERROR);
}
PQexec(conn, "BEGIN");
if (import) {
/* import obj */
import_lo(conn, space, db, argv[0]);
} else if (loa) {
/* Dump obj */
dump_lo(conn, space, loa, db, argv[0]);
} else {
fprintf(stderr, "%s: ERROR: bad arg!\n", argv[0]);
usage();
}
PQexec(conn, "COMMIT");
/* bye PG */
PQfinish(conn);
exit(RE_OK);
}

View File

@ -1,23 +1,48 @@
# $Header: /cvsroot/pgsql/contrib/pgbench/Makefile,v 1.1 2000/01/15 12:38:09 ishii Exp $
#
# $Header: /cvsroot/pgsql/contrib/pgbench/Makefile,v 1.2 2000/06/15 18:55:12 momjian Exp $
#
SRCDIR= ../../src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
CFLAGS:= -I$(LIBPQDIR) $(CFLAGS)
NAME = pgbench
TARGET = pgbench
OBJS = pgbench.o
PROGRAM = $(NAME)
OBJS = $(NAME).o
DOCS = $(NAME).doc $(NAME)_jis.doc
SQLS =
BINS = $(PROGRAM)
EXAMPLES=
MODS =
all:: $(TARGET)
CFLAGS += -I$(LIBPQDIR)
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(OBJS) -L$(LIBPQDIR) -lpq $(LDFLAGS)
OTHER_CLEAN =
install: $(TARGET)
$(INSTALL) $(INSTL_EXE_OPTS) $(TARGET)$(X) $(BINDIR)/$(TARGET)$(X)
all: $(PROGRAM)
$(PROGRAM): $(OBJS) $(LIBPQDIR)/libpq.a
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ)
install: install_doc install_bin
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) $(TARGET)$(X) $(OBJS)
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
distclean: clean
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,166 +0,0 @@
pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp)
$B"#(Bpgbench $B$H$O!)(B
pgbench $B$O(B TPC-B$B$K;w$?%Y%s%A%^!<%/%F%9%H$r9T$J$&%W%m%0%i%`$G$9!#:#$N$H(B
$B$3$m(B PostgreSQL $B@lMQ$G$9!#(B
pgbench $B$O(B select/update/insert $B$r4^$`%H%i%s%6%/%7%g%s$r<B9T$7!"A4BN$N(B
$B<B9T;~4V$H<B:]$K40N;$7$?%H%i%s%6%/%7%g%s$N?t$+$i(B 1 $BIC4V$K<B9T$G$-$?%H(B
$B%i%s%6%/%7%g%s?t(B (tps) $B$rI=<($7$^$9!#=hM}$NBP>]$H$J$k%F!<%V%k$O%G%U%)(B
$B%k%H$G$O(B 10$BK|%?%W%k$N%G!<%?$r4^$_$^$9!#(B
$B<B:]$NI=<($O0J2<$N$h$&$J46$8$G$9!#(B
number of clients: 4
number of transactions per client: 100
number of processed transactions: 400/400
tps = 19.875015(including connections establishing)
tps = 20.098827(excluding connections establishing)
pgbench $B$O(B JDBCBench $B$H$$$&!"$b$H$b$H$O(B MySQL $BMQ$K=q$+$l$?(B JDBC $BMQ$N%Y(B
$B%s%A%^!<%/%W%m%0%i%`$r;29M$K:n@.$5$l$^$7$?!#(B
$B"#(Bpgbench $B$NFCD'(B
o C $B8@8l$H(B libpq $B$@$1$G=q$+$l$F$$$k$N$G0\?"@-$,9b$/!"4JC1$K%$%s%9%H!<(B
$B%k$G$-$^$9!#(B
o pgbench $B$O(B libpq $B$NHsF14|=hM}5!G=$r;H$C$F%^%k%A%f!<%64D6-$r%7%_%e%l!<(B
$B%H$7$^$9!#MF0W$KF1;~@\B34D6-$r%F%9%H$G$-$^$9!#(B
$B"#(Bpgbench $B$N%$%s%9%H!<%k(B
Makefile$B$N0lHV>e$K$"$k(B
POSTGRESHOME = /usr/local/pgsql
$B$rI,MW$K1~$8$F=$@5$7!"(Bconfigure;make $B$9$k$@$1$G$9!#(B
$B"#(Bpgbench $B$N;H$$J}(B
$B4pK\E*$J;H$$J}$O!"(B
$ pgbench [$B%G!<%?%Y!<%9L>(B]
$B$G$9!#%G!<%?%Y!<%9L>$r>JN,$9$k$H!"%f!<%6L>$HF1$8%G!<%?%Y!<%9$r;XDj$7$?(B
$B$b$N$H$_$J$7$^$9!#%G!<%?%Y!<%9$O8e=R$N(B -i $B%*%W%7%g%s$r;H$C$F$"$i$+$8$a(B
$B=i4|2=$7$F$*$/I,MW$,$"$j$^$9!#(B
pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!#(B
-h $B%[%9%HL>(B PostgreSQL$B$N%G!<%?%Y!<%9%G!<%b%s(B postmaster $B$NF0(B
$B$$$F$$$k%[%9%HL>$r;XDj$7$^$9!#>JN,$9$k$H<+%[%9%H$K(B Unix domain
socket $B$G@\B3$7$^$9!#(B
-p $B%]!<%HHV9f(B postmaster $B$N;HMQ$9$k%]!<%HHV9f$r;XDj$7$^$9!#>JN,$9$k$H(B 5432
$B$,;XDj$5$l$?$b$N$H$_$J$7$^$9!#(B
-c $B%/%i%$%"%s%H?t(B $BF1;~<B9T%/%i%$%"%s%H?t$r;XDj$7$^$9!#>JN,;~$O(B
1 $B$H$J$j$^$9!#(Bpgbench $B$OF1;~<B9T%/%i%$%"%s%HKh$K(B
$B%U%!%$%k%G%#%9%/%j%W%?$r;HMQ$9$k$N$G!";HMQ2DG=(B
$B%U%!%$%k%G%#%9%/%j%W%??t$r1[$($k%/%i%$%"%s%H?t$O(B
$B;XDj$G$-$^$;$s!#;HMQ2DG=%U%!%$%k%G%#%9%/%j%W%??t(B
$B$O(B limit $B$d(B ulimit $B%3%^%s%I$GCN$k$3$H$,$G$-$^$9!#(B
-t $B%H%i%s%6%/%7%g%s?t(B $B3F%/%i%$%"%s%H$,<B9T$9$k%H%i%s%6%/%7%g%s?t$r(B
$B;XDj$7$^$9!#>JN,;~$O(B 10 $B$H$J$j$^$9!#(B
-s $B%9%1!<%j%s%0%U%!%/%?!<(B
-i $B%*%W%7%g%s$H0l=o$K;HMQ$7$^$9!#(B
$B%9%1!<%j%s%0%U%!%/%?!<$O(B1$B0J>e$N@0?t!#%9%1!<%j%s%0%U%!(B
$B%/%?!<$rJQ$($k$3$H$K$h$j!"%F%9%H$NBP>]$H$J$k%F!<%V%k$N(B
$BBg$-$5$,(B 10$BK|(B x [$B%9%1!<%j%s%0%U%!%/%?!<(B]$B$K$J$j$^$9!#(B
$B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!#(B
-v $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B
history $B$N%/%j%"$r9T$J$$$^$9!#(B-v $B$H(B -n $B$r>JN,$9$k$H!"(B
$B:G>.8B$N(B vacuum $B$J$I$r9T$$$^$9!#$9$J$o$A!"(Bhistory $B$N:o=|!"(B
$B$H(B history, branches, history $B$N(B vacuum $B$r9T$$$^$9!#(B
$B$3$l$O!"(Bvacuum $B$N;~4V$r:G>.8B$K$7$J$,$i!"%Q%U%)!<%^%s%9$K(B
$B1F6A$9$k%4%_A]=|$r8z2LE*$K9T$$$^$9!#DL>o$O(B -v $B$H(B -n $B$r(B
$B>JN,$9$k$3$H$r$*$9$9$a$7$^$9!#(B
-n $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B
history $B$N%/%j%"$r9T$J$$$^$;$s!#(B
-S TPC-B$B$N%H%i%s%6%/%7%g%s$G$O$J$/!"8!:w$N$_$N%H%i%s%6%/%7%g%s$r(B
$B<B9T$7$^$9!#8!:w%9%T!<%I$rB,Dj$7$?$$$H$-$K;H$$$^$9!#(B
-d $B%G%P%C%0%*%W%7%g%s!#MM!9$J>pJs$,I=<($5$l$^$9!#(B
$B"#%G!<%?%Y!<%9$N=i4|2=(B
pgbench $B$G%Y%s%A%^!<%/%F%9%H$r<B;\$9$k$?$a$K$O!"$"$i$+$8$a%G!<%?%Y!<%9(B
$B$r=i4|2=$7!"%F%9%H%G!<%?$r:n$kI,MW$,$"$j$^$9!#(B
$ pgbench -i [$B%G!<%?%Y!<%9L>(B]
$B$3$l$K$h$j0J2<$N%F!<%V%k$,:n$i$l$^$9(B($B%9%1!<%j%s%0%U%!%/%?!<(B == 1 $B$N>l9g(B)$B!#(B
$B!vCm0U!v(B
$BF1$8L>A0$N%F!<%V%k$,$"$k$H:o=|$5$l$F$7$^$&$N$G$4Cm0U2<$5$$!*!*(B
$B%F!<%V%kL>(B $B%?%W%k?t(B
-------------------------
branches 1
tellers 10
accounts 100000
history 0
$B%9%1!<%j%s%0%U%!%/%?!<$r(B 10,100,1000 $B$J$I$KJQ99$9$k$H!">e5-%?%W%k?t$O(B
$B$=$l$K1~$8$F(B10$BG\!"(B100$BG\!"(B1000$BG\$K$J$j$^$9!#$?$H$($P!"%9%1!<%j%s%0%U%!(B
$B%/%?!<$r(B 10 $B$H$9$k$H!"(B
$B%F!<%V%kL>(B $B%?%W%k?t(B
-------------------------
branches 10
tellers 100
accounts 1000000
history 0
$B$K$J$j$^$9!#(B
$B"#!V%H%i%s%6%/%7%g%s!W$NDj5A(B
pgbench $B$G$O!"0J2<$N%7!<%1%s%9$rA4It40N;$7$F(B1$B%H%i%s%6%/%7%g%s$H?t$($F(B
$B$$$^$9!#(B
(1) begin;
(2) update accounts set abalance = abalance + :delta where aid = :aid;
$B$3$3$G!"(B:delta$B$O(B1$B$+$i(B1000$B$^$G$NCM$r<h$kMp?t!"(B:aid $B$O(B 1$B$+$i(B100000$B$^$G(B
$B$NCM$r<h$kMp?t$G$9!#0J2<!"Mp?t$NCM$O$=$l$>$l$3$N%H%i%s%6%/%7%g%s$N(B
$BCf$G$OF1$8CM$r;H$$$^$9!#(B
(3) select abalance from accounts where aid = :aid;
$B$3$3$G$O(B1$B7o$@$18!:w$5$l$^$9!#(B
(4) update tellers set tbalance = tbalance + :delta where tid = :tid;
$B$3$3$G(B :tid $B$O(B 1$B$+$i(B10$B$N4V$NCM$r$H$kMp?t$G$9!#(B
(5) update branches set bbalance = bbalance + :delta where bid = :bid;
$B$3$3$G(B :bid $B$O(B 1 $B$+$i(B[$B%9%1%j%s%0%U%!%/%?!<(B]$B$N4V$NCM$r<h$kMp?t$G$9!#(B
(6) insert into history(tid,bid,aid,delta) values(:tid,:bid,:aid,:delta);
(7) end;
$B"#:n<T$H%i%$%;%s%9>r7o(B
pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!#%i%$%;%s%9>r7o$O(B pgbench.c $B$N(B
$BKAF,$K=q$$$F$"$j$^$9!#$3$N>r7o$r<i$k8B$jL5=~$GMxMQ$7!"$^$?<+M3$K:FG[IU(B
$B$G$-$^$9!#(B
$B"#2~DjMzNr(B
2000/1/15 pgbench-1.2 $B$O(B PostgreSQL $B$K(B contribute $B$5$l$^$7$?!#(B
* -v $B%*%W%7%g%sDI2C(B
1999/09/29 pgbench-1.1 $B%j%j!<%9(B
* $BC+ED$5$s$K$h$k(Bcygwin$BBP1~%Q%C%A<h$j9~$_(B
* $B%P%C%/%(%s%I%/%i%C%7%e;~$NBP1~(B
* -S $B%*%W%7%g%sDI2C(B
1999/09/04 pgbench-1.0 $B%j%j!<%9(B

View File

@ -1,44 +1,53 @@
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for soundex
# $Header: /cvsroot/pgsql/contrib/soundex/Attic/Makefile,v 1.3 2000/06/15 18:55:15 momjian Exp $
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
NAME = soundex
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = soundex
OTHER_CLEAN = $(SQLS)
MODULE = $(MODNAME)$(DLSUFFIX)
all: $(MODS) $(SQLS)
all: module sql
module: $(MODULE)
sql: $(MODNAME).sql
install: $(MODULE)
cp -p $(MODULE) $(LIBDIR)/modules
cd $(LIBDIR)/modules; strip $(MODULE)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(LIBDIR)/modules/$(MODULE)|" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
install: install_doc install_sql install_mod
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f $(MODULE) $(MODNAME).sql
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend

53
contrib/soundex/README Normal file
View File

@ -0,0 +1,53 @@
SELECT text_soundex('hello world!');
CREATE TABLE s (nm text)\g
insert into s values ('john')\g
insert into s values ('joan')\g
insert into s values ('wobbly')\g
select * from s
where text_soundex(nm) = text_soundex('john')\g
select nm from s a, s b
where text_soundex(a.nm) = text_soundex(b.nm)
and a.oid <> b.oid\g
CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS
'select text_soundex($1) = text_soundex($2)'
LANGUAGE 'sql'\g
CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS
'select text_soundex($1) < text_soundex($2)'
LANGUAGE 'sql'\g
CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS
'select text_soundex($1) > text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS
'select text_soundex($1) <= text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS
'select text_soundex($1) >= text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS
'select text_soundex($1) <> text_soundex($2)'
LANGUAGE 'sql';
DROP OPERATOR #= (text,text)\g
CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq,
commutator=text_sx_eq)\g
SELECT *
FROM s
WHERE text_sx_eq(nm,'john')\g
SELECT *
from s
where s.nm #= 'john';

View File

@ -1,57 +1,4 @@
--------------- soundex.sql:
CREATE FUNCTION text_soundex(text) RETURNS text
AS '_OBJWD_/soundex.so' LANGUAGE 'c';
SELECT text_soundex('hello world!');
CREATE TABLE s (nm text)\g
insert into s values ('john')\g
insert into s values ('joan')\g
insert into s values ('wobbly')\g
select * from s
where text_soundex(nm) = text_soundex('john')\g
select nm from s a, s b
where text_soundex(a.nm) = text_soundex(b.nm)
and a.oid <> b.oid\g
CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS
'select text_soundex($1) = text_soundex($2)'
LANGUAGE 'sql'\g
CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS
'select text_soundex($1) < text_soundex($2)'
LANGUAGE 'sql'\g
CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS
'select text_soundex($1) > text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS
'select text_soundex($1) <= text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS
'select text_soundex($1) >= text_soundex($2)'
LANGUAGE 'sql';
CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS
'select text_soundex($1) <> text_soundex($2)'
LANGUAGE 'sql';
DROP OPERATOR #= (text,text)\g
CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq,
commutator=text_sx_eq)\g
SELECT *
FROM s
WHERE text_sx_eq(nm,'john')\g
SELECT *
from s
where s.nm #= 'john';
AS 'MODULE_PATHNAME' LANGUAGE 'c';

View File

@ -1,29 +1,64 @@
#
# $Header: /cvsroot/pgsql/contrib/spi/Makefile,v 1.13 2000/06/15 18:55:17 momjian Exp $
#
SRCDIR= ../../src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
CFLAGS+= $(CFLAGS_SL)
NAME =
PROGRAM =
OBJS = autoinc.o insert_username.o moddatetime.o refint.o timetravel.o
DOCS = spi.doc
SQLS = $(OBJS:.o=.sql)
BINS =
EXAMPLES= $(OBJS:.o=.example)
MODS = $(OBJS:.o=$(DLSUFFIX))
CFLAGS += -I. $(CFLAGS_SL)
ifdef REFINT_VERBOSE
CFLAGS+= -DREFINT_VERBOSE
endif
TARGETS= refint$(DLSUFFIX) refint.sql \
timetravel$(DLSUFFIX) timetravel.sql \
autoinc$(DLSUFFIX) autoinc.sql \
moddatetime$(DLSUFFIX) moddatetime.sql \
insert_username$(DLSUFFIX) insert_username.sql
OTHER_CLEAN = $(SQLS)
CLEANFILES+= $(TARGETS)
all: $(MODS) $(SQLS)
all:: $(TARGETS)
%.sql: %.sql.in
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
%.sql: %.source
rm -f $@; \
C=`pwd`; \
sed -e "s:_OBJWD_:$$C:g" \
-e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@
install: install_doc install_sql install_mod install_example
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
install_example:
for inst_file in $(EXAMPLES); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_EXAMPLESDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f $(TARGETS) *.o
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,109 +0,0 @@
Here are general trigger functions provided as workable examples
of using SPI and triggers. "General" means that functions may be
used for defining triggers for any tables but you have to specify
table/field names (as described below) while creating a trigger.
1. refint.c - functions for implementing referential integrity.
check_primary_key () is to used for foreign keys of a table.
You are to create trigger (BEFORE INSERT OR UPDATE) using this
function on a table referencing another table. You are to specify
as function arguments: triggered table column names which correspond
to foreign key, referenced table name and column names in referenced
table which correspond to primary/unique key.
You may create as many triggers as you need - one trigger for
one reference.
check_foreign_key () is to used for primary/unique keys of a table.
You are to create trigger (BEFORE DELETE OR UPDATE) using this
function on a table referenced by another table(s). You are to specify
as function arguments: number of references for which function has to
performe checking, action if referencing key found ('cascade' - to delete
corresponding foreign key, 'restrict' - to abort transaction if foreign keys
exist, 'setnull' - to set foreign key referencing primary/unique key
being deleted to null), triggered table column names which correspond
to primary/unique key, referencing table name and column names corresponding
to foreign key (, ... - as many referencing tables/keys as specified
by first argument).
Note, that NOT NULL constraint and unique index have to be defined by
youself.
There are examples in refint.example and regression tests
(sql/triggers.sql).
To CREATE FUNCTIONs use refint.sql (will be made by gmake from
refint.source).
# Excuse me for my bad english. Massimo Lambertini
#
#
# New check foreign key
#
I think that cascade mode is to be considered like that the operation over
main table is to be made also in referenced table .
When i Delete , i must delete from referenced table ,
but when i update , i update referenced table and not delete like unmodified refint.c .
I made a new version of refint.c that when i update it check the type of modified key ( if is a text , char() i
added '') and then create a update query that do the right thing .
For my point of view that policy is helpfull because i do not have in referenced table
loss of information .
In preprocessor subdir i have placed a little utility that from a SQL92 table definition,
it create all trigger for foreign key .
the schema that i use to analyze the problem is this
create table
A
( key int4 not null primary key ,...,
) ;
create table
REFERENCED_B
( key int 4 , ... ,
foreign key ( key ) references A --
);
--
-- Trigger for REFERENCED_B
--
CREATE INDEX I_REFERENCED_B_KEY ON REFERENCED_B ( KEY ) ;
CREATE TRIGGER T_P_REFERENCED_B_A BEFORE INSERT OR UPDATE ON REFERENCED_B FOR EACH ROW
EXECUTE PROCEDURE
check_primary_key('KEY','A','KEY' );
CREATE TRIGGER T_F_D_A_REFERENCED_B BEFORE DELETE ON A FOR EACH ROW
EXECUTE PROCEDURE
check_foreign_key(1,'cascade','KEY','REFERENCED_B ','KEY' );
CREATE TRIGGER T_F_U_A_REFERENCED_B AFTER UPDATE ON A FOR EACH ROW
EXECUTE PROCEDURE
check_foreign_key(1,'cascade','KEY','REFERENCED_B ','KEY' );
-- ********************************
I write TRIGGER T_F_U_A_REFERENCED_B ( AFTER ) and not BEFORE because if i set
BEFORE , when i try to modify ( update ) a key of A , i start a execution of TRIGGER T_P_REFERENCED_B_A
( check_primary_key) before the real modification of key in A , then the execution of ( check_primary_key) return
not ok.
With AFTER Clausole i modify first key of A then a update the value of referenced table REFERENCED_B.
Try also the new_example.sql to view the modified policy.
I wish that my explain of problem is quite clear .
If there is miss understanding ( cause my bad english ) please send email to massimo.lambertini@everex.it

View File

@ -1,6 +0,0 @@
DROP FUNCTION autoinc();
CREATE FUNCTION autoinc()
RETURNS opaque
AS '_OBJWD_/autoinc_DLSUFFIX_'
LANGUAGE 'newC';

View File

@ -1,6 +0,0 @@
DROP FUNCTION insert_username();
CREATE FUNCTION insert_username()
RETURNS opaque
AS '_OBJWD_/insert_username_DLSUFFIX_'
LANGUAGE 'newC';

View File

@ -1,6 +0,0 @@
DROP FUNCTION moddatetime();
CREATE FUNCTION moddatetime()
RETURNS opaque
AS '_OBJWD_/moddatetime_DLSUFFIX_'
LANGUAGE 'newC';

View File

@ -1,14 +0,0 @@
DROP FUNCTION check_primary_key ();
DROP FUNCTION check_foreign_key ();
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE 'newC'
;
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE 'newC'
;

View File

@ -1,12 +0,0 @@
DROP FUNCTION timetravel();
DROP FUNCTION set_timetravel(name, int4);
CREATE FUNCTION timetravel()
RETURNS opaque
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE 'newC';
CREATE FUNCTION set_timetravel(name, int4)
RETURNS int4
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE 'newC' WITH (isStrict);

View File

@ -1,65 +1,53 @@
#-------------------------------------------------------------------------
#
# $Header: /cvsroot/pgsql/contrib/string/Attic/Makefile,v 1.8 2000/06/15 18:55:21 momjian Exp $
#
# Makefile --
#
# Makefile for string I/O module.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
NAME = string_io
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = string_io
OTHER_CLEAN = $(SQLS)
SQLDEFS = $(MODNAME).sql
all: $(MODS) $(SQLS)
MODULE = $(MODNAME)$(DLSUFFIX)
MODDIR = $(LIBDIR)/modules
SQLDIR = $(LIBDIR)/sql
all: module sql
module: $(MODULE)
sql: $(SQLDEFS)
install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
cp -p $(MODULE) $(MODDIR)/
strip $(MODDIR)/$(MODULE)
cp -p $(SQLDEFS) $(SQLDIR)/
install-doc:
if [ -d "$(DOCDIR)" ]; then \
cp -p *.doc $(DOCDIR); \
else \
cp -p *.doc $(SQLDIR); \
fi
$(MODDIR):
mkdir -p $@
$(SQLDIR):
mkdir -p $@
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
install: install_doc install_sql install_mod
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f *~ $(MODULE) $(MODNAME).sql
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend

23
contrib/string/README Normal file
View File

@ -0,0 +1,23 @@
String io module for postgresql.
Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
This software is distributed under the GNU General Public License
either version 2, or (at your option) any later version.
These output functions can be used as substitution of the standard text
output functions to get the value of text fields printed in the format
used for C strings. This allows the output of queries or the exported
files to be processed more easily using standard unix filter programs
like perl or awk.
If you use the standard functions instead you could find a single tuple
splitted into many lines and the tabs embedded in the values could be
confused with those used as field delimters.
My function translates all non-printing characters into corresponding
esacape sequences as defined by the C syntax. All you need to reconstruct
the exact value in your application is a corresponding unescape function
like the string_input defined in the source code.
Massimo Dal Zotto <dz@cs.unitn.it>

View File

@ -1,21 +1,21 @@
#-------------------------------------------------------------------------
#
# Makefile --
# $Header: /cvsroot/pgsql/contrib/tools/Attic/Makefile,v 1.2 2000/06/15 18:55:22 momjian Exp $
#
# Makefile for contrib tools.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
all:
NAME =
install:
PROGRAM =
OBJS =
DOCS =
SQLS =
BINS =
EXAMPLES=
MODS =
clean:
rm -f *~
$(RM) *~
distclean: clean

View File

@ -1,65 +1,52 @@
#-------------------------------------------------------------------------
#
# Makefile --
# $Header: /cvsroot/pgsql/contrib/userlock/Attic/Makefile,v 1.8 2000/06/15 18:55:28 momjian Exp $
#
# Makefile for the user_locks module.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
NAME = user_locks
PROGRAM =
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS = $(NAME).sql
BINS =
EXAMPLES=
MODS = $(NAME)$(DLSUFFIX)
CFLAGS += -I. $(CFLAGS_SL)
MODNAME = user_locks
OTHER_CLEAN = $(SQLS)
SQLDEFS = $(MODNAME).sql
MODULE = $(MODNAME)$(DLSUFFIX)
MODDIR = $(LIBDIR)/modules
SQLDIR = $(LIBDIR)/sql
all: module sql
module: $(MODULE)
sql: $(SQLDEFS)
install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
cp -p $(MODULE) $(MODDIR)/
strip $(MODDIR)/$(MODULE)
cp -p $(SQLDEFS) $(SQLDIR)/
install-doc:
if [ -d "$(DOCDIR)" ]; then \
cp -p *.doc $(DOCDIR); \
else \
cp -p *.doc $(SQLDIR); \
fi
$(MODDIR):
mkdir -p $@
$(SQLDIR):
mkdir -p $@
all: $(MODS) $(SQLS)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
$(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
install: install_doc install_sql install_mod
%$(DLSUFFIX): %.c
$(CC) $(CFLAGS) -shared -o $@ $<
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_sql:
for inst_file in $(SQLS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \
done
install_mod:
for inst_file in $(MODS); do \
$(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \
done
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
rm -f *~ $(MODULE) $(MODNAME).sql
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend

55
contrib/userlock/README Normal file
View File

@ -0,0 +1,55 @@
User locks, by Massimo Dal Zotto <dz@cs.unitn.it>
Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
This software is distributed under the GNU General Public License
either version 2, or (at your option) any later version.
This loadable module, together with my user-lock.patch applied to the
backend, provides support for user-level long-term cooperative locks.
For example one can write:
select some_fields, user_write_lock_oid(oid) from table where id='key';
Now if the returned user_write_lock_oid field is 1 you have acquired an
user lock on the oid of the selected tuple and can now do some long operation
on it, like let the data being edited by the user.
If it is 0 it means that the lock has been already acquired by some other
process and you should not use that item until the other has finished.
Note that in this case the query returns 0 immediately without waiting on
the lock. This is good if the lock is held for long time.
After you have finished your work on that item you can do:
update table set some_fields where id='key';
select user_write_unlock_oid(oid) from table where id='key';
You can also ignore the failure and go ahead but this could produce conflicts
or inconsistent data in your application. User locks require a cooperative
behavior between users. User locks don't interfere with the normal locks
used by postgres for transaction processing.
This could also be done by setting a flag in the record itself but in
this case you have the overhead of the updates to the records and there
could be some locks not released if the backend or the application crashes
before resetting the lock flag.
It could also be done with a begin/end block but in this case the entire
table would be locked by postgres and it is not acceptable to do this for
a long period because other transactions would block completely.
The generic user locks use two values, group and id, to identify a lock,
which correspond to ip_posid and ip_blkid of an ItemPointerData.
Group is a 16 bit value while id is a 32 bit integer which could also be
an oid. The oid user lock functions, which take only an oid as argument,
use a group equal to 0.
The meaning of group and id is defined by the application. The user
lock code just takes two numbers and tells you if the corresponding
entity has been succesfully locked. What this mean is up to you.
My succestion is that you use the group to identify an area of your
application and the id to identify an object in this area.
Or you can just lock the oid of the tuples which are by definition unique.
Note also that a process can acquire more than one lock on the same entity
and it must release the lock the corresponding number of times. This can
be done calling the unlock funtion until it returns 0.

View File

@ -1,24 +1,48 @@
# $Header: /cvsroot/pgsql/contrib/vacuumlo/Makefile,v 1.2 2000/05/29 05:44:32 tgl Exp $
#
# $Header: /cvsroot/pgsql/contrib/vacuumlo/Makefile,v 1.3 2000/06/15 18:55:31 momjian Exp $
#
SRCDIR= ../../src
TOPDIR=../..
include $(SRCDIR)/Makefile.global
include ../Makefile.global
CONTRIBDIR=$(LIBDIR)/contrib
NAME = vacuumlo
CFLAGS+= -I$(LIBPQDIR)
PROGRAM = $(NAME)
OBJS = $(NAME).o
DOCS = $(NAME).doc
SQLS =
BINS = $(PROGRAM)
EXAMPLES=
MODS =
TARGETS= vacuumlo
CLEANFILES+= $(TARGETS)
CURDIR=`pwd`
CFLAGS += -I$(LIBPQDIR)
all:: $(TARGETS)
OTHER_CLEAN =
$(TARGETS): vacuumlo.o
$(CC) -o vacuumlo -L $(LIBDIR) -lpq -lcrypt vacuumlo.o
all: $(PROGRAM)
clean:
rm -f $(TARGETS) *.o
$(PROGRAM): $(OBJS) $(LIBPGEASYDIR)/libpgeasy.a
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPGEASY)
dist:
tar cf vacuumlo.tar README Makefile vacuumlo.c
install: install_doc install_bin
install_doc:
for inst_file in $(DOCS); do \
$(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \
done
install_bin:
for inst_file in $(BINS); do \
$(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \
done
depend dep:
$(CC) -MM -MG $(CFLAGS) *.c > depend
clean:
$(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -8,13 +8,13 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.3 2000/01/26 05:55:52 momjian Exp $
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.4 2000/06/15 18:55:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

View File

@ -7,7 +7,7 @@
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.77 2000/06/11 11:39:47 petere Exp $
# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.78 2000/06/15 18:55:34 momjian Exp $
#
# NOTES
# Essentially all Postgres make files include this file and use the
@ -54,10 +54,12 @@ BSD_SHLIB= true
ELF_SYSTEM= @ELF_SYS@
LIBPQDIR= $(SRCDIR)/interfaces/libpq
LIBPGEASYDIR= $(SRCDIR)/interfaces/libpgeasy
LIBPGTCLDIR= $(SRCDIR)/interfaces/libpgtcl
LIBPQ= -L$(LIBPQDIR) -lpq
LIBPGTCL= -L$(LIBPGTCLDIR) -lpgtcl
LIBPGEASY= -L$(LIBPGEASYDIR) -lpgeasy
# For convenience, POSTGRESDIR is where BINDIR, and LIBDIR
# and other target destinations are rooted. Of course, each of these is