From f7f177d372750e4f766ccefdf20e1b30d66cba0a Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 15 Jun 2000 18:55:34 +0000 Subject: [PATCH] /contrib patch from Karel. --- contrib/Makefile | 56 +- contrib/README | 131 ++- contrib/apache_logging/apachelog.sql | 3 - contrib/apache_logging/httpconf.txt | 12 - contrib/array/Makefile | 74 +- contrib/array/README | 49 ++ contrib/bit/Makefile | 45 -- contrib/bit/varbit.c | 891 --------------------- contrib/bit/varbit.demo.sql | 29 - contrib/bit/varbit.drop.sql | 36 - contrib/bit/varbit.h | 73 -- contrib/bit/varbit.source | 171 ---- contrib/bit/varbit_glue.c | 24 - contrib/bit/vartest.c | 184 ----- contrib/datetime/Makefile | 66 -- contrib/datetime/datetime_functions.c | 281 ------- contrib/datetime/datetime_functions.h | 28 - contrib/datetime/datetime_functions.sql.in | 100 --- contrib/earthdistance/Makefile | 58 +- contrib/earthdistance/earthdistance.c | 7 +- contrib/earthdistance/earthdistance.sql | 23 - contrib/findoidjoins/Makefile | 57 +- contrib/fulltextindex/BENCH | 97 --- contrib/fulltextindex/Makefile | 66 +- contrib/fulltextindex/README | 100 +++ contrib/fulltextindex/fticopy | 204 ----- contrib/isbn_issn/Makefile | 54 +- contrib/isbn_issn/README | 4 + contrib/isbn_issn/isbn.c | 199 ----- contrib/isbn_issn/isbn.sql | 116 --- contrib/isbn_issn/issn.c | 190 ----- contrib/isbn_issn/issn.sql | 116 --- contrib/lo/Makefile | 65 +- contrib/lo/README | 2 - contrib/lo/drop.sql | 21 - contrib/lo/lo.sql.in | 15 +- contrib/lo/test.sql | 57 -- contrib/mSQL-interface/README | 1 + contrib/miscutil/Makefile | 75 +- contrib/miscutil/README | 43 + contrib/noupdate/README | 20 + contrib/noupdate/noup.example | 9 - contrib/noupdate/noup.source | 7 - contrib/odbc/odbc.sql | 145 ---- contrib/os2client/Makefile | 86 -- contrib/os2client/README | 50 -- contrib/os2client/config.h | 26 - contrib/os2client/libpq.a | Bin 57128 -> 0 bytes contrib/os2client/psql.exe | Bin 188698 -> 0 bytes contrib/pg_dumplo/Makefile | 56 +- contrib/pg_dumplo/README | 123 ++- contrib/pg_dumplo/VERSION | 1 - contrib/pg_dumplo/pg_dumplo.c | 379 --------- contrib/pgbench/Makefile | 51 +- contrib/pgbench/README.jis | 166 ---- contrib/soundex/Makefile | 55 +- contrib/soundex/README | 53 ++ contrib/soundex/soundex.sql.in | 55 +- contrib/spi/Makefile | 67 +- contrib/spi/README.MAX | 109 --- contrib/spi/autoinc.source | 6 - contrib/spi/insert_username.source | 6 - contrib/spi/moddatetime.source | 6 - contrib/spi/refint.source | 14 - contrib/spi/timetravel.source | 12 - contrib/string/Makefile | 76 +- contrib/string/README | 23 + contrib/tools/Makefile | 24 +- contrib/userlock/Makefile | 75 +- contrib/userlock/README | 55 ++ contrib/vacuumlo/Makefile | 54 +- contrib/vacuumlo/vacuumlo.c | 4 +- src/Makefile.global.in | 4 +- 73 files changed, 1144 insertions(+), 4496 deletions(-) create mode 100644 contrib/array/README create mode 100644 contrib/miscutil/README create mode 100644 contrib/noupdate/README delete mode 100644 contrib/os2client/Makefile delete mode 100644 contrib/os2client/README delete mode 100644 contrib/os2client/config.h delete mode 100644 contrib/os2client/libpq.a delete mode 100755 contrib/os2client/psql.exe create mode 100644 contrib/soundex/README create mode 100644 contrib/string/README create mode 100644 contrib/userlock/README diff --git a/contrib/Makefile b/contrib/Makefile index 0dc68e48549..70c0cddbab1 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -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 + + +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 *; do \ + for dir in $(WANTED_DIRS); do \ if [ -e $$dir/Makefile ]; then \ $(MAKE) -C $$dir $@ ; \ fi; \ diff --git a/contrib/README b/contrib/README index 7dcd1ca1fe9..97166f27cf5 100644 --- a/contrib/README +++ b/contrib/README @@ -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 + FIXME: + os2client + odbc + spi/preprocessor + tools + -array - - Array iterator functions - by Massimo Dal Zotto + - in each directory must be Makefile, possible Makefile template + is below this text, -bit - - Bit type - by Adriaan Joubert +-------- +# +# $Header: /cvsroot/pgsql/contrib/README,v 1.18 2000/06/15 18:54:29 momjian Exp $ +# -datetime - - Date & time functions - by Massimo Dal Zotto +TOPDIR=../.. -earthdistance - - Operator for computing earth distance for two points - by Hal Snyder +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 +NAME = some_name -fulltextindex - - Full text indexing using triggers - by Maarten Boekhold +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 +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 +OTHER_CLEAN = $(SQLS) -linux - - Start postgres back end system - by Thomas Lockhart +all: $(MODS) $(SQLS) -lo - - Large Object maintenance - by Peter Mount +%.sql: %.sql.in + $(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@ -miscutil - - Postgres assert checking and various utility functions - by Dal Zotto -mSQL-interface - - mSQL API translation library - by Aldrin Leal +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 +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 +depend dep: + $(CC) -MM -MG $(CFLAGS) *.c > depend -unixdate - - Conversions from integer to datetime - by Thomas Lockhart +clean: + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log -userlock - - User locks - by Massimo Dal Zotto - -vacuumlo - - Remove orphaned large objects - by Peter T Mount - -pgbench - - TPC-B like benchmarking tool - by Tatsuo Ishii +ifeq (depend,$(wildcard depend)) +include depend +endif +----------- + \ No newline at end of file diff --git a/contrib/apache_logging/apachelog.sql b/contrib/apache_logging/apachelog.sql index 7ae26386324..e69de29bb2d 100644 --- a/contrib/apache_logging/apachelog.sql +++ b/contrib/apache_logging/apachelog.sql @@ -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; diff --git a/contrib/apache_logging/httpconf.txt b/contrib/apache_logging/httpconf.txt index 77a412d6410..e69de29bb2d 100644 --- a/contrib/apache_logging/httpconf.txt +++ b/contrib/apache_logging/httpconf.txt @@ -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' diff --git a/contrib/array/Makefile b/contrib/array/Makefile index c29569d76f5..04d785da72d 100644 --- a/contrib/array/Makefile +++ b/contrib/array/Makefile @@ -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 - -include $(SRCDIR)/Makefile.global - -CFLAGS += -I. $(CFLAGS_SL) -MODNAME = array_iterator +TOPDIR=../.. -SQLDEFS = $(MODNAME).sql +include ../Makefile.global -MODULE = $(MODNAME)$(DLSUFFIX) +NAME = array_iterator -MODDIR = $(LIBDIR)/modules +PROGRAM = +OBJS = $(NAME).o +DOCS = $(NAME).doc +SQLS = $(NAME).sql +BINS = +EXAMPLES= +MODS = $(NAME)$(DLSUFFIX) -SQLDIR = $(LIBDIR)/sql - -all: module sql - -module: $(MODULE) +CFLAGS += -I. $(CFLAGS_SL) -sql: $(SQLDEFS) +OTHER_CLEAN = $(SQLS) -install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR) - cp -p $(MODULE) $(MODDIR)/ - strip $(MODDIR)/$(MODULE) - cp -p $(SQLDEFS) $(SQLDIR)/ +all: $(MODS) $(SQLS) -install-doc: - if [ -d "$(DOCDIR)" ]; then \ - cp -p *.doc $(DOCDIR); \ - else \ - cp -p *.doc $(SQLDIR); \ - fi +%.sql: %.sql.in + $(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@ -$(MODDIR): - mkdir -p $@ +install: install_doc install_sql install_mod -$(SQLDIR): - mkdir -p $@ +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done -%.sql: %.sql.in - sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@ +install_sql: + for inst_file in $(SQLS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \ + done -.SUFFIXES: $(DLSUFFIX) +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 diff --git a/contrib/array/README b/contrib/array/README new file mode 100644 index 00000000000..b072ebe3970 --- /dev/null +++ b/contrib/array/README @@ -0,0 +1,49 @@ +Array iterator functions, by Massimo Dal Zotto +Copyright (C) 1999, Massimo Dal Zotto + +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_]" 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. diff --git a/contrib/bit/Makefile b/contrib/bit/Makefile index 58c66b2025b..e69de29bb2d 100644 --- a/contrib/bit/Makefile +++ b/contrib/bit/Makefile @@ -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 - diff --git a/contrib/bit/varbit.c b/contrib/bit/varbit.c index 20caaf9f7cb..e69de29bb2d 100644 --- a/contrib/bit/varbit.c +++ b/contrib/bit/varbit.c @@ -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; -} diff --git a/contrib/bit/varbit.demo.sql b/contrib/bit/varbit.demo.sql index e47a83da052..e69de29bb2d 100644 --- a/contrib/bit/varbit.demo.sql +++ b/contrib/bit/varbit.demo.sql @@ -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" 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; diff --git a/contrib/bit/varbit.drop.sql b/contrib/bit/varbit.drop.sql index 54b831ea2dc..e69de29bb2d 100644 --- a/contrib/bit/varbit.drop.sql +++ b/contrib/bit/varbit.drop.sql @@ -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; diff --git a/contrib/bit/varbit.h b/contrib/bit/varbit.h index ca7202b4c80..e69de29bb2d 100644 --- a/contrib/bit/varbit.h +++ b/contrib/bit/varbit.h @@ -1,73 +0,0 @@ -#include -#include -#include - -#include /* faked on sunos4 */ - -#include - -#include "postgres.h" -#ifdef HAVE_LIMITS_H -#include -#ifndef MAXINT -#define MAXINT INT_MAX -#endif -#else -#ifdef HAVE_VALUES_H -#include -#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); diff --git a/contrib/bit/varbit.source b/contrib/bit/varbit.source index c47ea72e902..e69de29bb2d 100644 --- a/contrib/bit/varbit.source +++ b/contrib/bit/varbit.source @@ -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 -); diff --git a/contrib/bit/varbit_glue.c b/contrib/bit/varbit_glue.c index bd79a849a50..e69de29bb2d 100644 --- a/contrib/bit/varbit_glue.c +++ b/contrib/bit/varbit_glue.c @@ -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); -} diff --git a/contrib/bit/vartest.c b/contrib/bit/vartest.c index 7725f6bbd30..e69de29bb2d 100644 --- a/contrib/bit/vartest.c +++ b/contrib/bit/vartest.c @@ -1,184 +0,0 @@ -#include "postgres.h" -#include "varbit.h" -#include - -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))); - } - -} diff --git a/contrib/datetime/Makefile b/contrib/datetime/Makefile index 8f43ff83b7b..e69de29bb2d 100644 --- a/contrib/datetime/Makefile +++ b/contrib/datetime/Makefile @@ -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 diff --git a/contrib/datetime/datetime_functions.c b/contrib/datetime/datetime_functions.c index ca9c8afe35e..e69de29bb2d 100644 --- a/contrib/datetime/datetime_functions.c +++ b/contrib/datetime/datetime_functions.c @@ -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 - * - * Date2mjd code contributed by Reiner Dassing - * - * This software is distributed under the GNU General Public License - * either version 2, or (at your option) any later version. - */ - -#include -#include -#include -#ifdef HAVE_FLOAT_H -#include -#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(¤t_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: - */ diff --git a/contrib/datetime/datetime_functions.h b/contrib/datetime/datetime_functions.h index 4b0eb499884..e69de29bb2d 100644 --- a/contrib/datetime/datetime_functions.h +++ b/contrib/datetime/datetime_functions.h @@ -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: - */ diff --git a/contrib/datetime/datetime_functions.sql.in b/contrib/datetime/datetime_functions.sql.in index 8c35dad55f5..e69de29bb2d 100644 --- a/contrib/datetime/datetime_functions.sql.in +++ b/contrib/datetime/datetime_functions.sql.in @@ -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 --- --- 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 diff --git a/contrib/earthdistance/Makefile b/contrib/earthdistance/Makefile index 0cdaaac5a65..37bfb5df311 100644 --- a/contrib/earthdistance/Makefile +++ b/contrib/earthdistance/Makefile @@ -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 diff --git a/contrib/earthdistance/earthdistance.c b/contrib/earthdistance/earthdistance.c index 8dbef7295cf..7f2826a35b8 100644 --- a/contrib/earthdistance/earthdistance.c +++ b/contrib/earthdistance/earthdistance.c @@ -7,8 +7,11 @@ #include /* 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); + /****************************************************** * diff --git a/contrib/earthdistance/earthdistance.sql b/contrib/earthdistance/earthdistance.sql index 174d5650857..e69de29bb2d 100644 --- a/contrib/earthdistance/earthdistance.sql +++ b/contrib/earthdistance/earthdistance.sql @@ -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; diff --git a/contrib/findoidjoins/Makefile b/contrib/findoidjoins/Makefile index 0394510f43a..5b2377bf823 100644 --- a/contrib/findoidjoins/Makefile +++ b/contrib/findoidjoins/Makefile @@ -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 -clean: - rm -f *.o $(TARGET) log core +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 -s -o bin -g bin $(TARGET) $(INSTALLDIR)/bin +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) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log + +ifeq (depend,$(wildcard depend)) +include depend +endif diff --git a/contrib/fulltextindex/BENCH b/contrib/fulltextindex/BENCH index d8375fe6067..e69de29bb2d 100644 --- a/contrib/fulltextindex/BENCH +++ b/contrib/fulltextindex/BENCH @@ -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% diff --git a/contrib/fulltextindex/Makefile b/contrib/fulltextindex/Makefile index bf1d02d227c..a417b4a2bff 100644 --- a/contrib/fulltextindex/Makefile +++ b/contrib/fulltextindex/Makefile @@ -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 diff --git a/contrib/fulltextindex/README b/contrib/fulltextindex/README index 06850f7493d..fdb6fcf3b10 100644 --- a/contrib/fulltextindex/README +++ b/contrib/fulltextindex/README @@ -94,4 +94,104 @@ Method 1 is very slow, 2 a lot faster, and for very large tables, 3 is preferred. +BENCH: +~~~~~ + Maarten Boekhold +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% diff --git a/contrib/fulltextindex/fticopy b/contrib/fulltextindex/fticopy index 6b6d68e4900..e69de29bb2d 100644 --- a/contrib/fulltextindex/fticopy +++ b/contrib/fulltextindex/fticopy @@ -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 = ); - - return $n;; -} - -sub get_password { - print "Password: "; - - system("stty -echo < /dev/tty"); - chop($pwd = ); - 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(); diff --git a/contrib/isbn_issn/Makefile b/contrib/isbn_issn/Makefile index bd3c4325cd2..36ef6a5aa26 100644 --- a/contrib/isbn_issn/Makefile +++ b/contrib/isbn_issn/Makefile @@ -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 diff --git a/contrib/isbn_issn/README b/contrib/isbn_issn/README index 6b29eb929b4..6b734ce905f 100644 --- a/contrib/isbn_issn/README +++ b/contrib/isbn_issn/README @@ -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() diff --git a/contrib/isbn_issn/isbn.c b/contrib/isbn_issn/isbn.c index ff63381255c..e69de29bb2d 100644 --- a/contrib/isbn_issn/isbn.c +++ b/contrib/isbn_issn/isbn.c @@ -1,199 +0,0 @@ -/* - * PostgreSQL type definitions for ISBNs. - * - * $Id: isbn.c,v 1.3 2000/05/29 05:44:26 tgl Exp $ - */ - -#include - -#include -#include - -/* - * 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 - */ diff --git a/contrib/isbn_issn/isbn.sql b/contrib/isbn_issn/isbn.sql index 4889aafbd40..e69de29bb2d 100644 --- a/contrib/isbn_issn/isbn.sql +++ b/contrib/isbn_issn/isbn.sql @@ -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 --- diff --git a/contrib/isbn_issn/issn.c b/contrib/isbn_issn/issn.c index 145f4e38f44..e69de29bb2d 100644 --- a/contrib/isbn_issn/issn.c +++ b/contrib/isbn_issn/issn.c @@ -1,190 +0,0 @@ -/* - * PostgreSQL type definitions for ISSNs. - * - * $Id: issn.c,v 1.3 2000/05/29 05:44:26 tgl Exp $ - */ - -#include - -#include -#include - -/* - * 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 - */ diff --git a/contrib/isbn_issn/issn.sql b/contrib/isbn_issn/issn.sql index c1fac916248..e69de29bb2d 100644 --- a/contrib/isbn_issn/issn.sql +++ b/contrib/isbn_issn/issn.sql @@ -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 --- diff --git a/contrib/lo/Makefile b/contrib/lo/Makefile index e091049293b..ed6f9c92b37 100644 --- a/contrib/lo/Makefile +++ b/contrib/lo/Makefile @@ -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 ../Makefile.global -include $(SRCDIR)/Makefile.global +NAME = lo -CONTRIBDIR=$(LIBDIR)/modules +PROGRAM = +OBJS = $(NAME).o +DOCS = $(NAME).doc +SQLS = $(NAME).sql +BINS = +EXAMPLES= +MODS = $(NAME)$(DLSUFFIX) -CFLAGS+= $(CFLAGS_SL) +CFLAGS += -I. $(CFLAGS_SL) ifdef REFINT_VERBOSE CFLAGS+= -DREFINT_VERBOSE endif -TARGETS= lo$(DLSUFFIX) lo.sql +OTHER_CLEAN = $(SQLS) + +all: $(MODS) $(SQLS) -CLEANFILES+= $(TARGETS) -all:: $(TARGETS) +%.sql: %.sql.in + $(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@ -install:: all $(CONTRIBDIR) - for f in *$(DLSUFFIX); do $(INSTALL) -c $$f $(CONTRIBDIR)/$$f; done -$(CONTRIBDIR): - mkdir -p $(CONTRIBDIR) +install: install_doc install_sql install_mod -%.sql: %.sql.in - rm -f $@; \ - C=`pwd`; \ - sed -e "s:_OBJWD_:$(CONTRIBDIR):g" \ - -e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@ +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 diff --git a/contrib/lo/README b/contrib/lo/README index 3576d3fe4f9..aa06adf0848 100755 --- a/contrib/lo/README +++ b/contrib/lo/README @@ -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 diff --git a/contrib/lo/drop.sql b/contrib/lo/drop.sql index 2472715a3d5..e69de29bb2d 100644 --- a/contrib/lo/drop.sql +++ b/contrib/lo/drop.sql @@ -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 diff --git a/contrib/lo/lo.sql.in b/contrib/lo/lo.sql.in index 869f5ccc545..58390028d0c 100644 --- a/contrib/lo/lo.sql.in +++ b/contrib/lo/lo.sql.in @@ -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 diff --git a/contrib/lo/test.sql b/contrib/lo/test.sql index 0c0da2cfd65..e69de29bb2d 100755 --- a/contrib/lo/test.sql +++ b/contrib/lo/test.sql @@ -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 diff --git a/contrib/mSQL-interface/README b/contrib/mSQL-interface/README index 214d4466741..714ab290565 100644 --- a/contrib/mSQL-interface/README +++ b/contrib/mSQL-interface/README @@ -1,3 +1,4 @@ + Hello! :) (Sorry for my english. But if i wrote in portuguese, you wouldn't diff --git a/contrib/miscutil/Makefile b/contrib/miscutil/Makefile index 742db0334f5..38118a6f8e3 100644 --- a/contrib/miscutil/Makefile +++ b/contrib/miscutil/Makefile @@ -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 - -include $(SRCDIR)/Makefile.global - -CFLAGS += -I. $(CFLAGS_SL) - -MODNAME = misc_utils -SQLDEFS = $(MODNAME).sql +TOPDIR=../.. -MODULE = $(MODNAME)$(DLSUFFIX) +include ../Makefile.global -MODDIR = $(LIBDIR)/modules +NAME = misc_utils -SQLDIR = $(LIBDIR)/sql +PROGRAM = +OBJS = $(NAME).o +DOCS = $(NAME).doc +SQLS = $(NAME).sql +BINS = +EXAMPLES= +MODS = $(NAME)$(DLSUFFIX) -all: module sql - -module: $(MODULE) - -sql: $(SQLDEFS) +CFLAGS += -I. $(CFLAGS_SL) -install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR) - cp -p $(MODULE) $(MODDIR)/ - strip $(MODDIR)/$(MODULE) - cp -p $(SQLDEFS) $(SQLDIR)/ +OTHER_CLEAN = $(SQLS) -install-doc: - if [ -d "$(DOCDIR)" ]; then \ - cp -p *.doc $(DOCDIR); \ - else \ - cp -p *.doc $(SQLDIR); \ - fi +all: $(MODS) $(SQLS) -$(MODDIR): - mkdir -p $@ +%.sql: %.sql.in + $(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@ -$(SQLDIR): - mkdir -p $@ +install: install_doc install_sql install_mod -%.sql: %.sql.in - sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@ +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done -.SUFFIXES: $(DLSUFFIX) +install_sql: + for inst_file in $(SQLS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \ + done -%$(DLSUFFIX): %.c - $(CC) $(CFLAGS) -shared -o $@ $< +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 diff --git a/contrib/miscutil/README b/contrib/miscutil/README new file mode 100644 index 00000000000..903455513a2 --- /dev/null +++ b/contrib/miscutil/README @@ -0,0 +1,43 @@ +Miscellaneous utility functions for PostgreSQL. +Copyright (C) 1999, Massimo Dal Zotto + +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 diff --git a/contrib/noupdate/README b/contrib/noupdate/README new file mode 100644 index 00000000000..1c773dc7788 --- /dev/null +++ b/contrib/noupdate/README @@ -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; diff --git a/contrib/noupdate/noup.example b/contrib/noupdate/noup.example index 62db1ee0ccd..e69de29bb2d 100644 --- a/contrib/noupdate/noup.example +++ b/contrib/noupdate/noup.example @@ -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; diff --git a/contrib/noupdate/noup.source b/contrib/noupdate/noup.source index a1917a31209..e69de29bb2d 100644 --- a/contrib/noupdate/noup.source +++ b/contrib/noupdate/noup.source @@ -1,7 +0,0 @@ -DROP FUNCTION noup (); - -CREATE FUNCTION noup () - RETURNS opaque - AS '_OBJWD_/noup_DLSUFFIX_' - LANGUAGE 'newC' -; diff --git a/contrib/odbc/odbc.sql b/contrib/odbc/odbc.sql index bec7f486b4f..e69de29bb2d 100644 --- a/contrib/odbc/odbc.sql +++ b/contrib/odbc/odbc.sql @@ -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'; - diff --git a/contrib/os2client/Makefile b/contrib/os2client/Makefile deleted file mode 100644 index e3910ecb02f..00000000000 --- a/contrib/os2client/Makefile +++ /dev/null @@ -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 - diff --git a/contrib/os2client/README b/contrib/os2client/README deleted file mode 100644 index 306cda27ea7..00000000000 --- a/contrib/os2client/README +++ /dev/null @@ -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 - - - diff --git a/contrib/os2client/config.h b/contrib/os2client/config.h deleted file mode 100644 index 7a98eb60a9c..00000000000 --- a/contrib/os2client/config.h +++ /dev/null @@ -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) - - - diff --git a/contrib/os2client/libpq.a b/contrib/os2client/libpq.a deleted file mode 100644 index 467782861d2691336ab88f6bdef086b334b91459..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 57128 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 depend clean: - $(RM) -f *~ $(OBJECTS) $(PROGRAM) + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log + +ifeq (depend,$(wildcard depend)) +include depend +endif + \ No newline at end of file diff --git a/contrib/pg_dumplo/README b/contrib/pg_dumplo/README index b36cdd01d0b..aef8f9f71d0 100644 --- a/contrib/pg_dumplo/README +++ b/contrib/pg_dumplo/README @@ -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. - Compilation: - - you need the PostgreSQL's devel. libs - - and type: 'make' - - Karel Zak - - +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. diff --git a/contrib/pg_dumplo/VERSION b/contrib/pg_dumplo/VERSION index 05b19b1f76e..e69de29bb2d 100644 --- a/contrib/pg_dumplo/VERSION +++ b/contrib/pg_dumplo/VERSION @@ -1 +0,0 @@ -0.0.4 \ No newline at end of file diff --git a/contrib/pg_dumplo/pg_dumplo.c b/contrib/pg_dumplo/pg_dumplo.c index 6e6a20bef55..e69de29bb2d 100644 --- a/contrib/pg_dumplo/pg_dumplo.c +++ b/contrib/pg_dumplo/pg_dumplo.c @@ -1,379 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define _GNU_SOURCE -#include - -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