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 0dc68e4854..70c0cddbab 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 7dcd1ca1fe..97166f27cf 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 7ae2638632..e69de29bb2 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 77a412d641..e69de29bb2 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 c29569d76f..04d785da72 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 0000000000..b072ebe397 --- /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 58c66b2025..e69de29bb2 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 20caaf9f7c..e69de29bb2 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 e47a83da05..e69de29bb2 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 54b831ea2d..e69de29bb2 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 ca7202b4c8..e69de29bb2 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 c47ea72e90..e69de29bb2 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 bd79a849a5..e69de29bb2 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 7725f6bbd3..e69de29bb2 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 8f43ff83b7..e69de29bb2 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 ca9c8afe35..e69de29bb2 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 4b0eb49988..e69de29bb2 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 8c35dad55f..e69de29bb2 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 0cdaaac5a6..37bfb5df31 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 8dbef7295c..7f2826a35b 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 174d565085..e69de29bb2 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 0394510f43..5b2377bf82 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 d8375fe606..e69de29bb2 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 bf1d02d227..a417b4a2bf 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 06850f7493..fdb6fcf3b1 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 6b6d68e490..e69de29bb2 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 bd3c4325cd..36ef6a5aa2 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 6b29eb929b..6b734ce905 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 ff63381255..e69de29bb2 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 4889aafbd4..e69de29bb2 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 145f4e38f4..e69de29bb2 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 c1fac91624..e69de29bb2 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 e091049293..ed6f9c92b3 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 3576d3fe4f..aa06adf084 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 2472715a3d..e69de29bb2 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 869f5ccc54..58390028d0 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 0c0da2cfd6..e69de29bb2 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 214d446674..714ab29056 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 742db0334f..38118a6f8e 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 0000000000..903455513a --- /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 0000000000..1c773dc778 --- /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 62db1ee0cc..e69de29bb2 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 a1917a3120..e69de29bb2 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 bec7f486b4..e69de29bb2 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 e3910ecb02..0000000000 --- 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 306cda27ea..0000000000 --- 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 7a98eb60a9..0000000000 --- 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 HcmV?d00001 literal 57128 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 diff --git a/contrib/os2client/psql.exe b/contrib/os2client/psql.exe deleted file mode 100755 index d208e383be45982e18408cd091cc4aecd3178ee1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188698 zcmeFa3wTu3)i-`77nsCoq9Ral91sj(!cB|ZOGpNY<}ywa6andw44hy{VrB-=CK4P| zi7__yQhT$t^-}xRwpz6!f=$7Kv|6dvx3+3az0@-u+G6F^sL}j?YpuP{oJoSU-}8On z^MAglXlBk?d+oK?UVH7e*IxTF<(GfYlWvT_f8+7re8WgH@Na~%n7;nizY&I!V@x(Y zz|ZxJFeczHEe+53)Bi%7wwg1h&8^k%1C-@|W#CMFxGcvk>^V_{Q z?wy#MF=N5p&1o4UcZ@9l_}OS;-_9FGKRf+|-e~1}`#eUZbmxZ8K0E%V-V^pk3U{>_ z_FSXoghv)XyP>_`h@6r*eb*NZ`&=XJ-F3ZTpKY{c?==1>X(#U=G1?f|8K}Cu+t}F> zzWXc2zMaOxXUDgk-SyH=qXZA5-`(3DIeF(udd^-j5FPQzqG!kV?W524_uV`q%{YJH zaie`!Z~s4k6wUlmWaMk_?fSftm=HUV*10Idu>WRso-~4pQq9^I2~0a!xWi`sa%61LHj5eeM0LBcs~;r$=(z z`{zZnIa9{|%+yuAt!S+jZ{AK3QKA0=J^&cf*1%lZJ>3X+zkv?~(Fn$3KGVx)tqP(A3ocG!T%~vau;*u5XGq)}5F=u_f$!FEC5|<)xe+ zjy5+pwM0U7=DMp*WCChUI7CnD>N(?*V4WFi++5$%)VL|s7(u$Py!jAX@zX+EL&nI$=`-+e`iX8v|MUDG3H)D^K-pzdR2r-}{mX;>KL_9PW*8X^ zZAXF_?!)|U7~2)XQ+Owwi8_NyUjRBKJeCN+hvygZHzr+%n2Gr2f1o?~pDPei0PlKzE4r#r>gH!>iabH zjlqoZ$EfeI>iaY5`*ihvhWb8JeV?Vi&sN{#)VHa=S*~Daf_l$r4qwIAl-{Wl|0n;b z((b<{ct75scl!v#C3-t>B6>1ib%ujgCoX+C`IN>5vguk?(xW%!zs zkyeVYOES`yBiH(jv^UdXp}loY;o4wBLl`Cf=ih%M@c*O)PVm&hR=}c}s9t-Taoa^y zO}2FO@SlJGk-&c>@c*y`EOKA$zk1V*M2`IyzV`L-zkW<$(+vC3>pX_tdObe2e8n(g zPv!XS5qL{{oVB8;xTdDuT(!a%SW;Q#TVt*&swgU3c{x2rg6kSWYqGPNTC#`YnF`NT zc;>3f!APWKW`Q|v+BABqn6hTgd}DL4HX7YzMy!xo7X-mzI8mYa2qr#<1BG zjhJHwb{*rf>dN@ty&tWEH~G;G;LaotkE#lYt^O8eF2|&RW#TDPNhsU5^Zh> zh1DC1t0*h2s`gcwR8;GP#-_$XE;Jlzsc+mcp>@L42}U^5)ND3@&rl;^n2fg2q_ci~ zeJ!|eYBceG(5!80tgGi&%5Ov)C4-SwwY>6Dvjo+xid@|gYF*~Lq_Q=z)?ZdsQPp}$ zjW4irZCPn~X|)lynzop=(Uum>PtBHSV_~Eom3K{A83Xhn4u_msU1{c*R#oP==2u-( zhEIP}II^K76vm@3+S1gFHo#*|6+SAO8XZt}I21976(&$wv1;KtYk*R@bZI^(DF#() zeyf>Ga`8;b=NLq4cz#0>VzqHFgyqqS?$JV8ih3jon)P85wP}^gw3b#>`2y9g(j6gdv$jp)C1VOK{UuHSOUzS_ttuUz3XS1qj!Tv`+;X{C0f2Pi~i zbkn*}ODnfKRFrybxJjfr-`LcIb`LfxpxN9MW|P2hBde^ET7QT_&o@F_Ya62BdgN_r zLW4sO$TFMtjp6z_&`VJZ!XQ#bC1(D5Xacok{(PhEYCOOoH8fleB8YYc%}q^p(T0#g zZ^-aTR?ZMx_312|wripwCil{0?;LKJpwXqQ##d!d7V|v~K{a&oDQ0W-Cz^-stfaZu zMj_erhc)y6e&0WCKZf)}=#*-_kT)Z18Mk>$G#V;MR^(#5zc8fv*3O5NNLtZ!u3fFZE< zq1q@9kw|IO2%u0=GK^6~w`i>6+>qA@EWq@^%p2#4h z4&$IaWifIMEE^jtMkb4`u-SN#55dKTuf~YKNpe$)A-Stp`h8~P>SpeFgEAMwJk>W+ z7#e;MBT05b*VzN5%a);h3=$hQgj&SKf$dIqAs0=Bq=-lkO^3!sS1!@SB$Wy`88Rn| z2tP_qs(cvBD~f$)ID`gjtPL?Ut9TGj0afs@ri7$ZOtFOKhEQXuB^YUHkpgtGVv|M; zcn4yqTr3etGVqfyRO$BximEFE7;lB7NN4h@1`=RvMP-F=O~I-FwLmL8wa}U=E{fDd zj{G$NDZ+V^VoEDYe3!wx)`hl`^-R)ego=_o3MY?KCAU0E)}=LYVQAoAA8o9q%;w}( z#G6Q;o+^&d6y@QeofXn~6Uy*_^uYjIf-rU1!7+FZ4yw4x}ma*bJB z6R3i!VTk`!qtNlZ)Z~Dqy-XKh|Nd|^*cBbl|NKPvlf3b0GX?@>rRzeFSqrRBall7< zl4>coSdBnAITTMw7bk#u?*E%XiipMa*}udBZ>1If znre`!Z)}c6*6RLPU{=;tO9Cd`?i3I%KnE)K!EIUSj9Y6~6`)(uyc0vwLbKKiwqV*3 zYGL@&qMEYmh4~9)4!kIzBvMdCqx3=y6^(UHslX2SihZSUl^2?r+=t-8x)Z6rd?ia( zvinDNaftjJgUtgb85s znzf~jv()uXUlAOmK;@;aRn_PnB&BS4G``{*bQOP~ve;Kr1HvR`Jr)I9HbiL+IlN{{ zHat`+5`zf>9gQKgX+8X5nm1u>nyprWDHEvFn(JX**HRDcT7L!&?b%rpdSTI^dL=$? zAq-Z{m|i zAeZ|vUvc6ZDwhs(RFFUiwJ2M5T~&F}9eQ|QgBe7vSv#dqkg}mI0^ovYTJ&CCTEQyh z1{Ga47*vd=^tn)qR~933Fo;Dx77g`YRAXoaN9`OBMic zTDKAN{*+-VJF5f{4IowfifAq=Gky3q)yolOXjSiFimQnu2@^?{hFv7ZpSVj(Q;z2_ zfxj}}Qb=)`>hm+HtClWX?gGsMn*~V~Uzk*KGDZc(mF49%=o9E8un!2UH8q1q1vwiG zY7A{45TRmrkG_e}4jF;)+UAy~TA(g3s#@-=VuXt-VQv?i8=LAIbt;Bl!pGD(0x~lZ zI#G}8KdHLPY{sz>+QZNq=Dceqqo532+BN8eDIOlhMw05UgE}&MTDvI}v6?WFOxDpK zGCC9-3WrmIKCO<==L&>QL3GqXUt^MqYifkujH2Zc2N2g$)kgV|s_9ZZN%F_EeIa@& z?xY#;Ro4V6svz7*w55@qyX-9JVZNx?S|<$9nva#5yqMeG?bH1q4$H3uVB{u)gp=){IK zM7xzvFB`^@MHp_4IhlN79#9uD5w3lKNga?RIFodUtusVcMR*Qm=31A$NDVo|EGNS( zmBE3`8l0hEDO|-eDh8P_uM0L5YGJTimsXTk!)lgLk@by;^ZDZu6`f*a4TfZEh?b%Q(Cj$?<)AAHy2Cih;-sroZTXy3<*2JFBv3u6kd^Kx{Nudx#2zV~9!fEK4%?Rv~T`L8dp+Q&}xlQ$h zqp%7np@!lzETOn26X-$>O{g(?x-)SUw;RJP#|5Vd28u1Kfz=O)MUbuzql7puFCj2M z_YJu2hz6pUB96fAXHJ%SxJqF-5obgrYl&|egJ;+)shsY$V&(p|*BxwtFiZ)@Kq6Rw*(3`uv=Sp@gdsTMhD&ug&I(aF z>qx7nt}%;BO3dQQvYK*PgJ6#ewv_8XY=(fZqNp5^V9B&bjS(2$X(eFR@v_c@&E|YS zOmZ;G2-ek2$NCP%4Jd#8x+qq`3ZMoI;{Fy^RZ;GftPHGjwOlK;89W3@p@lc78ZR2T zkaVhRJ)tHX+z^^)P70f=nwn|A3Bv=CV8fbhBg-rdn!#wq3U978Q~uF}k`mzO>IE-E zS~l0$hB#MI3bOM;BNg1?^$5Nr2v7d9xdkLBatb;Ku+X|-QU*+_7E5)A96B`A1J;(z zFtQ*bF6ooQXjF@wl1=F3VRZJUDNLXa!IKISZt6cVL}D3uokl%MwVT+mg6k>s7U?W$;f zD1wEQ$&F3sCd{zVanMWg0@rp^b0jQfg@-4gR22rinU-J>Aym0|c_kFAwM31DNYy72 zVd)4FUQ-wShc(;;Z$xc(#sq=Tgxt`oGkvEwCcEEy(}MWXt)Qe3Z3`_vW0$q4Ni}Q2 z5Y|YHsVbuSAOf~*Q84VSpJo;=7iOYE2rwWRzLG^DmRpP=IM6X2NlP&}++JIUr>0dG zlVQ{YL#9%a$@?3$W#S+)`5&wkdx2WbVewM&w(8C5r}z2Ae%KEQ`4zakOl`5P>`QE zki`mOjMurQ31p+kwt`fjjGlx0u+oiTLbXfmNJdwUcSp@Yd)t5!$=>;g3E0HqMVsw> z6;GYLiF7<4+~>!fCSYta%+;TBDMeu+RJx%#8{l9nIMTF%Mi17A!sLKNJ{k?2=;@QF zPa|WoxoSaeusPDWXpISaj>4M+#F)u`oywCxDNL5wTn(SUk*4|!WHfCpTx2dFPh=61 z(1|cwG?mvT@;HRxzw*Fuet})SR@k~WbHRGj;zd+c9r$Ae;g9XFxDDKk;TB?ChOMe? zYKU&a?i;v%3cr9><)=#LYG`0uE-8UgvE_Q!0TYhWs5qHqE?T27sK?WINWK@BTp)5S zU|$L^YLSD>(-V$qOl^I#Rdjh8TZ*e6iqO=E)=|}BB2B~KsMR7N;xfy+6egmlH-hD| zyBbS5n5p8#nx$lLSyr8a$qG8NRy~w8n#^fM}U{&ja+D&!3d%$k1 zF{z2SXwWFVipP^s7~3>N0j1uge>70T*)&&MpeSUR7wWfUq{CM?MuJ-@jEZ1|x`HZ>tS(9}}cP>+2xtT1L>eHe@2a5083*z`%lrUFIah_tbQVOPSDIt+RR zx?}_qy(hssDWd{;n#{Sq#cZl zTrP_<3OEYy_BE2tIK;&m(so;PWkk7@E27X$)w|JRL3UtCPS>Q$m5s2*=gk|KFYx)=@__Hy_3*T;(VXv?-#%v{J2WUd_ep5gM7Uv~*hLG;J)@!WaD=eS4D=%RG`0G?6 z)A@$RcuX*?H#Fcr26(Lz6R8&9=5_@LXu$Of5Yd3J0_@d*bqesh23(>5BPS`Mixpt9 z2259g3Jo}00k&zti3;#t4d|cGVzPdw0SN{8Km-0D00^?npBJ!}oU2OT%kUhlRRbPU zIe)DIcR4xH1SbUS)_0vII5l5UX;oB~YrvI?%61L7+)X7rV9!ocxliNFR#f5|FiBCl zaIz|Almb{9kgfpRG~l1}L=r#NfIkaBG{_sU_xz8;{+k+S595dijbaTNmDHfAQ&i!1 zC@j{+oPZrpQre_(!h&Pns{!kzcaESusPE}+V3n12pQ^#Xj&7NOOb;#Igplf{a zPwpBA_w`^tLVm9=$4`w29sa?CoJ4)9pK?dX^E5@J{_v|>!|ks~35mL%E?>Xje)tKM z66^CsPGitrNl;oOE#U<)F&{oOXti%W&xoGwrd*Yzyg(>3jSIfPWM}p!Jn+}MXRG;> zU0ukvL6-$Jzs#hLL>%V6Tt>+`2lr(c7h#i88K(Ofxeza)a7wn3T^wwrqrE(_uMJ}N zQG>>qmrZlD*g`WMNA{vQm@dq%;i9@{e}`axyYx${n2z2^p0#@#tk(JgZvI4mkM%sg zuaI|@Ve1_ZUkfGS;6B-yOTGo|_-fv;R*&TK4QUha0bgJBbZX5$uA&|In9A@b8zyHb znYzTxp2W27*^ol4*9**k!tU~C1nl68RBR55@o!&a79hs7?%4ASHr-0Ug3~`!+-|kxKPdmkyg{Jq_SOOFhH(<0TrKjflSI}R>QBy zS1S{lR5)|?w3)NRL~v5!`Lm{-KP!w!qs5?Qko2F?FpDJ^e0`xibMD#cWMq2db3gjd7zevA?6AQmyCFZMyl{ zZ|{bMq}YXLMiO?vz;5(?ykK4AiUsSojaX0>S(K<=0GDt6oj1%By*y`^BU zyI{W+n5s7!Mce#9TZ|4Hf{E>+PuR4bFhT?I({U6Tc7v1r_MD$88`as-$GG%qZ1Aa)2?(rK2)(ukQhtl+(GlJL7gz55Il! zDB-ZDcKlQ&gRa|&Oy}({;IpfnKD$SCGu3V?wv$1U(3x?v&~!NMx}6!sS$NIet7kIZ zA*FBHtx5+!T%fM3km$-t^V<)>zk-+s7$JTx+L^{%)yDR%+{VYLb!Os1#wGb5zXVpS zf8bO)Miwb0@pu=@*l#zV#Ei#Bq6^a?1aIO_Jy!ayk0ALjZaKgG-I;`$W98vn!)|7n z*Q#;Bu2C>I-g<$#Ye9PLx1$ep^*Vd!a_w8a@l{X^)M=w?UZ)+;VaFtg{Qa-HO3Pu& z81e@-`>|bG@Ya1U^jA?KRAOV=AoO2o^v;f>U~FUhp!9o_=|_-mJ<2o*)o-5+Cl&42 z+1t?@ozc}n>FskO(X5@10Vy%Ed-l#fc<@{MTzu3BABjt>XIzvHh$b+lv#nnvB_)%o zGMx$eST77tO_NmXRaY^8hgD6g)(!ARQkw5MN!Gg7`ekm6*d8|6ku!8Fm(3cfR%!*%W$*l{T&7x#;^wF z&~Qi3e*1AmuOVhN1Pbh41(VT9U|&`+8IuIoreI^{Ch65H*i09!MqsK)HWJ@`#~FQG zLqs%NMxP64Tv0>7?jNg;+sT7=Y!46Pxi{PCY)3deutmn5SAW6kL!*UjNQ zdBwoRdei*YMptSz)Rl5HxM26|98~;}91~QIMpur_l7nU4#TM0XQBx?ZYF*{Ry@+wg zrtmmhmq=sgkP;t6lMm)GL+2Ql$7@v%H;>O_+KnzYwDJG^Kx*S>B-V*vkVNgB%Db=px;>SvBCSobozff2^P7^%@RUBOXOr2xc>Tgpy+|~cBc&=KN z+q<~Zu{|_=!Ijh6;^$FCZ2#8R2nV)5QP`81N`5FA3BO$;d0l3Gvk(`J@MnxCjtLLa*>SAGV|9X`c`G}3E!z{AkJwKo#xDBrLLxtUCsL=P>f7pUGvbvQ&j!_Z=hhf zN}aZvOL_kYigW!NgiKvkt}w3BA-axNg@z*2EsG+0btWe z&a^S<*%~3Pj7hU;f<0+=Jw6p1wX>YYP7R_cP2qrwS&QAEV2UT^X8lm6>Zc)T5LXNf zZFMwb){y3Rmt9J8{&`ec1CKO;$BV(S3d}lufMQ$@WZRZ`&Rg!2c{g4c&&a_2V%PUZCb;1N+x|S;qR!r~nw<38$p_exHo#;P z-_p*~-bG30<|gLKYaMgJwkp_}pG)G^DcEus%r7u7;Mcy_LWQ>4g*HXOu5iIlQ?Q5& z=25U77wm6id7!Z#aKU~rFt_h@?q40>i+qUK9{M!2@AUvK9n=2!;`@|*2KipAffH-X z!=!&Zw}mXyTqR!ErMq>jb{t~z^l3z@y7-m6u;qijunUzJMwov4<^rw;yf9xLl@fvf zMQVkiRn~4+zQV%;t=;62^F=bXeuheS`SSdBE!I+K)Ot<>0u1n4=3<3WqyP@a3<0>* zOHD;Tcdrt_T-J)#5%Ejln)Z-$#U7&;)IWG6=Q-n5x|EmM>*X0>3hq9Qs~k1V08`TM z*6Dux@ac{y$<5lBF$i^Q67|s}DvgyJGY6rTYg9Gw95E=pFquvRv+|$1J08G`-`+Bs zo5b2im1F-Bu^G`Uo-*shw zbWnB@3bN;R_@IW`Hax%?WHQt&%vrl#u+<9Ywgbxr=C%W$RcLNIFkZo4c9A<#!QOSj z-seb`mwdt$En4$mq`9P#+S)uPm~KmO=3g93z;UKM^y$O^zl#|b=FnM1$(HTXG^9a} z=pdJF0jwW^5u)O^U;ciQ13?dt;hw3QM74u;D(G{^{jYJHY@JO2rDSJ|TCkFxWu1c* zD_`SZBlz*V(E8xht($L&q$peD>=X@rHklHgLF*l{J=9+YA}5HG8SCv&q|HR^r%)Gj zsuYu0K)4*RxK=x@NuEPJoD)CD_o3U?68t#2<0%&l*~P-t#_dq}~WUF7amu$x@4P6hjc z3l>s9&$CE7P5xxT;47xu*~5F4MlJmDPGl(>|SP=U@&p1bu)9Mz;5_ zX!Ha}W)b(~hK)j}dUQ>1x|VAi+r!=wExAGw*7Beu6P_D*HI61cGkCpD4L{YAkH@#a zq8tfjT_*)Oa~|bRI@cK0VY5X`y=)3hbu3dSApDksEK7FU1$Mkso{F$1Y&dB&*H}o7 zsWYFUNt1Y-eB)3~4Cm(AXz%;NVQd)6m)`lRvS_O6l{l_1(o# zKAmiEy_;%oQii!nRS)`6aynpM-y2O&Wc6S&lK2b7m1T0WKu=EcP9$3j@1k?aAs(8IkO`Cd$x<~xAxM&iwxug^ja6}(ZyJNKSP(<)D_Z``(tD)ExRi5?mNlisa*ek0*_84(Ij7Is>H`t;@<9J z4^lmcmM1cLx{Jq=XpN2I6xOYp1g)`kcRT{(e*1Y|S%RncTf7?9br&ZG$(IG+`nC&p zK*64I!5$Wv;$9E2cPh-cT$r5-_IDR7s$gTwk|hTPrg+p8FIJdtiWe%_Ojqu6bZ+)7 zIbz=YiZi12qn;`buGee#V_MQZJKjZKShI1<;CI<9c5AhZ{yqi!f(!Ozfk`WhPy0=s z6;ml)g&hiZhbwDDU~UKC=PwV-?r9R>A0vFmUnUom)^w;!e*2K#3)9h?`=y^zfL|qC zyoI}k_JiEj>&uer?RD|NO`-RJYfWrt8+U`M7mEQ!z8XJSl&#f_=^fJLY8>xa;<30aj4QuG`e#e^R@(V{R8;h7VV}Ex?um9tWu1&O@4Rx5pyKty`U9CbJ^h zZhi%u?1C*2n7eLM6q>tkrzzNSS5}X}+;yvXY1q1*BszHyOmw1=V(HS?>TYxDwe3<3 zd_9~}r!B4mdq%K;-37k-yI~8=;sO)1lV#l`WNCJ|Q5zC6YTX_0algL}>J)owEbrs% zy7NK64(>xt(URZ}HmfXCvkn5-jd{dLhE>g>AEY8k1Aw;^!%+h9{7GSIKaNTEQG3xA zz*|;eE$(j|Bk^)Z>lih2hnE*YzseNh&SP667m8hw-#l3qii`Y^hcoPi>{sV}`1l*| z(8mplp%9LGZVGO#--JjoRtONMo`#KBIIl<7u;N5%Fk()^!A!Mx&l+EWUz>UQZIQpP zpPJt?0RwrzouhfdBLArjnf*7$gmj8YFMa))SL)h9*A!HmQ(kJr- zCyXuc*~XYOtD}fW1O1|^mAESb*O}0roH)cm`{`wOr6P+1Aa#J&<%4y;Ey!uF65en& zs;hi#XZdbyIJ*&_l9HEkKVA0NV`%dx;p2AMrJo3e8hs}rA zOV5B}^M?88OqGzfNwg1v4(b}h#uVWR9R|u3k1HEbd+FcNJ9T1xBXe&kLP}RghjF>b z7&tr@`)DTO&%|3bz8}P2&g$eJ3XE-?h>ci}p_k&NyX`6Tv;F;#=ivRFdk^@YmR_FI z<)0Yn_C4jdr!IAv?v1te8j+msZM}pPNl%>Iqqy6H?%RU{c(k{5zu}=$c!w+Phs7%S zbrSw+Z~L1OIhi3xC03Ql zJwu9N8hCwy-L{OlDP{+J#Sv~YglFQBcQ&8N#}l5G{ZYra0D4$u73j`9-FU zsD>bB787EQrvBL;wvaPvRiynIY{fo_A8-sKb0=!Ujy}=twhxWy2@v9qH6QHA8}NCtks$sK+z4qe=>Nferh${U z80i|>GjOhDqqC-_kxx;reA?ffUtO7RZo)k&II@cE-GV!5s0^IFUr%?N$ej;zmjqCGf5rAAFQ7TCr@5WUi<^UBCv+3>SD2CgJ}kHR zObEgnwU+!}NsZu;7ddIzTXg}@V|(b+K*6JdBwhad;?r_wPke*u6l*DG@k8nS_8Z)t zpqY8;zER!&f&FQQH4P*-!UiUbn88KRrx88Nn&}j=G^Gf*PKLD-iCrCp>bHOUkzx|g zS2pY~EO^3)c=Hu5oF5OtF%sjUBSOLoI%WNVJ!WtUS-|+4=qkA#Una?sT)=PeLq{Y9 z%rAZ7OpPXWmqY4HZc+&dVk|ZT5jGx2VcyIvp`@`%nW!>8`oO7CWURH%p}0`od13D0 zKED6RFgf6gL!0%D2Hl`9$2XyYyhj9n7(#;3K3pwA)@6%Tj~gS{#cRI0zznstAQ(rx zNX*HT>ZVLHs-k=e^m^>PAg8anK2!${Vi#~d?&aV&rBC#WSlt~bkTc%haUs>q%B1G+ zC?L>Av%4dQ9@w6KfxVnF+xHMUBw9y}xIdWGv|nP80h*@rX#G1R(Dpq<9&5_hGp;NT zOJZU)+WI9I{2Qs6#_@Js#g+XB_Pkl6Gr&sXEZMuRlb=XUj_n~NBU=2Ou_JI$NIvad ztO8_rHDe=pl0qV;Mmp!WUI#bQJGz+OsKgf1HKL`nz^do|bgw`6Ns*kYFm;yhj&#Da zFW_TiV^uc$ZSJV#`LI87Zu=fWGjLw%^mVZP`^C#loYZ5@p!c83`@wxMYI29xPy!3;kfJDHNsF1RRDpZSMFO0WOm_7 zN1&I|>8#O^v|;j6U^t1(TUmHtkgn38EYs-PESkGz8w(fFW*C}O()qI35$s9u8qu*< zqE@%e+i5fqd*h>^#qce14BBUs*S>YS5&4Yu8R(}p;4c;0-$=7*KG2odS<^3@BFRyh zCCbK&mRV4B`0R-rIIsvkpf<-f#N8OEU)#D z$aAbm9qBeO#0!7%K3=yY|0#Z*!G4Lz`ZPMB$F+NK1&fowa2f3vUv*x=#K^V$hAwI6 zh)+gGI&gk;^lK`C1hK@l{*1B}kH5V_=ds>YP$K+I4jbeh+&4Y4sd+m6*xj^A4R!RV z{K;yPhJEib$?bcPREy>-X#1V}eLpthf2Rt}wrk#|Z@1r`Cna>3 z@9r$$$&hxATV%xA9>f8iA0WF$Q7y}p4MLRTkPIap>%bAtf#@j=?)WS7fI>ZqNSE)y zbj;NJ1MTy&BPXl1YcP5fGYU0(5KTzU2u&#wPZ0+zd=EyZGOf8ni<8U6z%l$y3EXfQ z8B{&SI8QJVBgiNFG3F;fHX_&2F=)@Q?p>oeQXq}0tS6n4Sy3*mBW_xcz@A#`zr3dtaTGZh0gUtT6gwIsQg zEPyJ$2Lq+*D30?ZxVUBo7bt-DE%gzLuB3AOUb5xk5H6N;uH%y1a3mf!iY!TPM-FLe zMLleS_-Ig&fifI(g;v9g@{4k-&S z_eC# zy39wJI_;@DLa`R|;{T=eN5-MvJeHvw9ZweawQ`=E$F;MP^(jt*b35(_odgx?IW8UR zH!O)G7^~P~U`{)XR&-UTWdy80YSa~iYW+h4Fv}w;951gop!R>DnA25WKIh~EAWQO6 zOWJUlupfx7mB4NeqgJCdhcz#zRW&FJBzd2{(M2y>TQC^lL%y6>|xy8)6 zvkC?QGhY78GOEzqaRV0J#3Wr^yIDwQ7t*K;s%_9&*xIi40nm?a$s_jIXJt8i@9|Rr z>Ix@7u{UI`%Ysb~(%$ANL)QIiCXv$D8%tb5FB_$caG`vXE#B*q zZyNG@JYXT8OeW<(3>j`EJ%Qn2N>p1^h7^M>{K<{@y2eBX7x2~@b?dcgk`h2Ma;*+a zrrFsj0=T}Yic-Q+{31ZhWJqKV^Ea6>VTk!{O2N#6nHR9E9NSE}j)zW_OF`7+2Q@)6 zHvx#BFT`EVL)3@G9=5?uYB7rGo6Wp|gt$(gjmYB4VAX)Zy0Lh(5nW{12v)VPX;Ryn&MqMU>2kld z$Sz5<+)21w-*TnRNJ-;6l-x}^tP~;h3uYc)`G<&d2D72IEtwHqbL%|gm;so_tKRlw zHfi-8EcY4QOGtvqk+N%u<>BlVa-%6(OB2n)PdIXB#wQV>-5@u#T1pB_h?3L+2FjHb zIX9Z@1IkK5p|h$X^7H4-oW=LrvcQfcdoRk4eXgE1Kf}5$u^eH95tcr?J)l!7X zY5KN|hWz1$A#xh3g4Csksk*yLNy6 zwPp)_RLh>aD=XJvOMvD+zV31-mrF#l@T||W%+MU`0{B{wwbQ1;Ksz0n^3FG?Y8s1m zr4Dh~774fx30`nei#b+zqBr2u*Db*o`dv-(d^uQv^Io_%9Dyr!(;4}`>KZ#N7q+S) zF?l&I&LZI=JBr$JG&bA79dEd+N?KlBUZyU? zjp8SC)Rl7hHBcDCU`w5eAKZk)%~$k>TI3ehW?b-$su=2~FSJ}JBDbW4>Tp%$^t#aI z=`gH@x)^NuE6t46TmCiw&Rt}3LZ~G~E5f)~hcCuf`|)mCj1xj~8yEYwcfYBe7{C4C z^U8xcf|SLWW5T(*{w=kziRY~v6$X? zHczzPWk2Z1V!!?DU#NI^+1O#$Rer?to6hn+EEAAF&QlSM>bFnjB^S)p?O2;_L=bd2 zlJ2u@<=vb4V-&vWjV8ua<0-8U? z$|bZblW6qLXcs2YqNgVSqcud#|8BLp6UDES`K48Yr9{rKiy4)P<#_8f(2?oN={&RW z#+MRfv*Q=3eCJZZ|NJx8fMQYf&UBvSJ|+B}Wlh)MRY~%>9bcp_fxZM72@5mTD^%wI zhd+Ovh@wXwj

&BG^B1G~IWYdeliy9&C?y`V*!4?K4y^$oXh`&0+3OZ%Eet6gr~n zzab)6z$f2w;@eR80pDTap)bh;T5X}`;f+|^8_Yvry6+8#2hQW>fl~eU9o!BOA?B6o zHE%EvhoJ>Xba*%n9#Fu}xTw_8JP|Xw=F4Rr> z0t<;-I=AB+(2M;YhyQ^U1Zy5Jy7?LB8<7Rb9WK~83ig-_mMbt; zn)%iXu9W}z6YC8LP8a@~fULJ%Xunplzq(+%6wJ-|eG2xr3-1;Mb2EOef@L)&E4@*{ z&UV382y7U}7f6bm@hOUcoAJ{W>_Qh&kHGYnIubwh3yZP7_Yjli&9`IYGrWlIq*;~7 z$365+R#R@b=on}t4X?0rzdt0F!2|Rj;0HAR5$@%xoiCPl{u8xxjc|fz=;I$*`c{hz zRx7aBLcYjz+ZgL6SK?AhOq|wZ?R9~t56+WtC7zPZV>Yw6x$F-)a__a4yI^lASe*;@ zTLtTI!G0z%)hv&>Qtp)$)ht}lEsB6@7KUA`V83)_-6$}pSqRZ-mLKxw)3NcdjSx8> zMMiFy>shr`yC82pZOuW$cps*Q$%|XafOdID<5wr~b34w+;Qsd zSFl%IuyG3Zu?u#Bf=y~k*6BSCd3mk*F4*e|R^x&_Cot9C4X%_&B}KJ2SLVBlfNF1s z-K=2BelYAB1>5E#w_d@%>VgFn>>(Fyk%GAeKUH8_@S`oa;7^pq#HbXxzxM~}f6ux| zzph{z;iR0NQ?ThS*b@qNu?zM+1zYEW-72tQWOucsxMjCq5pc^cpkQv_#itA6!J!1m@ToQbxzl_+BKlF*ZIkP3%lYMB9JvK1n-M zrR>aIKN34b+c02fMr!;ctZ*9NvvHlmZ&vt+FeCs!TjTFe!8bNW6#im`f0y8&sPS(~ z;^%h2ryxJ#XJp6nfPtYL&whK%OQPRXT(EQn^SfaG_?_Tg;ex%aV4GdA0}9sVf;}uS z)ka@;rF>0NR2wlvUsMEC8!@a!U`~4w&}olHe=F_r9n=u}1Nw~U=|I%NJm-fZ{1{Tn zx0MASc#0FGjmh7S7P>P0^8wDl@KYF$-9;EJ{vhzgLK?$=fI9HlGMRgdZbQJ-jj_vj z6O|mb9~Rl0?jb-%{89`y;G-K$0a%#CA6TjUGb6|6OB&B|HpUiC9*eOja?*F`8}~Lm zNew{z5iyVc&5Qg(i`IYK%a3;xmdX?TjBI+$eTI`T5qkS0exiL5eSSsI!;25zgsF3l zv3`VV$?T-{&y>L%zdsY~c051=SK0Ps;*AvbR`TCmt?rJkE|j|krL#BIHxL=myLuFQ zrjVuOah`=l$6)WHN(;(tFaB8+iL<@m1i`r-hwvGlg$CfgG-CzTdd1=M1sSWmXsWW6 z`(H-<7{o>ZkuPLl1&U}4MygUs&jAVTfVon36q7`{?tBD<)9J&^1kWq*Ow*DIZsm0^ zu=uD#p3U%5a7k6$ToWa+2 z+dFqNWtv0T5#6Y2N}C7G93w61`z52HCG-1L29d}pMaarQE$ofFpze+TGaZ$~`WgBH z*7`Afo(N_QJ~Kl4cEX^7CMM_3uN>3`J^3L&v5ZhA_6mFxR7rn8(Qkj7b=Didfr{G9 z0>u2g5L}1?%@+?kzCqIErbQ||O%iCQB1tZ`hdyy3HBq)Maq@r2E@@6YU-EY`apMDqu3!dxG$K=?mPycJ$(onvqD@zc|~7{~D;&A5fQ(_puVk zpCAxyM3>H=E&0c|@^3^Aw9oz}ImZ6QCr~l`=Jo7foJEErwRwNPi-l;Bj@h^UmR}@f zu_O=3tkkJZ_&texCCZq$RBByrYD+&2wUt6G{$~sgJx<%@k0wUE@m~STZ3m4s)!z0z z+(#?30S0W$w%-<~JANn8KvR8aIq(0{y;H>C4 zfA8Zb)He>vIlP^2{SDlR&fdVb!5e>A(vv@SP$3Cqwm5JR#j13Qww5zOPNG$UArRs_ zl7-%7H^OU4fc}q8sSeS1I(B${K_X_ykGBvs{OuqU`CIi?eJye6B`ZQ!rz~;+2|c3 zTF6_0>88(5}c-ybRv52$> zJv)4VX>a=rHord#>Z~57RuAk0i#(>P%-7!DH%Ao&S^ioc_wi;j`P!Nj_`MIGh_}JyNXQUmiT-3JSztuRY1*R+kvF)AIhlhNz!;_4 z7K!9goWj(8{s>cx(pQkBGd>n6$er#x)IMi*^lEC_XjlMrCgVAIgc5c6 zUZBRAuNvu`^03&=^$CjWy5V1Wb8nVH& zE;VmX&8yKY%Eot2#K%av?8rIgP9>u)WIXNjrbn|?FC6e4ivNW=5$vbPYC6scBr&Jr zoT#c%AK~sw!7YqpKdD2tFfxwMUTHd|uC(bmUpE(R4I6`ljacI#B&9BVzA=maaoQw= z1nSy2W@W@FF39~G9hnr2q%8F%^ARsVGB>PK&wO$&g@FmUPoKvL$+e^A)p$P?B-Zv4 z%ma*}qaE{eJANjb!(#T_n6|?Q^-%SKAygWIe#hN-Qc^>H#|~psLk`Hhl&iGn4uNTX zmXVJ2`F%bZrS;h<@kZZsJFpj;*zR8Lfhwu;@!KZQ)YWwM^M%Fjb2daXV!jvBs2e2C zO}5|UXy$z32Q47A@j~m#eH^TQq-#h;y>5Xl;v|q_Ox>*&~ zNP3TF{9$yy^EDow$=1-iq$i4FUL=tyj6EB2ruX`TLa$Kh0WnSW`-3XwL^K<80cAg? zAQ;1_ovAeY9dTMZal-8dzx}3qqhV|N2XqE`^ISQD{CSu%F*VP!GnixTa3D`G1nq({ zs-%p>3X&0b^~KcBRAWv|HfHwI#CWnXKj5Ohd@fYA<*x+9bU&2KqiKOQdf_mwd&X04 zYc+J#WBcWOpZ5BZs}OeyUhTZPd7<_5md6|MXqTZyLMMt|AuI&#>vN`1xcU8dGPlL$Vh*9NJWmpM7lN zqugr0gzTUIF*hrX8jXR7z=LGZzN?)R?(_x^taU*~;Vmyhpb z_{#u|JVmEu5WP9-{qy*?@YjmJ9SYWi@4N8VtKNzJ)A)n@jrbX;G3*-sUxN$@ZD9?W1Up;!xrqYha_eq+fH#bS|5IeF^ zF;D#4E*u>0iQ|~P(EF7q9@Ec%H{i(57CNj&StGf56LqSrV~NX2ml7Vj2X{XvI`msK z`+a}&B$m+k(?(*R&Tl^iwv=|gkT{2V|A$A;#XjSaF_BMiUv-1b+Kl)voVNoWMwjz4 zk3lwcHfPLt=qdR#B{eztfe{F#z3mAjf{~{G9B5s8+dqs*Nq5Ifa3THO9Sbmh@Y^ee z_f#m^YO>DyRFa*05^;$$N1eXj#DpG68-$ZMF^R(`{436Ls)m!v=xv??1t69ysSv9W ze93^cfZci+bRZtnIo;0j87_ov6POaZUTK`4Xq@W3n+_Cll~3n(3EsvsqnPIeg+}w9 zgb}T4rxECiSlezRdKpETqX8=bR_x2AXIo#SmvZ&;D|%V1Uj9ih=c|_yU%|_{^1}7` z905*afOlht)k3c$WB}y&@Myjn!nzi4X7O6S+b75BCd41&sFKo!`(thQWA;jx>wxbr zeB$dK`s(uC@3%90l_2>X)Jd?Rk_{8(yE>l7Z|o>U>lTph^4*2saFM7pZmgxZ2%9w7 zVX}%LKY=&LG`jtn0eklYE{gYbJRgB{@A6xBGPQgBcC}FBy1>3-rU4N@%&VzrKp>n7 z`wVhSdZawFl(XC09;W-DH`4h1Fn+fgUAfbD7Y?bR1ni|aFNKZIDmHv~QKBjy?7zr? z_#9RIT~ho7x_BVm_B}2>aWVP{wQ*#s_BD1ha(Bn?s1Mi=JfYl;ZhG%5eix&KC;sr4c+o#NmN zALMr>ECaCaj{ZM^8TJ-O7889cu%i#a_C1ueI(kO?o{#V_EqY4(o{#ZhM6>8<2G@@~ zAVtD{kb}PXg$K%vT}fkbncPSUsb?c*k6-#5gZlBA4&*_cu2j$y859eO*9|DU0*~q& z?AD?E;K8o-ah*whomv6^;65LDKk$Lpua zJ1(?AJZR!aO6!~O6YPz6<{%Mr)<^I|d+TxRbkQR044tO@gi(+Y{lXZodfD&$Sj0Dx zLygwPZ=u&bagg})3gjk&d|x04P2k#&k@2N8kU-yXqIR5MJw;eCS3di{(9@u>`+Xn5 z0q92|{YE4+PM%12H?=`$H;EKKV}ws?wAdbc@?2ZGzvBpjD7;|5nXV*-JDmZH?V-=? z$cgeWfVou`>_2Dl+{j-$eEo?2XR!ZqHu?ZJ+>N(WKHO!%Zv)*_QsQPs1o8c+!9BN3 zd3pBriI)Tb~XH2K|0nWCCZ@s#3#?Lt+9@?T=CIkBoT60PBGA@6q^Q6aw*w z&_Ae;0#sS7YMH7JU3c2xlkbTFT5Kz>hq(|B+qY)$RWaw`xqa&tBZ51W5K_YBEdOA8 zo1Hc1|IWs!%iT1H=Tv;B5c^=Xlox#5x`?4gc*ekZE+OKlZ3w7ft z9cl6Y#Zx@EH&)~L?H_3iC@5UQEka1pNy1bKI#P=c@vcmWk~|?_*OCnQdZ;muJk$Q* zd8XkHhQnK$T5#Kg0sme6T)Lp`(iK+Acc610GG}r}(8fAYgAL+vCJYFk3nW~ha=ZJr z>Nj%IeO`3{bfH|BC1>>IV!#bTL|q1Ezaio8&ffOjlLtP64n{Nab5yub@)vYxGTk?3 zTx-f5V-DG9t{XtNIJ6PRrNVJ{$34ger@*fJKDR^n9=aU9`%wb-KYju_$~*VQ?xm~3 z-qX0`DPP3cIm|It7@~YaeC}?(e%_BJH0+6j#mSQu?|dzqX4a8`J_I|A3~Du95y|15 zN=-kF3>4X<3wBc+{hddlAKjt8RaeMwx3bRUvCi4RyrzcF zMuHEzZ)KpoKk*0lClSd+XiB}OV{b@fVM(I;(<*T3~y=x=I?7@xi1{8>o!R|cw$W&$|L%W;Pp zQkG-hZdml}q*S2SBBi9Lx@bvJmCvYKNBuaNuDdhQEvl-z6bBj%eLX@Fi~2t>YN~tz zgiG=4&@YNcESkX^NG__WUS7S@?=ylL$SWjk8|pXJ6MKAT+uE|y^3rN!L+Gj|fR_0# zsWe*FB398z(h2y>iXfa?R6%}z1h8UMsBy3UhlD}^TAS_8U$e4ZZ5QagXDRXx3D zW^ZS@l|lG79~XZ|Dt>W>^_P2)Va+fZ@@TEizSPNp`{O%{z1CBNUwB;n{8aoLYXLFz z(OE+)AoSnE(vs?{L_g2EmhhiFF8+a3{885D3IERH;@^>qKi1v_RLB>5IkHsAT{Zok zOC|$`zRXumNn36|V&st@U>t?Xwr;0lmVAb?cy~_342kY!Tnd#hn`inj!LgINb!AN( z>Ki9dnP(<%mZ`(Zbo`8bBTk8%erVhV92(&ZJE(_@*LNr8VJ+`HtW%#nSZ{s`SBUl# z;Q9pE5-$ZjXC(}44Dqrb%UUcr=maYSTmrP$_hf~GM(zI2G+h0{b6mgur4%?{=K(vz zG1U2}xAhS3@cXtcSYT6cxlg9u*h8*D`)i)-pQj6Lk_mqMS7#)p-E~o3dil{E9vodrd{@S9 zy1zr4X}VJhZ+^QgGnq$Ok#y=8YmVUBi`r&z(^$WC9>!AX{8u&1n?Bv3EddQYh^nY? z$&$%a%)&yPh-)lFE;Gn?OkrM!JErvQpES#JGO9bvVn@j3MNK$ADe@W7Z>{ zYhHf~q_Yvf97R|G`|~rSMJ~LVgYY1HBXI)c zjY0Mx2FxDI4{Uqtk5r@h`CTfXUUMv9ALS({E(o`lA%|pmUk86YzGE9d=fa=ClrRYz zB(KFR5Cl?LUT6fC*K}9TcbTLsrzs*Ek&+XVp`3{-)Is{--!F0cHaig1x1ndx=_+x7 zst;mrC4CT$i$3^+R2*t`oYgtzw>J*vMYZ}hDH$-u<63Buqse~G%_!|sg34ijkAKz` z+$2Ifpj88rlCvyJ8cX~fyM^Nc-ks#wBnlE^sn19*!(B2I2W3sVof{1o0<(WRsArhb z#w#1~!}TV08<{84#k_n4(X{Y1|1zv3O`B8)2aeaGbcYHz!AFjubICf?Jh{(p;iS53 z%8k1ZE;Fkb1vkSL`=^)sCv&8wuzpGkC7rtz_ab2FhI;d+V3-0oxDJ^P)AA2=*i?LAO$;YhBeE8T4op5ZzkJTQ7EH6czP2&aa6C@IoSUI}=7vxN=eHwG>#inY zsOk-&3BQCSfSJJX0vIGM5G8b?csxc1jhgP(PrF!Mq(c%?Lk@f zosK5C@;FIbueM3Ggy7PLBSY#EZFF*M!tKbx4Ol{pwvg;qsm?u)Wze@3RR=nDBiur& z2gSwxq*xSY4+DCd8P6LDV}X5O-H*ONG0R7HQe>usp1U8Mh&-K-K7!}24ua3^pyw?a zw4NXk=>{=Q%}D$neV26GqKt@nG8x>fBGYli1@Azbfk1=(aah@F3VHPnPjfzOwUTr@M$(S^9KA(B8Qm#_n47H zW>4a)WM91NyKX05)_3+00x?fFe_6!0*6UURN3%2X7`& zLHKJzIQKEm;J3@Qm|%g|chXhNMEpQIRU;2Ca!(dEdkMaEzmgXr`t1!Il%vr)QvhFN z@?faDIj!?yB7*Q4eu0np!rAbvxK=X0;F#?Nm?fUCZdY6l0<6jEx<%{pl$QDE=aifm zFT^0)L)Gsg;;5llBt{_r1p#|Xvnm3lsoEqaRIMuwA2IkXnLGaix|9-wvSjc4C*E*1 z^=4xy`ILSu{Xw@r+`y%dia$nE7X1Ev27V)66?8w35Il%Db@(cG4%A-Pp)Q5mTvdm9 zP{Z$Aaa-kfz<)5T9w6HP)1*Yu$(j?}LmEPNqTZH5=AXTU=8aF_dDO;?ZZ-*smWjf3 z`Mo3-md1NbaTHI-XDLCy0|iPE^v)FOw=wm+_)}2(10BzR14z{9<|h_g?;MdUgng(n zDQw-2w+$x$RtovgD)J$a?;$qPHs#&}+ZUiU>ED6t=IE#P3)B1!GY`3&^}(MJ-+A%Fph-+1c8TS}#*3ZWz?MFRG^Rh_r{o2V8WI1Y z%0hhKNDOxFAchIEyJH_~`9%vT1AHX5$vH@E-$NqNEb+(9*Sc%&qppr@}q`t;-HLAkUS>WKua7uHg4Vcsd-zHm7upd&y8 zX^B?hLG7oz30YA$;2}6fP0mjRD3G48e}1CMtDRHYdkL3tWMs5;eTo?3dk9l@CA|ot zqD0!$0U8@X3~%td3h*A=dV$d@_W(d?H;AF(Qt6Vnft^$|&lkJzeE`f+NEW{^9E>(Z za6?KpT`029oHT9rjBxTbpWpM*RvaH&OkPJbP{V4%!| z%XNR4<;O1iJ-pz$E0={4^Ywe|6w z*KE&?PQhX{f)7m1jKp{#mb2BQ}KotQ@f7Ts*Mt z9gv}r;23G>?3ywI6(7~-39WM9`4WALPzZ`V<*~uZ?$SG8V9(oSgmC0O6jFL(s4cIeXsVrEP zm!1RmsZJ{Tx;!7;cNxW*St#hLXW_wbeSJ5E#C3Ct4Jaf8{aUfZ5_M>)0y^|p?$huC ziX8+7QjA5L8J{#pvf$=+Ys&aVXmu z7J0~oad~_E>P#pzUnyjT8c1LLmM!no7o$p?)E{^QiTT4upYPj#$%1Kc8WbOG1vKt-5;7WHt6C!LWz`n+$%Ni{ku! zs1D5X5kH%hYEHQKFpl58N+{|$1luywJlge>7wgUN+pD;%i650MKMS=?WQyYGY$;;m z@62`t3E!Don)js&%w?w;f;DY46y zbddLr;BrJvgRxO05U32$a)i>(x^>h6%<_8qEus8{xY&_@{(yfcsJ_vmaNMj>+MI&* z3vf_}y{%33C8c4<%BRULF&kNlHc6qd-_-%t|KKYenBbxkkn9whmj zuTz?rWf*@Do;>!`LFKSdnZnm2;@ibPK9aI98yPWxeatWS01IQa!c9x8=BI_&D}p_R zcuvhjko^YkwAI8j6XUpDQ}OtmDX7zWFR%UL`A)%WpR+ImKMGs&9@XqO^5O_o3vsw5 z*KswaDsL*jQ%X$7efxv?(&fD(W$^kk>Yg9D2L1&$#B-f!KiCz+)Cr@hs*}3M897%+ zO{b2Lye?3vIdWt64*cfFkpZ8LpCTroa}e=S7yva9cH4f+f$eYYi=MnsPCm-Tb z(H-^~GpMa%zBkTHJWq9Dd}*ucKUb=@_b0@zwAEMIU98Uq>r`jle+73H_J)R>H#(Q( z#G@FdSYBw}TFH{iQf8bsWK($*meKPTeur0cJ~2x1iT7{_lj(N)Re5{#|8 zxVtnhcs>Z?A}>6jhf|Rf*TT1?WmHOs5FTWfd6pGDqr2k`Y{$d>HfvJ|)81NMs#SSf zU3sRQt|BqP z>hD^TlgNQ9erDoO_w0X72NNI2msZj#o@4*+TILq72Nvgmb2#3h^y?Jg6hvw5fZUcP zd4v2`ciN~=NE>_nv^4n0$1N}8|0C}0M4#&~7mRs$WUj5k@+v}}*TNSG!0h?&GieRr)s79ss z#7S*b3Q<$%`#fu(GcN({ZSNnyd_E_0&VE^Y?X}n5d+oK?Ui+)_O?Q4xoU2cqn)qZv zI(=l{xSO!f!a8rEbL;*E;9wY1a&IaPCp9&x{3U7m!Y{mM;Y^exPB5cSC|c*iA8ntxbQj>B285$H=;Yht@qtu=?uH|o@kjqvvJVQjC2 zY>4!Om|o!cb{uC1n9U`2iN}Qsw=hZG#?o(QdmN&lWuE@hr!4 z4W7w(M&f}zNoDnoVh3=eOuuHx)z@5odf@bFGj2q3Ka6uK&2&7i!Mm`Fm6yF%IJl@obByyVOkv z&d&Extc=S_9e#CUfeJqAE%j{45PgT}Jjq(U+Urqol$FxUUAh;;(N7fKFw2VlR(M*5 zm1eb@57eL_w*{|D2kUnLF7~n&K<&4!?>Y2xXSfW@PGFxNDuom)a4h6m;c*V63bCHy`gDh1J{U3ISjH8OEJ{`Md}DE9 z`PSYnfJkz5`euQI57qCxoG=X}#hkjWbh>8?PINl;^`3CsN-flDqK^GSXy+Kg0sq^L z!e^#6Oeh;87S4wVj9v|@eFE#z{FvMYYM%CT)Qbg;YVazT=3+5KE)G*dIk9~rAIMK~u zH8}~*B!ET&9?2F5j#Vi-S-mRQ!QA0mxWW z#A>LeS`Ju(XBikT^%*x(u?%&uUNWw_XSP(8xZ6oZ^Lk0RL!6Sgs7 zY$AUn^F!`bxhM~qwwPGZsXa_Nn>c<`;rL57;lyA)4ngt`JbFuBy>d-W9_&XF+n#W| z%yW`x;=&c?VF7M`UNq;TJj=ur4wBaeeKQi!xtk5=$6$fgSUE1}lWzJ~r?a-(Ws@1l z9DT{cFDhKY`(&4`OuK3p3_cR9OJ)n!rDtF_K+LMu^|%x;35Q|UJ+uyN#h3CUhwV1+>vr2{{I17u`5TZ=@RZ;=W`3_Zq{10zJ+17urF#W1 zSU)xRht9zk8tJB;lJQ+B;BIGcWN*oe2jE_!}rfmBnGA^EYbEO|K5%ikB})az%D$ zE92yR%VnzFcBZx4Pk!{jX}2VSgc3&J#d@7ONLYqdjc@?Zb|{+05%4~=qpepS%~rP*R@)H`Z!i`}F+$o^Vt z&tEBpSprB(??y(y@k8Mhhso6AMY9b8f-aiXu}r=(Wo#KDIDeZ%#9v_G0{i72OD5df zHOxml7}?2$zq(INPLyQD85<%8nLCf8|~qtPE*t?7r)9 zRFWzn+)dxw0lD$@2GUWqBCw@~?gy!z>P-2vWIF4Z`PIpwa8LP0*xNC=wy>Ko5Yk>( zlJk0}{eQGj7qkqem0cUNOubaMTE~PdyB)FPEo!eXfr#v;iB3e15F;1o-p;jS2$WzQC8r^!d{k>l?m1^(C&0lN>a8{si5j4cpwOz|P)XDs%Q>4E>p7bL?e z?}M6ADnp_v;XX6HK=&KRHk(4n^vJ19s7gTN`0j#OQ0|09xpM5obZK)v7*zTOcOzKZCoOf96hMqCUU{PP z7({g7&P9>P^pId|(H|c}3W~(A5u2t2%>^Ocyr#tBb&!I`Y*@AihFiYnt6>|rp5m>@ zzPKd@QVb4boFN+}6DYD%blaHzv6(D${MN3K;5=CcSW64Vy5>p)w?a-Y2cG64#2x9D zwoR^TaF5`(5)?x(qI{T4&-gA$OR zY8m-E;9=A6B|!UOZTAsIMwp~D!uO4tI6tZaOjedihtemH;Fyvu9`+WAa^@RP-Y#qx z%WdhLO~w#eR-ulriQ>cibF_oly2%Xh%h3+Bevzr|?naSYpW}bp!Zj@iIKNT+iOisZ zp>L)RPzSIc!l-EuLH{MkcF#NnNoCU{6ve;;F%puTem%kx{n1Dde~c;T3F0yzxKz>) z(75o)9x;%B1XD?I(rFh%c4q8|{1w0Gn`S&tjhb(|yp>k=!q-wS>aSTw>9Rq%eSzO)bI2<%+e)Ex!+j6?q8}# zcIQA~0N#_jCshJHdXz|Lt_%~KrZUxrQj;?z7hS<>v6fd-o!O>mDLR}E9~m+Qc`Eaz zNyE>vVV$9ivcj(p>yvTH1wHi)UdYLd_M%Z0PKdek4<$ zwT?@u8ZfY}P<;qKOeCixFfXk~JpO~!9`Wy8UoFgiMUN2wfV~DDhD4q!N-PAIHQc&xMK$i82`L?drC*n2JvWJQ-ct2L<2BXO zP5AJIwO0D4m~s6yDMa#sF2;phWxkV@?`B8B7h;}mZT zlefexdoqHT;@?IWR@%N!4twkeJ(=!pI^Ll^bZ-NtZJn@F7hjk7v30(I ze}Jdj7IzA>{4?u}+@XHkM=>F0319u!t9Z0_|dm=6qp_QqbVA~G9H1(kVdGs4J z*>@|v1>Ia13@)QtH}5^-thh}49MQNL+rLOrZyxJc=T)83jD|z0(-P+s%(E{r0&`F= zPiwGD=;cSVFBnG!5l3Lv+o{O@4&p3EeQ*uiLh6LHkE*n>`-rdd9A+H&i^>1!UDRt} zztOby72<3HmkWtOcxjQ0Sc#lWgUE|sxKu#|CbEM`)Y5QN=l7qGKAoy3rUcM;ZMb$Y zaaLoG+8K^rK!SYbDuOah${FBr7ni6a%^i!8kXxOhFvkTaw8H3~GVug+d4#SB zhpb!Fr1UBqU7azc<&{_fTCz4h1FBRHBNd!AdhD2UTkuZ2(6z6h68y)ea@7}cNz~l%ULZu6g*Fj!PSAjVa`(@0SEG#)FI6_ z)nn4PiQ}QvkSi=z!!3C+o8`YKy{=4S)|Ibmm4o*n)O?mz7~?IYQO_uJl%7obV0MM~ z{hb^0gXHzg=1F5i2|mNc+@l~_9;80I^F~!)>0jSKgJi-5fx`3$1RXx`ckN!19+|@X z|Bg&qI2TObKVhv4Q)mL)F!;|P`T3X1m|u}vn$*-U<8q{;jk=F@nV$5It-Q{m8l zf%;X`4kiWzLAEC|%efwmdFxivghj0!=J;0D@%TtEuzKAsR1?h^zn=8LPIjI#q}f9r>56rKl6cVmCi%WmeFIAKo&|(w?g)Lg z3NUaF5k;R$*9`iNt|J0^521*B!8N~s-YT3u?rZM0&bJX)h{_3>AXZ^Bai6PoWO>!P z$w^&pO?`b`{bXpIrxb32iJG~m3W*@IOdx{0N(lXa=S8Led3DigaRh1s3cyxrmy2mVK#Nw#573 zpS4f?V8&y;&m|$?K!M=HdjBXs)SS(H3%k>9-_|RK$(CGG3Mks;{T53aj1{M+4sV8Y zyC6?ieg(7z9&F}~O97V$aJLa0bVpap_=EeU&xpmDf(6|DLMJuxL5}Pk4RAQ3+L@1G zftVP7K1cXg2+8vLsq&O!^HM>U7W|JSg?HYWgp5rxr7F=cOO36jUv@;34O7NR<^70S zR9wpx5y?t5ol~r_P`{lEPc`pcx@fk0!aq(fp zo;dV}r~H9Gq;;f%y9B7!9Lbr)lrwwZ;kW>2ArQyCfMfabV-5T0gU3jlS@>}Yj5afS zy7=*99^{~)Pd$LJvVeaYaHa_OOHrp1$oWF;v1L#~> z(Dd1TU|@i^Y>574d!KT`ENqzU6AO|Huu)dS+fhSnmvgIcB~@wWnxLLHulmN1#YtD0 z?;zknmq1yto-&-rwiz-U40SxEeg|Z{g&3b*(A!=qTq%4|{~dtoRj)Bx?)6W?iB4Nj6t{qI-b~0Ly zya0@+k?3x-f8M;DBv}$XYFKhfpr927F`$`hu?Bg1M9YVb&Q2* zkN4NtSt;R>sK<1|a3ktP%RY1_uoljDi^KJ-n6imh-&-~otEi;KtsS?5V84m+2*mk~ zEE6`Ac9{!%d2M5F?9nvXAV)7+4R$RRR^Nx=j%8=V=^Hi1{*}~6W+eK52Hr0%64+cH zoYz9Qzm)ulc~r#+O=RtW#u8^krro#MR-gX`ZKY$~VXaNr=f1YBpiV?zNwyW>Hmv?O zm_XUlm~iKR1h^CaIk?WgaB+ciU*7sT;U4|spTgIb23M^eO*;{FpAu|`_UBu2{2Umu z&0pYC^$B;u>o*w8C1YhL4&5QVHYaf5Uu7B&@5}caA!!vg=a}i#eh1iG5(L*M2B_@D zDUxvOaPhmeZ^abCg-x z74>I?KOeavR}JIhue=MKZR!SZ5$>jj0!d{FX|A1B{cJNT=Td?O1RMBZKwLx|Pu)0jDJK10Zlol#LgZZnAf!co`&6YgZuc55zu3N4ioB4sap`imxnme5{pGe{4XtMja4XFzn5D z=~W(>l)3&WpWY08Mjrhd${Z_ewtoJ)h8(9gC2I)WEtQ5M`buN!e!2Q zaLhkO#gQj6iZvD`aa!HLjk`1A^e%ClpMq1an)Yc^_w{vGc!m0_^eOXIivI2YY?nKe zUClHenhJ9$v;TmukbYcx^Ca{eQ)^@DH|Buduq`Ulny9FDGSSX+cI3z9BsH>%NiwHh zPDp_VuwO%XewZg8Z{XMjvo@tU5z^E>)hADbgu>VPV6CiLuEeC6RWbjYp}ZAa@>#0hNH-LY(m8 znb#)B9Jv1hvP5dX?uorC_%g*7Q(m#=0Nh{FGfGZ~%f<0nvb&mayb;9h&6IL5w`0w5 zKq}yjjh1@O24VZAxNo&tMVIo**~V)$plHPYXpbh4@F^{wPl$ofPq3Li(#(IC4P!R5 z=&BafrSOZA|oiqQpIJTOmfv-iQ?3LPb%#( zzpN|*YmdDc1&hufBHd;%r?6WysXa>gmWIA^wnY`V8hp<7SILCYB^iQ1z6VyOwLjZ0 z6UMLR$$Ui?pJG-5fo1&$!B>&zZJENoAdkW~jXr{?$hXPi(>Rh8ZGxs=eY8b>2!HGp zDB~Nal1=b!DZ`T}WBs>g)dc6PgEJY}-1;a&aY@9paSfsMbf?2BvC;`QLQxLk=3WVH ziD9Ik5u~Mha7*WhGXIc9!Vls7u!ZrI3I{iud$kil8SpBtWKN@GwDL>8v1mmqCI6e0 z47X)ykMYI*6jKZvYw`yMO!rgW+9e77VxnB?6w=FmhN#hh#u>|n!20&`GnDI4<%+C( z-|7APFNxPpYa>anm?8zDRe0np(LvK#M(^(qb=)V8IsS zoGNzH>%Zj>{li8}au0cZ1eqO8X6;#6O_s|hE9d$aR0RjOjW(;dN~`=5L=w{*P*^BTt7r#15_A$3Y$Nre zFQLXQwXnjA(v$l3n@ntZ%-*sK8BV*9EH>rrlJL93_kdk(hdXj-?Cwb1iFOP@fN+F6 zG6IRI{Uy_}Mw8P3%1cU#dDixK(h)EWTCQ9|pOa+PChNM}ta>V5O2ehKCyUa=mBfS> zJlPJvr@cO6ZlnY5d9i2l#!CkjP3Q~uH0?IW0CkePZz8cy{wlKdO>CJUuUJ#pP_t4j zm0_a{FJf!pbIjUuUvul&yxau=XkuXBynNYm_~lz$1BbGb+=7sDR(9EPT-LW1r+07l zEw90$-5OpXqs+PiUl{C}og<6-b0^+6Y z!MX2h1`VxnHAR$wtQ`9#shSQFK`s2AZ#;TKf=>VsBF7IT>wQe8-OG0~KchIljWVP7 zj;Qv8{~0Wal}(bs`G>x01gG%?C|ihAUdyrBws8Mbd9Kh7Mu%l+OVL|RBM*gc%T+=M z^QbWW7G*m{5+%#%Lkd<-g6I+Hz(vBUiA~nVn(&nTY=_N(bEWXf zp+5SBsCWM!@~Q8Mus^TB7w#fqTEFq!O@xxtAAXV6j5o;Unn#A$&MKnGy}Tysm`M&H zedf|$MR)0)ofi?j&=r0lWI_dWEJZ}Wuj2mcy1x01K6PFCm38IbuT|H~*tOOf``-&c zeq}v3Y?K1jG!l?H$^>%eI>u&VJs3EeMyV2kz&+)pj|%Y@@|qfPBtqO+s6r@{=u5jf zX3Sg@Y6yJofRU2I>c0QK4*+R+V{0?jvmU%oFYDt^Pu3qE@=Xhu6v{$IZ;>SkWpXtw zTo8B;hJW}nr?A_vW4oBc2>iWbpNvKt*w-J154j8Awc(P4{on-q5PP3ohA7m3qCgs! zvE4l6javnNs50JDk41oudP2I^dEIzDSDoIl2AGq2}*7u{JplkA>+%Z|zZHG(us_vpH zF=uWfUn&>+yU6O+zKzOqX^R-ds{WUBu7xZj6e-^-SRwvGBx@RQDA{=Zw-zs3&AB_> z14-(nl}zyU6Fth7wl1d}3mF~$K}H0oXUMw7Y}H4;NyN=o{S>u8o}?hqv_z_<1cQB$ zmDIOb0*nO6Gl&PC)5HT&DW8_Qt@TR?6Ma)Zu}_H(`>+Am0q$W55FdUb>m4ONOiPY8 z&?%T>=T>3Plrd#RS}iY>Rk#{EV;-^X&WA1=bp_dRW^WJmIW6$53#S=2|Fl_fCBM-& zle;Ol!Z8;&z&+I>+9>DYGPS}6^R;XRPE6I;Of3ssGPSUwY#e^d#+hMxw$xZT28j6@ z-ZpA@N(;-7`nrt`zKi)Ldp4(Kx0MAUD`3UaFtu#OGV#X`mmavucS>OO&4HU7_&}`De-7eJoY?1 z&79rBfmzx{m$q?g5k}||4d14GhZhx?0CU8HmB}$Z%0Mvz=8G*j7(Np5f_q>V2n}(M zhJ*V~T4c{@xx4fz1Cd(~9kf3o2_#u*<&nl*_)KMF?csuKhQLnw|aNp2Z-H(R4wI?2C_UGh3(aEp{ z9a@jQokd~eBsW^|Wodh3UTjwBJB^OmG|a~@p>lFL*9SMVg4jIMFvHQrYgjw(as*}~ z8vIJ^BqjC*+GMA;2Cn&8Aa$|x7I8%d*aMZbFLkTR_s%zlUT(ohr|m$O%2!?Rt=U3Y zblPXtIro;%N)#)7fk?ZzO%y_##4WNuK-@)UsX_Q65GD$|EVVf@iZ}hfF7H_W`)*(f z-k49pB)3Vzz&looFGZB_baD*h*#zkccu()7nKA0v(t8i?2{ii!R9f=pHv&=~{K1m_ z{l>0&QbCSZnF|lvcM&+iltWS6G>8(2iM%mh<>Pi%R3wu;<4=N^6TPcQI&WNhE8Ly} zMjSNuNV+k`b1Gfz9W&p5nfcflAk<8=Rd{$G;}qNyh&~aH;R7F9H2C~_qUnkaMI9;h z;mSCtLj)@5o+QqLK?}WroDM~9_m-T_w}f5-9Hq>)N*ODnBUIkgX_65BHcS<=_RIn> ze_*x+Qdc0A-;f@EAZSI@D?IuPkeSL~1n@e7hx>R2o@023D@Bciet3B$!PO8**;Uk` ze#4JRDf~hS>H4^ZBK+7Z(%?F2=z=3C-FQq&hBu_1&Y>W0i}w;+iS`4YU)%{{gMr<3AttH#YD{CHx;!k>!vXU_7Bm8D9ucw^r< zbGnQyv*8LQ9d{Af{oy8*Bsqx3q8=&95~;dHSNRT3Y=vL&aS%A(r?s=hFTYw897k%a z4M_VG2%q*B2q0ptP3i-ERK;ZsgQtq)a_8`IoI_F}CSDffgeqj}y7!nl9s7yL(GiVCrXK|r|}!>9roN$tM_o@i?$$G05$&UO=ij$ zxS;tRyp~`PBwiTGnMAmRmyTOpvQvt2Mt^)SnC&{=XNB9!AXwV+5^`dweqD_vCKfh8 z!y~%Qtz8~4B6fLk3kZ(*c}oVEjr79NgoJ}#6yWszWI(q%G}K<{;@p+iBqzj|NkU8F zH}3r-;b4sR8y8ebt+Z{syKzdIjq!@I6AErf7;L~(NcWb^SWO?GS*EXq#NrR__dWqb z#fqJj(rvp4veB2aJVbdZDKwRWg+3xS7vBRP(4Nk{jSH02@=u`rP>bS9@(}8NSXx#p z;ZtiHnh5bSJY2enLVNY^MTh`4Ud$X1CUab@#4}Q0gzzD_fgBGTzr#zUWoZMl4fq5m z3iZKC87d+jEeCC`rC4rH3=x{= zbaKK^IYS}aVp*NrBuNV0Z+_RLyFW0=LbqB#x&*h&Eu!>TxTQ79$V7Hyps3EczB2Oq z;QnicBS*b@uu2+jK3HTCt+QOk@vfXuxwO>BM@+V5H_cJqG;5F9N70h6Tk-zD|eV-EmlES`oWv0WpPPF%0R z@<6%-zPO-{O^B*?`V~)_KA=Qrs`hWGfQKevP0gyHO|FQ?Lb`rxSrAvJ$|9T*Q_Ggi zx_>#A{lS$fkyx`+AHcA2$c3?8sSwDG)F1Fy?JwqI8BEhbPM&ClVM$VSr$zjS49r3! z9FXd^H4P-UCG20u(Y65R12!r78848iaXteVp4+Ln;>G8kJ77u;TF{n*-@J|59eDtO zZIvH^Lh5W)zSu~~=DYa3?AhtrvG5}kb`Td4el)Hr7ynB!?v8{l^haZZ7vO(o@Lc?_ z2@b}8U(k*JV}iMQ<><^xZ<`GZ=o1+Cm7mBSa+vaY2_{Fmf_3m>AkaLiQqDp&PpSzH z1c-4>{qVmOJmZo!OhA+Rxg)O%->X`4dgX+Rv)NCP?bzn99J_9&j1c1L(wnkq9j{jz zrLK%dT+7%um`l-01HJUJ2`Vqs1mUl`OwwZ+ za;a=BFV{+Qtooo)uxOZsa?v1n2}FoTUaVdUcvgxL zf{;$Pw1hNV9~}TI(X=}_Sd6jcCE1+L14Q5<4uMY z{c>oiVy&K1i?!amMcxFK^5Ci<7NT^tsJi@v7sHyyMu*!dQaNA(N94Ge8F^oojZk zM(G=`z(S-0i>i2K2N6l;6FfeEOn0Jl6NX-a1zuHkKxf1PM993j9XG7U=A=S#%4jsBWgCeZ9G0rngaBZnLeQq^XgT{&9No590tqSqN-D_)|}}n z(lE)}^DUIE)-9Xx1|)&TE|JSUv8n%y{7s4c;Y9w0D!)n9P=DYqE$4{gUICV1k@&bI z#9Fqub2lu_TP*U4!XdC70F73aB&HhfE(8gRpNI^Nh7)_(Xw4h4#!1edR^MHT4$WT5 zPHNfPSfv0YmP^tzuQN-LGplFdh09g^X}oZ@#R~-(e?1(3aS}2y{!$w%_GgMIFhZ#w zXQ~-6SeXowKHdiM&oyi5l3IE??~$RpPv+ES9i|w}g2&~68YfcPS6T{kmD%rd_OQV* z#wXitx5(cfGxOK9+i1ZH(rAw?m0_onJyIBzE%^>w(i(@*6;xY}L6wZZ34CV^+F^wr zTEOQIOt7kZp2VY3vEP+v+^tfZaud!V!z|N-3*u3MQE)rNJ;WYdRSbV34&^(+>leR9 z#sE+Y9XIw)>V2u)4Z!V3Ay@orSGWnbY9qop_&PwJ=?!=IFu{7o-Z*>5TRS}NCqIv8 z%ec0v+PH6q0MpvF9`515CRg1J&E0Ug<)zO&^Nwamt<$)9l-XY)=%2}@siZe;h#X*d zbT-Usz*cq+taIsT0qh3+@*5I?3%sPy7!RrM1U($J9^=%-Utb=u)clwUEjPn>Q?jSv zAmz_ZfK_W3Dphk>yNnp`)HQ7l70!(7CpCA(ve3r=O8i&B?t&f`o0ibf^;aeEf1U>9 z&3iY962q=^XtS9Xel=xN89s!Zr5-xt2GQE2?GY`Zeuo)60{s+3Hfaa;LmuUAGYoNu z1A$Jq*QO&U<5a<}gfChcKe#lc5Cl0Di8VwX5CKS`TN+H(g7ZEOHxVj?JppQB?rP_( zz;TRFnS?b=Kt(F2>5o{^1aYQ617^X9!d0a1!7W(kZ6ta|DxyGMA4p_V84$~9vqTr?rBTDtc7LKx0V#@cZ9!A|4e!uq_A!i7n9I6 zt7#FM22zeU(>3NwT3sblr(ZnSCr^5$Puz4ChWZ+wQWw$abhx*_tXe-Qgtg4QFvAvq z54?L5UIKWw;d#J(to2P`>IIyMAXCp&E8RU1sN%}LA+XMhyErv&D@s!9Wbl~Wu{;!a zEdS6-`(?E>nZSuHVS^(T9yH(Cm^Va!7ukn!>za~bSMi}8I-{Z!fAGsf(GSd37A5X8{kEyI=RPwoUvsS8ZW=AA~1+v_JHzeS+{2`##%S54sRO``S&%05&0+;>yL^W&kEEKAKO*0DMX=>r67 z2f$X5qnj_THU^0n(*X=H;XugnXh(PtXtnXdA91;fc0H8bvWF~vQBJ?K=ral&cf8QL z&vVBM2h{t4mV)8}rPCZn5vma)lxGnrZM@>erfY6=>G5jg2}oSE&c)Tnvy<=9_ zvqc-hdDc8@2E8Rg3uji0Sy6xM`rv2`o52-EOvM9zt!*qG zh-0?%@qkJ;O0wB_rr^004|`jI}wkN6TF(w+1n9ataIh4f*) zF`5W%S=S5jKv^MlWP6czU@>VE(u4G38?miOXVS%IK2{xxGigHntzY6!yoe*)-1=o* zSZCIQxLUuY2kY#?L%LYM*+MtM$uzlNLTa#GCMm zp9PO;i3`)Se5N5jEQ2svH{wDV7LT${ESI?Z@UUFcg7qcNtRKrIEr>7cP5KaD=HWZj zuq?J2%VQeCB^;K+yu^#;6E6RVH~*NP?}S5mgkix;%}bcfOBjSp_{_s{nUCMh$Fc~6 z=?Rx#KGKdfVSO&{tex_x9#xvYXZ^0rQt4_p) ze}qd|giAO~%XEatv=%%oJ+GcEHlKVdSCIPi~Yi38ySGF!*Pc&2)@s9>THeML0}v(Z`~< zMGwMZKIUP$R$0WysykieEeo!<|91fN0?R}2!rXFmu2&hcoII-Fuhei%eC+) zJf>qF3s1ZX91DNKU|CE{SPW+#3s1aCUczM=EQ|07lQ> zRVeom$A2WBUyd{r@QlJU0uN;y$~2@I>oNro<-;*}3h_{WqI|}>lSWtIp}aW`&qa7B zH&K=%9Z4_ZL_CNeaU!n7uN;pL5A!e`^D_@&F+brF);I8wmSgd-4M+>hSfmSOF5*Ny zh#zqxuEdXc6IardbR>OAQ_`CBCEZDD)|vHW{aI(yg7qg|NDH2Pj)pt|Z+l|KYD3j}MR4Bt(ZGk*yg&<#>E}%;-L!g8Wyfwl$agJTTiN z3e9-_$=qL$%0DVQB{$c#RQ6W7;D-_i@u$xY_ryad#TT;d7SJDqCzjK)GjoT%V%nAA z&*PyJDSjfhcKJ~SIcMO^Vnwt_Hsh=f;k0(-W=13^!V>jegqHigdx>C0_=_zYemXP!zKO-S zxNr-UOakgZK`KGL1-Rb?H~H6SJx{Z{2x{&p|6Onvlu#D?m4)+7r{nBP<^?)hA4E`` zAaV$ZjB9E!={FllTwo!gJD%_rLF?p=9K+9*+QD!~j{C{xeL}b6NcBt{7_@$vslD0y z=YG+Nk=+aoj)}V7(V{}=B#w$=u3f}a-^Iw>J8v&RaoUlqpaFbAu()e4hlS{KY~JYZ z&7e(-i37BVssdWcB;6}$!EQ?vK+&tmYp$VJhrf)6UN@@|KsBy~&jv+H?bFD~#?0sq z!*M=Z+uZ@+iIC>^J4~MFE;^z~ivj#i6Hs0K{#`a;pdERdOiykFcM54?a91?ZBY_$txbD#B;0Cfd3u2Sy9 zL5lE~SGez*2xQu`$n)&{0d{}s5cu#LYkSE@RuF#u#s7(t^;F{6-0ais5g) zJ#qvH0G3Vrto7YoE&2*RqmCvV={`g7ojH+^*Yo88`HulNe`)&b{5S^#kcy zA7tuxmE4q!LHZ{rrF;i(cf_TZ;pa#(Fv%16iA$4&pCjQBbS-{nh2xp-yYlgdAvM1B zUd%_)AO8rS)}E~B42>0^Q(GvyQ4a1)T~Eg`N4Mx16Q(;ZI8vMu-tUlq+KY40XN{Ec z9J*l+<{?*jFM;Fc^F_vBK%@O<$hk8cF_Z4N3o%gV<9nuE0`5kDd)qr~elyVyNt8&k z;|?Y%ju*d#pysmTo0|H$_d1HBOMZjH9`tdAuyQNxWf-C{Or@UJ{)cw%m z2JUg%5B4jIZ~&Sf{yb|#=d|!=_62uNb_Ski~ljcE8PiLMLg3Gxs4E9CQ`O&8>o8b8>iwqdof7PJ6gxi(Ybj zZm4JLen7DGE4zJ~db=w8MLhIQG48;2?e<}gfbrhp_hbSaWd>CC95!;P`fvSkaQM9~ zQ1-VP0|?K%i_=U$Z=_^0xQf9!2-9>!)Hs0Z@t9L?G&xjqQd2v;5F>e2Oz4$Zp`?ccVwyy2XY+c)v z+4|Q^PFsh=?_bgSe&${dx~(5(bArQwm#N=*K4r~*cV<&$)bBsv!LR$X9r$YfFwaWH zc!-3Izz^VIn8487@6I8Vc>CQy#DO1Hm@t_bax4?$r}eMdsSyxR8G)bHzviVzK=Nb+ zet_}TKP&K4DLVGMf2spNXu~9Y$jeNPAJj2BEefJAqws?$Y`3N4f|ScB{0Kv27OGOR zDaJDbKj=HjQZO4b7(bvUN=b==fXFEPAc~uM$z0@MMBxX)t%h03_1TVoJ7mg(Q9+(| zts`1vNQ*0*K+76JX5@+9C=7@$p*H^KO>JAp7L z)wVT?mqh;=J67#O<;xiDSrqtNIW|KpWqgJylFO#9CxMYr_!;SY_%7rORJuQSS@BDI zxKJy4Q6JW(dtcSOZQ8I`_3JS%EO^zSEogIS*T3q(Sen!HCT0x1(WCtbVHCeqe3J5k zBPuc^oJ3y&)Eb@5n{#joHK$)mlp`_no!xZQwB!tbHg3zP)AKAvo=oJ))61eZDM~YuE&mgDeImU8Q^RS%UMnj4^QhbP|d;@Z&g;!eooPM}0Sm8CU>8KX!)*HLD zMyy;6xGTYs6K(8XjBP_$5g!Ik@V3}k4riP?5-vTVEj5Z?A}$NDjqQw-L@5)xckSDe zfwG4;F_J#^5T`d9k+MF~e~Q)|OYnZ`9^N!eBi0@sY`J6)7Q>|3id%Xhz`cak4$kl% z8o$rBFE6tKESuBxw|$0v$Bd#Ll%3Obe3AG>YJ$H*(~}eM#2U^l$7wu(vDe&74R;Bj zEOl)?(2PpbPfN(PwN2JxT*P_wbG4;i*v!;7I5bKD9{o0_-hjERyOUIDfipgA+{#2Y zQTu$tz;LU>{nUQkV5bkuFJ{gjeMYvUxYB6-(4!B#gh302IEoh<@Q$8Hjgm^n7vq+= zr6=?mnO5qOp$u9uNTu#dq+Z%Hp)6me>ju;bWkXdW*vcA-M4=NC%EqgrRiaB&x!v(9 z+K|{Amom)wHNquLt)1K78!?S2IZO#v`b=kh z_DKBKo4iGvMi(C~y&-=?MTiig%Qo!d64EBth z34^R!+alvlw6bN;r}&6?VuKs~f1^W=rwqcu{8`Q{dN1@F7h!DVdVHo+t8lhc{Q_7Z zXDAC~i)Co}+6~U|3P-O#YuIdU*050C;zdRrT#q~gY(Ns!V^A1bMT38ZKB%%wzd@Bd zu+|<8t5P3FQkI$%-Z!eC!@mf->^}iIIM*dWT~@lKDIk^Xiw?S!HyT|To!z6C_dc8n z8l1vVkGg96o8RlvGp79IqZNM)=HaK|k3l!?eXE`~-#7u3X-~=bo4_aZV_`h6@+m6; zvB$#X;eHNv7wduWzArYp!#zWqTzjbIGHnCX^eFROI82?RPjhOSv26aJjpsQL)=!`2 z(kkGMm~Des96_b$Zq|XaxHJcB#94V`8}O-)&S)EtyTI`pt?8jl4UtE!0Y%R?(=K6x z1qa5r&!h$oEJ0HYZ9P~gI#H{4fPK)AmslWV97({yfmj@*nCXaKc|scyoj$yvLz_Du zr^6lpJWP}K8)3ZS)tVep{|ShT`v`Ht_}B#cj}Ld!AkLjS-S!(rQDTo$+k|GN3_U?hVF^;HI}PtYzjSn)-U0)^|CWrMBS z_&FwhEVj%z@|}0I=p7CS_Vm*OlPGpc}ql z9RB&nzByo2j4!xP6nTYL&3;(r**f(v9|iu1t0$Ja+>ibt@>1|D4Rh|PkG1yFMpuw_ zk)vJCb%-jY`^87!30@OlOTg?KY3zI83_@B29sIo436J(mV`*DhkxkNcA(CKgIi6 z+GpgCmyj9xs1s_n&pG8W{5E~i9yahxL9zHy@xJzL`Q3QsA6`$WH@^0mui<^3>81BD z%a+6K;V%4QZm_k7d-2~XZ!RFrj@ce2>R1HejSkeXd_etMjf`-I-5(8$2Q=e)P!1Hv zSbJG}CYuH_OZ1M%KoumR4i+|Cvq2!Rj7P7?*D8kTf(JVbeDd<^>P9V z(k0RawB;{J=|#r$OQfXYedt9QL3=s;Fk+6YHqM_8w7{yKMaHMlma`dU?6Jnet&@af zzEPS*P7R)4npFUIYr!E|sseunSYXe)^_<{w88p=x2k5m<_Q1z{GF=L<(jBNhc+Qp_ zRHz^B4x@9>K^UL+P+1=}um!qCN5e zX(kAQ{%W54i7q`MQrg2vV_Lq|+NzPPS~7Va?8<^+R~G*RT$bUV2o9&6*ha(?_!ay` zjtt`o2{AqZPXdSMG5mmbsxLq2LxsaV!#8?0touRocosuWr*H8-&>8zI>6f|U>L!>* z)~$yJEFPCk8i*ojb=|tlQ|^IZQMa;Y%J@x%V=uwoL#HS8-Bh>&H_odl82jQv+0a_v zau2tPW*po=5~y_^Q*=y?uI4E-FsQ=XJv`+EXn}K*-$nbGAGmBKi=p6240~lv*p|ig z_V%nv__?Gi14(VDu|0GHCdufqCy)|j=Lc90Jv19Bs*R(3or_oWobVKe!OaRtJ~S`^ zxdXrQU`YQ@?Dhn>Ml$|{Jt**zpULpoo(1)vyfsge;)DH!wK{)#5V_3Dm)(;RnC zn_l|X=8u_-#Uok1ekrSfWPQ@;mlDuS?NSyQ7g)yDzhMZK^u`9fc1}T=SR-wB@3r~k zm-Zr|c_yBgo^C-Fu{-_tZHGcj9wasCgC_^Mcv$>Ay+4uA2NMA+vF6wr7t&Y(50Mga zX)LS0+y01w30@d)1x2D0CwbhF7g2Yf$8ksYrqbp6`1oh&VwFik{jX>=n8b%3jw|uH7M{mHXw5!CW+9vHL^Hpl3SkJCn{^y_z+R9=(kcTax4`wqaF#~xRtOC5- zcb>Ila5WmfPrr$AFm^ufC^~@iKv^uD@wX=8pF+HQ z?@{f%d<+|Vu0R`fz9#KspX`q8$D2M_m>S0`&ejIAd6Rvv^M1rfC!#GUht5j&0_)x( zsWte2%asujg9n8xIi^-apx4jiG=jcyA$oN1JQ*VV z#udO&UIS(Gu@W4QPt1d`F}|Smyt3;uY)$7#Y`kRm+y#jDNIXvPgIB5pS0IZTYRa*} z4e?MuYV(Z8@hOs=l)V&FAnmuSjbiMFR~r{qnXz-PnRWHFD%@~^>pX1rb#+18>}&8j z&Q?9Ua_(GP#Whvc{>lp5xaF(YjcW+7Z2*sQ9F{&uL!$y866MnWQj@m>LHU7C81#*l zpsZ(35zAhN4`6sZrO$XM>v?-M!ZY#DIQa;|+ZcWlAaWV>eo9c*-hl|J&8-eJgWrrb zkZfvaE)KNt<6QKn+L?<2NBA)SAMII7@XCbkS=ZzLImim}R2zJg1g*q>{UJJdNjPcz%FK!*dIs#ds?46yX_) z$Ac#m&tH~g*xtr-2+wcu{0h$lc<#Wn7SFYKrr;Tkr$3&q#TmBW<9P+$yKLR9KCw~9m07EN4Y#gcUbklT3f~%BF4uKpI^%KEzX>(di}dIBtw21te0p;6%dnuS_fE%K{6FN5dm zo9Wib^jnR$Wh++#P=jrn`c2dfA|Q}T1g~1Qb~W5#ryc#0iqzKy>sHjQfs=D4u=&%! z(=((nP&y#g#^eK&#ByLOElm<~dhj*MFK1d{Dq_ie>M~7%OySckunLu5b~Bl_&bJ1) zZQ5qkG~jYllg&+{kX)nSq; zYelfGUeU8=?fT%Yw)t{VxB?3yxyCl5ZtXHOf=oiT>GgHD)U5NZU%kF2$>6GA(Bu4= zx^-xrRYXo5SF+79PjofZ)ZAj5vAW?F-zr`fBlt^Ir3@5`tEs`QD**(~R&D{?)~#L% z+Wdk0B%2=NpFr zR|J602I;8vbqx(;)Q5}$3jdl-s~dt1q?kf}d8px5jy|ja;3qoX^kqr*_Se*}T@CIB zr>(46heL)^cFnrF(9HojgI|lrNCL!pFWgPBtezZ?(`N~QC}Txn^%``Tbv6PQf~za@ z5(MX+;34HVR-(abYnKIW)68`bMz(ri&AJV%akHzegV-3$SKmzhQ>xBXR?nO>?i!N| zaFGVsA+#RcWl|VJ2U^w2YdWV-d3=dP{BGu_KS#Xt#se*jnAoKU z3p|MNGRcqm!X!T;h#PO{o96wJ(l6^h=_zAA`>XcX!XG)pe|7v_qQY&N;r7e~s9p<} z;Py1chWPk>pZtOvy?D`!!~-ZecdjgOZ95(u1X=5mNgcs+v8Q+nYhcP=+fOAjZ9j$Y z=*&1UYiUV`ck1h!R ztAxa$vwG2D!+@2R)?-Otq7zEgUo_Z#s(B~U1EZi9<)bQAJu8T%RnOu>pnz4Kpr>WJ z`$@+o)_3URG-Olhol>6NBI~d-mS_8y%L9J|(FZmc;DV4xei3qlLwcx7bw7CxnN#@8 zq#q9qy4+9ZX!}n#cVbiB9?Xs|@x?M*w8QQvhiI>#yj_Jlqtkt|Z=k(cbU-@-h8fU& z1$@Dh8yvG{#-6pP3%C%LBZoGhRXSLfA9=cC7gruQtNWl6&G?W{!!pyww*tO-_%;%6 zs~+^?b=5l3z#vJh99_GN(h;0sz6$8Bsz#Yz`k`ygiKskgL+*!_kJcCGRl_W3HQVn3xXJ!XG-TKMzaE!oZc z$HyEk&HEScfDaLggqLPe;`fo4n)$l`J!I!a6joC2p-Nnb)6Hp6Fth z&68_7$q)Y7>YQq?1^fGF7&>1&^=5Q&9EMJ{_W6s9;%}nzu&u#q<$b}6qO&pzZ~%Pt z12EBeL3SUxE|!Tg8qR(!Hem2VTvaLeppOP$rm<*HGEGCqC? zJYqN|&JwAZPf~7daP4|iR}G!JqQ&!Q`Z(Op6gFeCV@fm9ht@4JhGc>aoJ!&wJjO1h zpo(E%W0s_b4x;$v%)!p!sM@Az=dDP2TCdvi{Rme zDK>x(^^0$C7^^!3?joZE!Vl-E$vw$(yc_;dG$vsGoF!BLgzyd7_#mFaiNZ|LAz zG|-=6w+AHx+R}(z3y@Tdpp_ygHy4%uPh(-};l^C8G`%9h0C(+wE;GC}poSfP?1{|%et)kFo4jXb^I)!f*)#9buzXt+n}2?`T(f zb-7Cjo#E=QETBY@i;y$3O~{*vv+sq@sWvbJvsp={ezj1!BGt!8r3qXa0L=l;94GZ^ zxGD^HWQTjQL)p#m{awR1T3StM;D;oADxJkIVR*XsnK#ac0C_ZcWlM3q^fqVH<;pf| zkUrxQZy`B#3jc-9jXH+-!B@tw(ST$$uoyarNO0k{@w1S1%Ww7Ts0@4x7kTl1blf?D zw!(d>X7S0gu{Ya@Ie82Bd>4Z+oZ&C+O|xOi5uF{^u5r%Z{qSy#97a|!+CJd95RLpS@Q#;PZOmjt-#ITQwU?B8_&gU@s3s~}TFV;a5;sG-1b{>#EUwjm!A3Dj6DLj0Z>LmT7 zcJ9c%NT_Fzn(43~AVha$I|2yxCeRp_zU`#V6WpNBbm&7Mc(q0jHLZpmWuI1-7qVAe z89B7&)7X+0bdzdy*U*IKrb1h20<&MBvR?pCPL0F#0s10m(P3mB-D2jwO648a!Yr^S zcq?;})BWVkLhW$T0k})uU>kLVGqI}-{-ci84hE)pr^dacy){Lv#o`BQmW&$LM^3u8 z(J(;2ky`Hy7Q6S_{nKFNX&i;qVl+4|FGas}Z+ioEy*hSbOX=GU8QQ0q_Ag_ii$7)} zmwkBAjgTLE?0+bF8zbs3JKq(Wel;ndLwtA(46OR=vmB*4p=^CtK5Vmy%ukqggROL< ztKk-XIHL~)Cqk~z3Hqwzmtil27i#&U`cA)4Bt-GiPiAoQIN(lA4=!Sp_=FZVR z1xYq=5Jk`Pa?N1x@yBxTE>=L_<2v>LvQyfI@NO+IgdbBJ(D0mwx$dyeOgI-A=a-uO z63vKpcA8k!`55V=50*K9VXuls5Uo!!1}rjukB&(}$Q6liZcuWiEwmYvIBw@^f^C^6 zc*&HeRcMNe*aFx?~4LtPw=4|fgkiHil@r6}nF8w_zG$AON3oNrgPEo-6>oz%ZU>E&CvZAux zlG0Z(cPvHaoJJP%iLA>uIEx{dO9&bXA!)M9zkww1>HdWs&iohlz;F?=_rl(j8NQ(X zYMlSN7Ni}ZN~A;)tL5E6YI|=Fc9VsGVVudD53>!H^AG~<-K6Ti#-X(~;gh=&mIC4; z&`E16K3XjtP>)DX;V8W~eBnF5p*;hmP#k_D`D67JH6}%QPpLUc8IG$Ha};<&rYX!V z+xBfXW%7iCj5{(QFn*8`><=3SY&9z)9ETE!ev=w}#;b#5Tp${+qKglzHhzUmBV)Q^=d=*v@yXr78(0t51>R5YpGIMwIqEHamCt| zW1-x%mDDv{A}`}s*v70-a)`N}!LB064R8$rN5dF!uW>U$b0w2cj4K$l{u@5SPkGou3LHR2#QL3I%}(c~Cr*zsPtFHPdkN zL9C(NR{m4ykg*qA0yFBc!F6Q|l5loVI_ea7Ycd z*jD<8S~MOo+5!ua8EdtVWP%{`29`?5a0$WEHRRm03L#uKuEsC9&g-wPhG}_;ht(ua z=(?)M=>7zyRQ8|*4soyn#eLV)eO3h~0tcMju=oo+DKZ%C#6=ymGqbE7Dv6EOT8-R~ z0W^Xiq!ojsaq|Q+N%bd^oQ1wD3Q}FU#JAI z?ltT{ifbD$xNw--94F9^FkdqI1N_2@fU6iKxLR{{b#$rgWY&E!u*nGxQP(-m7rQct z85$h;;Jt`7r&h{p!}`c-D%bsUSS2TIIaNU2bT(}=GkUg?+6Jlke@6y1Q`R%U5Qjd^ zWjx2E#q1&wz}`s}z@nSteenFbvgP_G@jNkG@QmOvsNhj+hne!DSf0{M8KyLs$NRUS zzMF=h%woNLp&<|QqL4OQUObC0&x<|V&=!?B&nWmSu*YQJ1YbSRsw8WiR^3NXE~_hP zxUlWH&eDf*Ou&UUAunV?h^w*+p$|D3#h(`hRhcG5o-i7&%t?R_>qBr7+Tr15>VrOH3MK>C*%BSbK+3Q7A<4 z1hzN}ac1*`HW2>&*;lbR{^M9_x;zB8+o^fEs&r{jFk5ATHj%P$hpDC@|FROl|Bh+1 zAY;RL(!DaD2Lc+qKr#9^$GIJxb7}Nyjc{C!;}AF$w2kKwAn3s8`c@qD!tYev>kRLO zTe9|0;l@MRxcm(_HW~jF741e%M?7?dgFuJzKJKS$uRMliw&IhxM6VpoO35nZY-&Kg z!;Np)g0;Y)=#~(Vd=r9D_SJf5iYyews{mZ$~?n8b2xUG zKF`uV4kvE72L2Jp_i>*=V@Iyz`|-+S6*G~2%YNqGf(pKYBDX-kJcbHUxNfgJPNb}( zLygC^#@;CJ6#9%KedR&Lac83OZx+GdY&@x;XiAi0h@?xdvGj|CV00;UJn)I{#NsDmy-un@FFsVTOx2N2EM%f z%8XYYtSJ3-^UrXB6HNMv(apdpTJu6mTZX%4u<4x9r5>&F4PcwR+nfEM9ZucxhbrC< zT_dWf0%huGtNa^A`)B>p(7{DU6(%X_XBHWYVf@QZ;>B%SQ9qQ7$7XNB9asn3AYcL! zuJJLf8?SuGQ88NcE49VbBGdfX6?JQEV=?>N#xBQ3rkZ!iTOp2@XV*FCTQf-K zg#NNZ^p|UNr5?itb~veFy#Bt-o0#d^W}FTECC>H(*Spz5z}1QF8u=ekTC|rVp^wB- zmqJ?yRd?kObcd)pIibt!d<1EE&$G=|tr;+`TV#B85wJ1$vgQV6Z-l{)G3^85joCdoAy6eD;}Rhk1m;V~d5I8r zV6lYsLkI){_;+?SU+J7fI-6=cnSVe~YEVBLoh%QkhD*la)3mEf(c!6~Wdx>dh;eV< zsYYf~H_#t6m}+axI++8Zc(yedTVurI=)=}LytT^kG4ln;Dj3p2=@j(iMQUw zTetZJOI1bGa4e{y+A~4inX$uh`Sh6;#D9Ag zs)MPgup0Y?sDuprH3}wi{6#9XVW{@j3#9&n_9(%s^QR;M_AT7oFh-*e;}7YAdFg@1 z(O7SRj%5S#LgzL=JBlUr4-Krq>NMlO?WG5{WXGj#FyI~7{6E;5xl*-2Gp4X$9%qJf z&CdM{k+i@OkiFnrb*EIB(|E4n`xgz2BuU^aSFsO#-S@?nB#r*K1OH_>qFe;NZ1fQ1 zjTa|bF=frtNi_%Oxa`6mKq=hg47qD@fQ(sYC@diN)M06$XFu!-juh6xk;>XUoJm0E zlEqhWAP#OZ$11F_Ar!?1w5abd$=k9#Gvy9nh&R052EeNO`%rpp3d%>*6+c&$4+O?&<`gItnLVw|41rpn$8|~pQhi}Q+>%&K_$G~-|BA#He5u6ltJ%Lat z^?T+S*E1qh$sFfUY`%&C6%I8s4UA7P4z+Xt;+6l$-g|~MwRQiZD-e1~P!JFlR8X;k z1r4Io!Gd(KyKRWrC7~!K7*IltV(-28hKe0f0n1jvhGIcQT^P2aA|N6;zqwWb-S7K9 z_uS`xIA5+li>x*4n0?Gq@fXC=p$^4@uL*6@CiQ$Sc1Ubk?p(ZKrYYS7U*lb5uW&)@HI0 zj+X{K8;Mmk6xx4T^WB*Mmw<`Zw1=V2d^hZ35UzItmm0G`S8C#cH%5=mpUZ?w)ubjQ zR@DY#l_7x3=+<%ekZ|IUNydR4dLsnt%3Qg7m=d6e$A!uJX5A-pht?03yTjP?R}Ty$ z!N9?T>K>l&ZU}=#U(7eYnisFr1t*bT4F; zJBIs&OWh4cP#V$1G-;t!qa2_YDg*cVr1Pje7XvCh-^CDsWCNmZo}`Oab0rm-o94d|tVS4|?qvXyv60*hHE(2g0OATI znqt(`{h8p&Ot3a{!h}l_4LQ+f@T7;~0Z12A?a_fo#uz@S~dNS(8t0PqJ)-J4-Tmx#2_a0tzc79{;5eV$gbR1=){PtBqfq%1;L zQZQ(hQUA4_?RJq@@+(kE{N_>3jV2f zGU1;Fwg>u%a2!ZM^ev!B3>#GhQGG({WVUMyckI6KD9aEtJ2!Oz#DvHR!dx{o{-5bc zz%L>BJB`6J`%Rk{#k{b@C5$iNXU-t)h~bur^%+`VEqC0R;F!rF2+#s`;WOF40l_FD; z6kI_bIlGv&40G?BYDzP8k8G-&yfAf_{i|+v4nWPju2IxOK8efdvXgs@s_r_;^#;Mu z=m8mQ9e9uVuCOEVxSKfT zHY1}_M|y_vW7$=QAdHWS)&jb+Lye$+38fARn}TsB)-L$!ifv?u742`0S)o(3~6h86P?=_%VdH>S%bXG z38kkbsWQfENXob{hgTyq+(qi#L;et60)!s)C5>uHT4Fs8Ig`bDY8Wyv6_6_@0~)6D z$vnqgzziEq?jg}2sN=_y`5Y`inf#7n!VP#(?8E=50Cz>SFva4d@y`KD*zzdle z#5VK4jb&DL--77$-@*Wyr#`1jkSj9fyp#@*`I<2dHi|i-7=DVhq!y%@P~`a!on0ay z2MC-H$N9#>pewB+$-5w^WxWxYfsQj^Bfai#>3IZZ_}{=uObirX?GNf7^z~Ib|7HzLsu4&9eO@U^L5@1iJ$2?yn--D+MEdH9#?nMH&@XWca~2>0 z!~}llQ<7m}Y$Jfk3CjZR`qCgvxx2Sb8LT}>3)O+Z=fvnqbM0=!XaJBtBEQff19Bd6 zuCCPGjCh?Ds)Iixb>{~L1wf|i>c8+OwtUPLa6%`V0lDu)_7itYQgR_2L@~F5&j{BG z2!xtDk?~PDNq$U0$b@bi6At3>l^JdHW)-itnFYSmZp)l^owP}DHA3Q*Tl<0&C)OabtT&OTbe1uEJPuA z!umwuZ9)+l9LUVJtO(V9$k@0c1R!Dz!n1BL036C&Cc^GbZd@Ukk&n=*z&~okTRD+z z>Z}hNX-FlxB;aqnu03vnDGnsgQDtR>_-Dl=FW@cVk>D64U|1r%IKbkfp<9zLmgXId|@HoO%_5kSU=HGiZUAI8=ju2qCO-Js%r z5dt_lmx5&O+C<2UU|%)BqcC<#g?|RidjbzLrh$P%P$IO)eH`eR4wz1%kPA~hlq?3x z^BBsB2Wu*R=`w?)RRX-OiSxWR!J+ds^Vi6(Xlx+0&PF?)#R zJQT1nS00fTz8vrcv~ovNiHzj~)tSX^LJ33!fsdpr`UVc#cKAwbDn@9aiub}bhv*nI z?Yd3px@yUjTZ|cte}~dvfn<}j1aiZ?RB&e~0y-Ow2*lAyxaRW@qlW_;Re3_sd^KYH28Ljyu(_uxb>mCN8t1za z1cb_WBUBR@_rc{@UmD6)dUxea>hT+3V*nT625& z6=a%KqR52<9kK;y$Xk>VvG*p)<+}(n+cHt#NDqY~tvp4Y1i+-lYcj{ceasf=F_GYF zBc!S8SROnv(-I8iDutM7AuseAFj~oyA51Jz0O6%;AP7g>;m?M&SUa4;k^Xw zWlS9l{P_#Dq(*XAZ8Ap8z3VsGbPNn1aA?!FNJrw1LWGUNYx4*f1y%@f;T)?CzR?hES8)o^Cm(nW-m9gd6c0umdHUf^(4B2-V?i486ZbRZrf_EQu#gt&vbf2gGQp~O%gSV#$z8i+9ltLl zf?1}lp&l{?Ses28V#8AKb)h|^K_u6)(OLSWmWVpSIEzZSsGZ!{9Hzwt1yMM}U|O$Q{vV*gljoTq4r=f$0@u;E%Anc&Hcq{>Xt10#RLbTkO)Duh{H>;Naj0 zWOLE6=h@y9spM9vBsXERFd`SiTXq zp-o>xE^%p^F{6s z3)C)hV}DK&mNt>YOBg7r*N5D!PY+2>dxaLlWcnGy{#}9^o0-FAwkrZd(^2M;(ZH!9 zV#ozeAd&l}q|ydpNd}h~lFi>KU!yBI1@JFlqet_bJ>IaIal`J{99Dn~1naDD#b3Yy zo*C=6E_ra)M)-;ZW0seqj<{>2MAVNNcp8m_*K3%T>v?q=^5WpF!BU5t&a$f+I0e{m z)-ETJt+|LWC>v!s6kjOYtOm395X&~+0_z7b@6zuqsYWV#4r9Gi7*_-%*H|n!&X5}y z!tl6VZq6GmX-IWIsIor|NR|D|nZITD3!IRZ-}Wq%_Y=#xCuJhMEWM{EX_(uLNzhS=~-P{DDbR`(UFO&Iif1qOM!28(mg;B>y-WLn2M^I zzg754t1+7q?4`=NOXOVWimKTaGF3DnR#in#cZ28nLOo0+aC%BA$%)ZW_pMg2vgm@4 zvUr{-co)efV8BcA#hE$TT?JnizbD0nHFQxGO zvzT2Z@g9=2rIB! zrx!9DHfE1z@lJ5R^>&dsNp>Ubr@S>Rn7Tm#eoO{N6_ykDK;8Id3qKn5Ag5YQwnjMJAE+7$>i7a9_qhCs*o z7zWK~l{62rL%WNl?(WXD)08ac5<{m9QNF48X8J6U4MM(5bWs)Gjv0XhyOKCVX$h%; zw*)*AN@0jJx}*-?vPN`~Oj9)>u6Jj0DEeTB@?q*EdSA6AB;zA8Xk_1O$(u{^wpVXQ zfD59D)~~cZp+`2sSFs-npa=0E(CD+!L>VduFzwYOu*7u#HylCqG?YouL=-C2leTA( zoFKWQcN1{B1UQt_<+pMyT41sv`H@+qDQ%Da)g0E@)!>(?GLjD3(KN6I;C;AlS0XEHP9(<`l{$qJ7iu%!-qGp&- z)I;zfT!Et>H-{e-3+z2W)N9&N)KsATMb_}I(vhN$bb_xI+%uPgT>q^LMg3(*QGbKA zJE#Xm9qb7|E4?Xdi9JPCIZ)Juz7%!4AN;pCQq;Zy@R1^b!8(}Tsf1F+SX@T)hrsuW z3s`TiFd5_yudE)}A3dSg>`hTOe6YU_r>N~CU=-SyqT)tT)O$a06apwJI}pBKf+=cC z2+ZAuVILk%QE$fpryoaASH{CH%S4LWI0^RjCgV;pg`!?fr6}L&6m>BizGWgPYVAxo zTbTu;WwR;j`5cNGHjkpt&xc=_g%q_ailQ2Y6g4}VqMpW3lvf-@omm8*F7Xt#B7vfQ zf}R*5rl`ls6ntY))X5b1lv#?|w2Y$a(kN;=Sj)vAs<_~sKeht?U@$7nz_kCqnxdwx zrKtPs;AaN--{Fn$X|tK4Qnpakm#q{vX*)&T-GM9pE{fW}8;1J!QdIIjiu#0^IPM^5 zw1?p5<_M_uM`6zIIBW)Oh#Nq)+6pEl8;`xThhy%_yo>6#y&*O|ZbTfr+ zq0j^hRZ@@eRO4xdw1m>(r^?fEmjJeoYg>C_jJW}kkjVjotQDkAy9@Q82&;`?RHAfG zS0|dUF{2=02HXlOq%Khtgcqz`IrkQ)fOoaEe56_-P`vo=?&+;nda~t`1WU*%@UG^% z3p_1}#1uFnYPC-VzWgMv;71~%!SX=PlNtgD)lzJt_K`E4;2GF|fCE|qA}66GqkY@P z;a0k_IRqvQP|ZVUPPB%&zB@zDwT881wZu2!GWBq&X1cptnwMIhmpV8J>QXCaoi{DX z;IWjqZ?HWp^W=|eB7C-j;iNN-9P3%w9k5x!eQnkVgvva#h&FT6r+h*dYzf|lFJ5#D zLn`2<)Tj{=B#3C3Mbe1O^ryEln+%Y9UdmHM$~-f%>luK&qEyzFNIf&bH&UHynR2d+ zoGWIe@iLjZoJ8GR00j!9A_o!a@GOu`PQw33OPQ&pOy83nU*z~dFF>=U0FU1bfGipm z4>bs24^mL{b0;j5x$Y_^xeB{Ag9Y3La3we=!s$W^@Mq2~V{@UDguWz8RkC z|1CW5%zU^d7Y%?(`&;0FhHrXHd;y8a{|IptywCmV$fkJFD3wf6N;WTb8k=qmMiQ_nw&`pw~rs&`*uJ0{;l%y@L?*;qI ztun;*PQpBK{di%HLW5Zs*ch%5yr5KMgr#VZ$LZyY+jsyy?lLZ%&315cFO=RUH4%Ow zF@mA0N?*JPRcT6c)fBoJVyE#U^*puSZem!&ekLtY@uRS{__9(54mG5R;6H#hWPo)c zzz#s!47?qi;I(DoZB5`cRG2x`0LoVK1xkfMhC>Ylz2Z3XIFu?5v`A(!JS8F*B7I5> zU^qdy?)T1N>$4&CwPovb67ooWy@fCaj{3%fWpf8`iVB*f+k209qQHaqcMbNTm_Nve zJ(JxsC+J7$?;^bZml!2xmlAe@SzbCUN404|5i*n}8xmN%umz$?DF~kGQO?or10hOQ&FJ%(~!4iq4ywWwB>@lD^UWynI(pvBrhYk{IdK1q6cj-^NZ@6@} z%1HNUuS8<5vyMn(1okk(m+>Hk8$RuOfz$`88rpfqoM{eb5~1klaa)gvwhHiCJ_jr` z?Pd_2nm~lb0GQy=g~(UMJgh6+`H%}*)2bVA6F*Z@r!MT71RX7ounnK7T%{0uvU@_v{_hSs`XcGfEES+!?kwGBmHX~C7VqIt?)SU*R7t#BC=>Ww* zDUaD86b|SQPzRn$ZwtOeSz~;i+Zu@UA@UaW0s}5@u|3zb)(HL*C%}&||R+xy7X}VC@DoNXUvaqYdQSJyG9X^!r9P_=6 zNrhPc4jFhS3*-_9hnS)x6UTh(km_Nlgk3{qyen?uPlnfNj{Pmt@u5I(0#U;hp;?k9 zaIyA^fzCovzm!`di&Gr&9loM_2Htsizt17O8E;}PL&LsUk((iY+bF&Rsce0&)Y}*| z2m4}_b;JwiHLzxJ=fKI}O%4?Nn6W?F?2kVCgQEjdW8Stzxm29*-Id=6A_(ZAG?9*H zc_W=8_Tn7`S}b#Y`anA@P;Wl7xZ^dXbqXEmgXbba%ZOo4V7E=Z74Ni*h%g9p;E0ba zXCw)_+2!o=fy@HvpzShb{`!KVcpbYUnG0|WQ56EUWxz1g7#<)ipY>nL!7-*lIWWme z3Mv+YsR=eP%E@6Em?($gnQ%!#E%bdtUsRELnl$XmUJubv*qC+K7UU*$ko5(Q>u@VW zT2SkuX)JcZZ73xT-6Qw0cN2uvC4FGk>F>fG{Pf){r4KApHcbTagh`J=FpE#>1<_Bp zVZWV+IxZ6I=0c$cN^;Ei(8d%**X9%skNc{c%u;p8d|D$k-^G}6AwNCvK?M0aW4b0Z zNGEZ@xI$h-CK|G%9@j@o1yO6?4DJV0lA1@3o*?sti#6nsl03gW6% zVT=t^oFbTuJ&AI7(lbRAX=j&ErmSt`0v1G{V=1_y(C$$HFGgRDVzzI^Fo+|$^RAX; z$aufCwrxvmd4IN67j5mpoLfv=FDku_Njr1U&V9r^1%qmJoeO(^cFnRgILAPTg-S}P zh<{1%5X@sI@-?D0E^)~#WSUw-GVtHJZ{P!^X2)v^>JrqX`S1%O$WJg6Ct|m3WmgBg zAfYs)`@}T6JNO{934`sEUa(|STana4b5-gkY@=1Qr6zvSAG`{cEf`6HHT1-pYmlNZ z`dpG=gLC#$PmBPAe~1$`$ai=0O>CnuDaDDJ6g2y+5l9r9gl+A!aV7j+ozDj>P`K;B z{>D;nA%vg6Pb+LnQd=Y~K$1E}VF!9s#{Usj&CoupQ3G=UPQYc4*&A_xg>rSiC$lGl z&7;nUtEhWIR-u}c55+Vg$6K7JZ4ahWsJ`GyLN5^A>NuWe@IS+Rw`Y3QjD#}%I-0qa zpd)#y*`zKM-~yWo@c!Xh>u-kllF|YEKy8+Tw#822wMxxVQt9c2@{oG zU@YQN4fUG&%ngDJQUtc^Nc&LwV{-^FB8a8HhX07>AYee2B+PC6V6dYC#0|{~q_3dMnh-DhSnQW7`~qh%;XfFQ6ZoS=Ize=W1^V*_mt3qM zE0+z)0zGk(7A8)X@(7#*hSAdqCfCBlkW?}<3JKcj6ZnyQxu_a_q)*>xO3_z&)ndhz zi9u~BHKj25SqEo;0e+SUmP2;FbT~KjrBO&oWgz4iT4T1rQ59kGigW;n21ET1gf1W* zNRj~cWb~dHJ-_BXl);z8ivh8!X$&w7ji>pHf)?WZ+Q)>Q7{G_tg_`uS z+)Y6wd*aj_N-@2wBz49y+&u0;W*ZPfhZama`qL=VW!mKGq2^G7B?7tz`Wuou+Tu8L zzYd9kfo!3678h4t&~~!=9LJoi$iy1YkTe=6#bl8K(+=!rZP^&U-Ss%FJP#`q;D`*l zjR(0#OweVh1|fu{$(E}pjvv4wB|}9i%Y-SwU(Ou@#z3GXTg{(daa5^H*U&(fX&wV0 z83}GR0gX%#bgM!DIg7kXwhq`RVXAHhzNrpUxK0)+gP~iK1H_+^Lm>X;{+vseO$V!f zx~Ey1XEjt3yOaJ;(862K+6nv%1h-92;D1mD6|^(1SC?qKZL0k#^(?}A?2{3muAe#^Dy`hLoJvgn#@+tbaSjMABh^CbHzV1(kf?@%$@Aji$SDWl1Q{mE^o%u!YO)%` zXm#*@<dwQrbijRd>>TE+uX$)b^mbvR%V;2N8kS-y#E=D-3S(ca? zM-c-=f?4_m%Rk@{yeLU)r-kVd257tpG!f)WoQQc&0McOrB0LUej-wvBErG{D8EuBu z7yWN|*5M!}=M^9#8!6^iIjrCvVOHp$ePd1LS5xPt`&y>?mPr<4@U-&X`9RI6Kj38h zD?JF*2wZO<(aClk0~7)@7%<5pLdS!SrHF$(3HnRzKl|&uDd5Wo#StJ%>Ko#)L5J)r1U0jx`#62_Fu{iZ)sKEulJD*YQE_Jvg#Ez9`A_(zXsH3Z~@0 ze*{_a&?Bya+YsWH9(x7^i-7ZZ@o{}2mnpTUW$B&`+)KcCVbPMe>>+|-S}x;^8kOOb zsYY4ivBxw1|H9*;s=o(*1KEBGrPq-0fuE}B3bjbj=Fm-;aSV?6ukZ?zn&=z6D4~ls zKt6&I90cWsIfEEod!RC4L4bM@QmztZl$q#bQ4k*=Wak8h7JWjco2Ec)cPF|{KA~JX zp#)`$>uq@{_Yo(qPm0!oM;WB1L;<{W#nO;MnP)lfyYjJ0>1h4oxC12=l1q>a%!%=3 z+UX&MX+}yAHFL>c1Ywy%TI*QTEr^$5i&~VPbroGmZQ#L#lm$j=V$-KPf^!JPa^^Cg z1nx~CSvjyn0Kv!KYilF<(Nvk9jGv}UYRXaQ`UlXvaHz0%EnW)oeurATmA-{Ub3Q4n zB8yyE(XJ$pt!RkMw_Fy$G++!GfV)hdnyr$PWs4eN6D}aqmJa@{u!U@4l6Y4xBdsEo&zoS+0{=cRB3-73xqp*=X0tSx4lKfWMD~!qSM-I7r0!9vz)3(2ra*LO` z5IBxFfredP0vW)n?jLuZRL(3>N@0fwYLmbZ-YUum<>|GXOI zeMyb7{{Npp`k?Hh8rAgtf9;#mDC_^UjCi0=NAWb(O@2vU687&h`XOvD;(dNAf2}HA z!*A(H{o;g&BSme=EcJrVZMf9V`C%pHOMSQ%ADR6g@e!g{Bz_c$50@HM6d@v`IRpXO z2*7uGXhT}aD@;tXsX*d2y`3d_+Op6(6rFl2 z0p2|$IknFuMO5w6fIx*i^dV6S-UOts&;|w)b>6jNECd}kt->RNq=6#1BU4^Sa%eGS zHpoWR1wv4%guc(%H8QR+VC(&(tniBhJh2F*U|147!RNv#cZZeo7;K5n1L&p zsX|*3(9~xb3;oi$)u3gxLWv9=1f{+3szV5mt%HG-!TU(dP6NY%z?Fgr-;BVoO6cj8 zBmkrUp^7F$WNfhe;CxD*39J+Xm@S4$aLzR&_PDY$wvL})V+tUeLjRMkVjZBhz(;veIM zZNxu%3ys7-oP_!;2SX#nO>qqP0!!&)@2pH$68m>~IL>Mr{X9`Sm^#EcEmY~SHnVps z2I9h$!T2V}j*di_z$7ujCt;%xx_XeAgPXiMuv~$Ci+!v4uo_g8!xvf*H}iV11}HKj zHhJfRi*`>9HNrAqhO}PtMx70PtdoaQQHii8=mk(0fn5l3Tmu!)aglyaz6~7~SOL#eT zrcfo&VQm_0N=CsKq=y7|aY7X(?9Wo>xv}Csa>8~;wG_O`YGQQ*&CnLt7-zYZ7AK~ z{-1#Ik&lH{oq?4#UB~LOW9>5AODG)(Alc#h&A>S$15iU*3$@sV-!qi%2oRh4%{-Kz zilqyZI!|!D>B89J@3cifQ`H}=S^-_&RMT(ve=3M9CHzj0BYkz9VKKH&(gBOnoVmL& zJVw|G$#-XXj0y|13GamN!sw6&(ZkWHzwr`P1aZPr9EWRh7{gL*m!t)jVi)+008eos z_=ufOagdN~J1k$ZHStu`hD*a@ZK}(pe_@~<1RU19*bBpuc873oPvx0m@hoS9Q9$GLy*ThRunIk24 zGWM(@_t!A`3Wk}?R_Gxsg%)I)fbT@Yu7fNAJLKfG<0~=uPx`aL$qMzr=<%kCp zTLK`O;Xs6*H=#8XFA5+s2jGGk=llyfFy<&rl~PEGLexY=HS<@2A2dblDD7#t-{Y_j z7*Y?mg>+9o%wT9SQeKM5wUDyF;bII!Gg?dCi4B?VSypJI!dvdhSV`>*yWhlq2C>qh zHJJEK7WFu(&Lm~vwF10KnAmy1rjpc65^1xhTSOm_~V5hBvw)fLlC>S+wx{-5^18DkyMD*T``Dq=>j!V?f>z=B5^3JanqfjSY9a)U_q zWIV%!oIo>-1z5Qf83RX!Z7^X+jElQ$h<)~NtS>nMg>xIID^iGF%ZU$dfBNEJ#$ww( z22SaOns6utNvD^SqEHUOgJf-_Pg)9M8~_C>&yw`?mvsz!$k|4|R0S8Zjm;xm0s;~P z50Pd110K63I4V?d^!XExuYjXkI=xJlpV+wmPdJ)t61%Yd92DqJPy8<+-DHFhD_yap z?z;;}SxGgjmx}h*WbZmbpJ2v}UC8O^@YGwpl+pO*ozo!X8Y10emZXarGO5Cqj0chW z@vCseEAji&EZzpuQx0z_nXDidrF(NAzL#QzFG&K_PFscNywPU3N#Qy$ZKxeCHO(S3 zy@Fiv(MFJmVl0@Hy5S%WsZt;}RZ)yTu%B;J<_zB`S4oiMjTLrlG2Rq&kr#1Q&Si)r z1xnuV$d<2-xIi|p&bbP4>P#FsnGFQ#gSZNlufe$vaailfr_RJ#Q;hr>%4~FQ5CvZa zp$2i}bifN&>8a1yPV7vY$deY>W+Qa47=J`|Id3$HQO=<{x!%$QePRmnnINPg1~R{B zzb4xvP~V&FDK~BDWKWME5`whp5X_zI3>9`R(sp6&MI?S^ev-7{lNYHtj7${rV84BW1Elf{z9YV7PwN+^lgBcJxu_SqT!rAwyURe>Tr;h zTH1_$I;X)!(G7LK&?x&esb@nbcJc!6>IxUe1Oik91oD-pP2%vzZrTsr&|B!et3&$sdSBztAu_ zKld8)h7Dz8f397}hm1|VjU<&m1@BQ_K;E|9#b3!4@=l35O0JMkI2nQ+G9d3~%T1*n0m%*mif%IuyI;5%3k)2?*%6L!76;c)@(oeoZ zD#zLt3(e${IMQt;_{>jzh`(f)VPKW}sY&H6;be#LR)oqOla-`?p~-(M%pyOPsyLd7%j*T4EVU5tqz*8(RIz1D>_NmLX9W>k zm$3EoRvbV=*){?UhXGt#FStTVPSBLCBfoa*2ncrU`;-3>TL1q6S{mUDJB)=_d6v}l z2h67--NV8RNd5!nYP7b=kDyG>fXQ^?{|HDv#A$-qeq+QH(qPAh`YBv^BV?UKObx2A*!DtRGm^`vf?_X(EXSn!UjF^lKPCRnm=FZ>h{cmDwh*j**+mP zH{{FX8d73`y{I+YDY#k?ZES59DBC%*L9R_<@_m_TAG`IFvly<ue^LMcJf zLd|6_mleq!2ZiXzOtQO;lN>^ivS_X>i3@KWCa}vTAIEKt(+KWMk=6wz{>dF-Ht7-(_q4ks3_m2b^0NgQ=DlA?k}XPw)-YQcdXOLQsJSR*}o!T+BO`Ol&Zs zDQqmlT8K;Rd|;%wMgt|6jiLtm>c>pLxDUfTkor-W1egjA#NU}rvvxZCdU81>l41xkK|3F0GW-MRADiaD>kNW=LY9F_ zz_S1gsJ}k+6s7`pW^-_*_T=Dqg8H*y`pj|k5uJOn2%$D@ZGt*`1CkKf~Xx&rUMgJ%PPm1#mpQwutU zK-?=_@6JMTlu>8@H*eoHaFLygtLb|4d>eh^t!5`)lJ5=%!yZPZJw|v zlumGaZkMsE=5PIIy5nqz`wPyWJ${GugTqbBo^OVr}-+%CHa;yDYpLu5LA>MUjqV3>Mie4XEb>#Ie`?c2a z+?MRvf5yaT2Zh_T&icNKkRj}bUyVqc*0ZQ15klep*6@lwPqjcPIF`8!fq<7G9QfX=ZKtb6cdo7Z@hM2}nZeoaxkI;q z$PZpS{V(KOzDHI)4g-U&;4i{-+J%E(X+e^_*BYj;n!B` zR&`h2R$6(yaqalk^jkw3@;<%#W9Rw?cZJDxkDk`zF>`ba&IrGVCYAcxc|VwQX2AFZ z(S8{>kFDt=w0zI~(SNUD;hMVpk&UGj)<}OG$wmI;yC*U?E%$ZPjQZJU`{SY?F4qeT z{nli;pVI%H@>VqN*7E8#Q#6$uY))AG2;3r*b%=cx-2cq$$BQ&3t&Yo6_S{FPhBMz> zsC(l2L-TZNqk4WO?+M z?k`8bbiO}Y>DAFBKJ4Ha(TC1KGh$4qo`0{Hr2FgbOaa}u|4xmA%Pu(7xbv(!l)8^C zS^wSQ$ZqqY5m;c-lyI)iz4@-s0>?(0P3{-zd#~o2YkMr;OCDSv8KC0a@NpO2EceleY%i|&LSof!9 zcBn|*^DSNY&-XzmrmwFaZoBLL^c4q2@ki{k?H@65@xXw9O)u`8f1@p>Cg+Hw@9xqa zt2h7itXC1i&ktNS%6UF#Zd&&_`e)m%Pn~uk@$mMl`QPjO%D?Bvy~hGK?=<37M#J)y zNfjE2)6yr58rSJW`O%2Jbwe*sv3aL$cJRXdHPreM+NbQ@pA4Kd+TmBv3(2M@%_8S! zriY!{;IwX?o=JgjR*yqx`DR`1ecc0q-iQ4-XZXO24xLi0TlLM{ z+Q!G=S>8f77ptogOLx!b`(?NXna{pqsmF;h?PfUk{tvp-!^pgE*%l6^@ptbn9;}`= zLa#XWUBUgOm%QG|ZzsQ&8!y&h-KWO*O7QDpU2bfBe(K}!(LW%~a!6NQBmC9tGu7jl zPe4#2~$@VoqQ;cEAMn;#od(1`p-F+2i6?P44>h?(S1>C z?={E9X~U+))3}47?UwAXp});Od)NE2^Tpu72FVLIUry9im$>*1SfoDU@cNrI^01LM zz!mOn^t)VYxWCu3vl8V|&c4`r`CFq#zPMN~t#B9LUv%4ViGHsJza6J6OM2^!o2Dqw zO;PT;C>fhxQNQb;j$>v!y+@5FuM|HqD7m{Rfj6yw)y=%;10E&0S{|G7uzXYBz4X2x z7Om}kzsqwHf*sdE*Z=jrHfl@D2W#tk_j(+9vN$iS`jeB!VRx$;U&pP#e5&rW^|)@W zYTQ=NTQ}QwX3n+|J*TGhjD2y^EoHO&th2GF<;&mx!wJ4NuC-t7xHa`&R;xRWjC!&_ z%g{k?-*wW65ZS>SZ8AQeNR=NSV76lXs-d3;UiKXZT4}Y_9d1(FuytvVQ#GH=weWi} zJ$~zpc?phbUBR6g54qnFId!gUPt)9fG3tiE*=ecv; zBcQYYAc8NZ95vh>g>Pg7glFy3pKNWU)PnC*Rcm}k#gy4=<{Q6~OE5 z|4=x;gfE*9|r%kZ`8)R#RX65C+w_DIo12=UGAiy)3*vQDE_(36StwZ@Es@b zd;5$#36w(4(@T5APG5%G`QG~eSLuO>_d~7P%HO3zj zu5z*rx;U)((lP#ncUl42i`TyL?*I1a=zIP8omv#0^H*ebrxWk>6TN#!O-~O?AMoah z`i8xt6NlP)f4<;n{9&Y0BO|Nr(vzKH=XTw;fG>FDci_Y4C)d|icjHhMxi5GI*V@G2 ziLZaQXuVs{cCC+|xv6!j>w2>X!#7{ZOVPUSGxlWroXACvT;Z5^mz<8wAMwe?B4SFf z+k?(0|BTuh>FD8M=4f-sv7}z(~dx5jf(xKb$RClt-LaHO5vQ6ne|bN4N83t7JvIR ze}&cP1k=fZQ{E1^_@XaoS2q*$pv&XbsJLaZYx->SySqofUq{Wj-CKr?8g=N<`;}p9?br47AJ(bUk~MquqCy;R>{wJ6`#vgj>-msH14N7IS*63<7T0N+ zrez)KR%I-j7jpcpRx68`-BE4)H_Wn`8g#&})uqBTXYaa63)=1Ul50K{)YfM{U)!UH ziOJyW!}V=BYkQf+`6ru&UHd*po$8>OI(B>LtzfxebAmn-9p8bM1pIZGOYQmM$&3aRJ4*2_T^+&Vg@1CGL^?qYF z_e;>JoEiFkuQ`scUo-TMt!0IBbKZW-IVXbE$IR(B^4Cnu-CavNe;oN)W6@t*UbQv* zDb%u`;O6=*GCXwD$GUx8W(?I)cfJl!(%&l||9!WhAy~8H_Kx&lJ$6(X&yhoK&;G4> zpNR(V+7I*XaE~7jgUdY}_AYi_r<=7P^`l?h#nbQJ%bKd) zaIb9C@^5p#{M!5ZS9h*}VPe;O2bd;Iysp=j;*yKiVx4x-i(A>R)i=4Rc?Z&I6>AvY3ii{Iezho|(*CBpf^qclwz8!hHB%?8E^PRmPD~6vO(zy2Jg%187Pk0v< z{GHN2{-x6hqpXP^i(Vhsm37lQs1X3-x9fFi{5-4li1FR#N8eoSZLFQixmH6}e<)WTT7Ecr1&TX^(L66}*&+~_L&P+V-|GrB5 z#Qb08r^c>1VxQDKCiLjwiXY-}L38>{-%_V`>-Oj+`!(;_KATz9`Nc#1`TuA<@l71n zc)a_CjjIpeEm&p~(_!}P)>Lxhu=EG#u8uzUxxb%fmsyQ}`#o;s*28mi{NnE(n}_#U z88*xQm3iO&X_C4w#p^GQ9sa<%^YL|av%Bu0hmKsgVa09z>xo0Oc#YZh#(Pg$d0e+~ zi=E>h6u4Si^%Zhu0>&9I!TjuYVxo*g|=n>EQ^9?#450CPBnEb)fD!w*o zlkLdo_l_;PvZwdld1tLWlGphCx@@!O%9%OOqMSAz7$aJIk-AgvGDW@Dn&l1?^j;hL ze;9kKo#(VZ9hYpMcjTCL%){ca-qxM{HC}x*upZr^;9%aqyqaVajTJkN*+d+wF50kD zH-6^Yopt_w_@Vf8D$#tIO zKAd9`@}v0i4(?%{p+mM7*_NER|NZT%9@|B;b63ziYM<@+Iw)tznyFiM)n6Sk@t9x1 z`Haz1HU>-+WS#LC)nV=50Uv(+{E{WKjy!sJ#r8J4bljY}cIx)^lOz3i(ykSH$7b%t z>OFWNF8ukWVIJn{)*Aw|x43rM9M~x?C2v&p?l0qJ#85-6Ba5B$yB;K)nbp0M{> z{o>4-(QSOsdt}|#Us!%GPVE`BMC)Pq(*3EfmT6lwD?Zo{_33H2^k%*J@H=VuJq6xN zXI+xna<;CrT;?>Tew;?!#*z`HYUL)z=iBI1EaZQs)^J$1Pp&^SfiI&dGk`-nFxs^{Z>^dA@VKC1EpS2PN;Y_{G1owe-cP`W=>>!6vaC zz4{OMNZsg}&_7f6Rr>Q$moG_ZNp;$7SF>fMH>XA0|A>$_-2mA>J9a~4=k`fxiEUC zVPNHsU|!H%#j!RThZpf9XBf}gmbPiFjquibXFF2`4&7^Jn(r-w1EXaQNCEZ|_$DQbfcGonv+i-H zx_b;OwNf8wC#ailwln@|<;ap&nr@w6^}l5H>5GwR*k4^%_)ZS+U!^(F$VTQo!pqJ! zrKV=4zVR!s_wzrr?c8_#Uyl2C|1i^fOc^&ii=^rdA zJ>!`)-_>K}{XvbZay##lc!nAY7cbs)SNhqcN8qAES!0$&-|X?=!^U3+8r%;b+2Qc0 zjJjf9Yi;pk!s0Q7EBAFP>26l!FHO!)p_jv-Ei%$z?qlNT-|&0 zQE&JD2mEd34m#9sf&GfeRJQ}aLgKF_2AtkJTNZG6%IX3WUZ*`>4T{evPBzzDxZ~yb z(b+evXME}LVR)~Z-|k8SpFK}nn0}=9uBo=|JLT&J<}T3p9^Y!K^XaYg1j&mp9o(*! zuKAWX*|2NQmt%RM78BR|wOW6ELT;9)N~(v}`?hF$z%e{p|N(#Kr``yReF_SWN3o5xJNHQvm)ah+vdO6qphEJQr;#Q^YGPY4UwiR1~3~#NGJh<|;Q|_BFfm{0}iVGVjKf3sH zyV10_XErDVTPlp*2S1JSzhM5xY4EB^K4qp8yZUWU@8q`WV7E2>&M)*Ezh?c_B?HxO z2%df9Ua+rvIMw3d((mWv%(SnrJie-xR4e|Pv;K428>0C^BZATzwl$obT`E@VI%>(G zl~1b%w(r&5$T(w#Z&3a9e~zzB8&VoOtaYO>B*(J*t|O^h=lsQWCKV^#-|iSZbN9`X zvb`ZkI^23y&1=7^RP*G$4_hZjNj~md=`(|@zYZmmHyKB$s>}|fM|H?YOap;n{dN~UELZB$b>+zSJ#qW>FwI4oCPklG_ znz6;_WcwkHT~^fi#o~6a6R+)m6y9yTRXMHp$gzq!UcIEgS8uG@c-+AJ z``d+XhYBk6dMFZt=x;wxzMRlnoBuhiydv<|xC4r^p zI=wvo)j78!=w?=lmEZT!qdUqkzh2kZ=#kUbyn>FahM0?&MD_+@pGqF2{@(dly8o=f z2V=@COilj!uw=+gg9`^A?3^q*o#Jxii2sKf1BX7EH|)syhd2BtJY95Tq|l~V5mdi4 zugXb9=?|CtYWB?JAGjvbxt$ zHHU4_K2BM7*wFgi*Y;AsI~M~sRu+z!KA8v2@YPjU` z*oyWCe^k7(%s7*G_VNBjJ-hTg|8%8bjj*Ki#a9EIUT6sDInq}BvZuNw)?7W^S~6ts zr4a+HGE*ZP7M-w|$$L6@L{eqJ!o>^vYTW2IYyYjY7p}~%7^8Xk^o1v(`kZr#cKg#G z9%z>mXE5OOyKu9ehrjC6Nop&)++Csha`59wf%!Y}bvwAUQ-p4i<=;h%E`Hpo>@T-4-u3iiQTac{w8^BZ zzTSW5=+0WW?3RH~;W4+9e?5*5ZXbF;Z_LAE9h~%M`3;=d;BCGukUyZ#=WMKtuUf;Y ztj3s8H*I=b{}ecul-zKver$BjYtTEp72?$K9Pgax5g!_l(fyaDyE+W_5xeI6j6HW% z(Yn9sk%;@IX`73O@ZXPl(YgQoPi0YShmBdbsH{3EJL*zIaKW>hlo^L!nh8DcnA9BY zx|J7PcB${7$n>R$EO&k6yo{OAGxyfjo+pbo^?ecZwBO5{e=Qz+;)j~yLhBq8{Sm35 zS6=piW-AzbWZwP@*P<;05*MGHaco1*;uuQ(|k zSvdRl7pw3A?KVvs>?53g`pb0tQ^BdpjsGm##P{6(=0f!brQ?$$U!C84?X-{AE;Vr7 zyS3v!&0fCu(-@y&HCt>gjf{ByyA1kmSmpSp+J2;3n%RX3f1jv6wou|x)Y0RStss<4QUn`1*dOiFM)Q@7`z zub)q*m%U%)p;2_@$dlD$_CBV=Snm*lOq`DbIpa*JNeCn$@pu7!8V zEOi`t_Ta9;FUEG=Y~pan{#x6~Lrle;C!Zhvw3E5+Kci-?UvLKkD)$ELN~T6VDX z;Ok)V<-Iwn%hc3oPYaHFT7Bs+Jw4abK9L6t%nSo)sosYN=T3Qg_^v&<{?zAI+*s?~ zqR=GQ0Ilu5TOKEd;lQL(RR_8z57b5E-^NZ@0@bCy#l< z_ldeMF?H(TW*B#-t&hY#?bImOqO(V3y8l=mtyivilzi5&``*X_=Gwe3E4NRXaZa~p z?qVI|1B-i1Uu*m2A+>y$-4;oD+hYaKGad~t@OfdjB)WI)i_pya)lWK`57wyK-Sx%X z+jl;EUf1gS;I=&k{TBK!uv-x^tdDWoh4HVmmpnLh%ej8Odg*{qmy+G?eLi?__bRP* z3$I;mU$$u8BY}IiWxnRHb&oe6b-Vn1ONi^$&Bu@T&O1BVf!m>*0k7WY$$+6ZrY^O4 z{?D)3oivOla|0GdU9fI9Ddn}ko=ZWs&c$;B&%LRxa65VA@tHBFg2reEoIh-}l40&^npm#6;!dKXfTE(I zpqZ)Tzzi^tFf+{}YN8faB3iUqW@hA`R$^N2<(6A!npSF7<`$(TmMIqM?{l4V-NOOv z+syOF@B4cFe)2pg-*fKkocrwSb#?j^ylLJwIdooFo04zCQAqxR*2MUCy5V z(!w9tPM^7Zf1hUVjMMow9$JvG|CO)j%&T3k=H%Az zrEQ=4)zx)3*^TStbc4ww_rKJmRCSGH@(PDhK_%EzAG{?O<> z4;SZ7YWB|ki=PVX{&VP}-Bs-C|LD4+`jp^5KWp*(pw6!rKlXg@+Jl-uI^H#=&eYe( z-(B>hIW~Hzq4mkUKi7YJaaZThPmQ_S{>GR&-`}w(7r*y2|W}l_urTo-6tx~^uJ~gm= zt!f|FY5U-FqrRJYV@UN|S6{tr@wD`I&*Qw=?k<16Iig|nfme&>SNN;L7biA+-12hK ziFG@cCmz}y)Mx%W=g!STHlKW=ZJvABX5*YuE$dW2aPHWe`2Fr9Q`eRRr3~(z^U9GL z8^?ZhzUPneAKhE`WLY4C;REMJR zkA?R?ady(z2Te0$|MP9L@b}-SSG&&nWeYti8!wma+_&f3g%b{EB^G^{`1#w~^bh`c z>&5*c^-lj%w4?du`rl4zy6*JNaUbVD_>Cv)qu!U^8Ev|>XK!|;LqqRhWb61%twweK znzF<5l)1b6`A$C947mi(4>b}((oi2}_R`u=R<;#n*stwJ*623NPRE6jdTfP_8 z;oUbPzunYzT=QNx`tH{5YPqt}h^^_>KYujorBg{c13ZE4>K{m)_W8*J*9t!PBCgKW zSEhDawPfS+ao+{+?c616zT->~Z(!0JuLc@V8yxY!bxc{b z*tk6Z;GA#k{59*nPNvvDZ_GMisW`lyZK2b1e$rQOuU_zKji=*BoT&dy{f*b39$)WZ z)J^k+8G-LzeS1nlt48med%QHS?(*8J-n^^ksKpOIaMS!#m2ac&&yT6|! z{%p*S=EY4uU0CPY@aE@!%IICE{WI@wI9T!h3*lWp%bA&$`rF~d=P!jn+qZs9$eYVE zo8AA^-dWEC&Al>U(%DPjMSWQJ!`Bb59DebOty>S>Y8W@#ljlmir&Y+nzY4z}bN=34 z9n3|+Z&|9Ixz_FYSI66o{HWi}{E63==I4*OBd;F~iJ=VPU;tSihj#zD+b-n27hKo}dU3h)%*acZr8@=87 zi|SVccBhP)dQbd{iGlr(Tz{>9o%!3&zPIFu8$&Jb$(@=HNd2+xv^D4F_K2F>W8Oo} zsw8y%Y3aqiyY21TT7K_;_&~x#n=empXTACOyoeW_&sLcA%&-R6>o;gnGJnmO$I|-E zuJ?j_{hH;&M{8Y*cCM|w#Qa{bq1$7gpB}to zRx|eYFTS{J(+93;wO00h`dIfvtsfXW;Q1L>wszTIYaSYM?%qaifBSaXPq+}T%ejMJ zS32o_|DC0QMH@DMxMjzQigQwHr>tzz%AS8A?uqVgYBlfu!>^BCzcKx@&9zc;u`twX zRQ}2OGahO>slXX9yGj-*&A(eInI{)~6^`37#z7x4K=!feC zkJVdPVf@=awR*!ou*HGt$t~X9zdr81uco(2S#|5hOH(#v{W&1w?bw!YG~NE=>HDTV z@vWn8RDO1q>UC-~-+!@c$qB9IbNibt{cw2gZvub$;FS%-w^z#8{#^9x$_tt|IlZ<= zuK>^6<0hT^Gi&@N`->aWAKkicNR=0E{IR9$i%(?rX}j?Gmj+kw*WtH>(a$~B>Sp`D zdR=Pw%p2{`zftS+OWmwX{+O_D#)=YJ>lR*VF)XUf+*|4HS&_fqm%ZBl%TM<@_asibuif1z&$*6%u=TD^ zt{)%$?WvLTsxH5<<()_7zml|a-`%DL&jl9L8v4TiIv)>zHfDdFgm(6t_CHg?2c|jN zP2PL{MO#$0;R|D0j;%8Et5ug?eK~T;W&6g%$%AShG8OH<`)q#5v;h_Nq)j~8?Zrjf zrYGtJkNT?NE15etymkEat6!Rq-Ac=q!snOmIv!1}cd4aB#Fnc5ls7 zWe>LbNxkVOx?+1XDJ999a5lGOJj_=};FLi}9QmvI{A&=*#Ya89Fleo7J-r40&<9(B z1mUXa3TMeCrew~T;+!$3ppKQ8TWe0J5T4Ue2p8ps2*Nds^lo-=B|GaB&bZ7OQv_$Y zH*!u4eKO}1^ub0H(xCxpUDDlT_u}n2o>K__#N4Vl*MJE1$0t7n+*aYfLQdAH3uDQ? zChTu@(0w>~96HI}!#$@w&2#I_37ShUjxUUdB2lYdIToA(?K)=+4pfrPF%dAf)<;f}I!@g}I!i(7o)_jB<3LRI|MgDB6nA$f47 z8eVHcA5}Ob>OR(j_#DJvpBa3KjkP&lR*zV>nt)cz{VA|}p5 z->(C!j18or^_7Y zEnFEk`%}CY`m2L42H;ziMerl{5hy}dgBE2jzI~EaloPaR$fQ$0Eg>=J6^bXDL-DIM zzUGdv#z2Fzkj^9ETbxA!M)XhEyO(Z)$+xWHoQ4~62NywgQ@na=522>n z8uxByUEw!2EPxK?ku$l`1^Bkn6?hy|gwG1%J5&f(|Dd~3!y4ud!R3vID4&PI&uXyF zr4y(}P9X|8L9_5dSI@<%HKl_+L8NS|^@G*4UvSJ9w(`nb++yZEqndqD-oaHZcX%y) z`nWpOWaSA<@ik<`Ip?eF^Nn*nXK~5HPZj124G13|G9?wCUfY{hQ|Qzt;M4I>(R(7p z_fGjW=dZAQJI&?+lN+gEX3SVF(6-=~nUIo*xq+g0M#`>j4T2;zEq6rn#^GH)PK{9)xm~Jq<;xV)i9yEMLhPgw`3) zygI4$DZ5~V%lmq%->SSnp!EGzNZmmJID075U?cQfFRYXNuB-#WTy1e6O8 zj%#o$qf>YWF{Qjal6|Iecua|>4yqxdlp8%$me`o$3vDUf{em`yLbTNhdN>6S4yqr{xV{ut*ljuz)$f^49A$!UO#JVbk@co~`CE4&sb6=(l zWqXNBA>>7|6lVIWIO$oJKdXq3*n}UOQU&KqBdT@qREP~fmi5Q(XhQ(nwqo&R@Nd$a z1|2__^8G2?Bz7wMRR3AiH{UR5JA?3N2s8xJzyHl2ZX^f_!2gi8SEHL&nT`*_aQjmF zt;yU3+|hI;`_@elpCzw?^!lkTH8D6VHK>+>&mLzd<4dDa&|kxG+Nj!<==#W&OT`Hp zx*%FZXVjC9*1Bu-)Syi0zPl$~hfwwDg^wD zaSUco%q{foR|*@-@Nj(b!91ZOUO5lxQB52(^?oUn>t{nc0)WyFeeW@~s18Jl>PhVr z-QKs#s}ma@tjAkt$~_^`YOHwUMT?REXD^%gR)}^gKiBj z_N=C`;X|#ND9q241Y{q><J0897+Vtd%bbX&IX%T8+@7I0 ziu*_*DT(8zKKys+t@B~qgvx%O)t(Z0uez+XxY#ivw>G&#?^gv!k#RRjbftg`k+>I1 zy`*#RwL^0z-a<9T{rU;nnN=~QFWsw! zPuKR3zR)6XdX>F+*cZpx(GH%-rSNl%vVuaQFBou_dGtfIsKVeBMsZ;mQCV?MW-*3i zl?of+1E&a6Oi73AogMHA1@AY=>07nx_hbsw5iyb5`q+fd0Eg|cpeu7v5)*Z3ViWZJvNW*}FURhqGx1AQ4% zx>e+tG$=mjR4d&5Qj&89=kYGk6)oXAofV%Byzm>^25n?6M0Vg4 z@v{HH-Lyq?KTAxtq49LQB_?=i{IJ3>BnPe>#_eKydi=c{)e>|M2$htR4TQM6bTA!> z8D1@CXU*6(s*E@YO zr+;wHBOy6PEeGE>E0!mG5I!7N@zlz}P$?!vfR^(J&WDK7df`}ZV$&de3LzMuLI_zG zRe1fc8@HSl@FDCAl^55;odu#fL)FboKYwH13o5|+dswTo^zDd( z7(Cd0n|uQN3PyT`6!gdQW&gwTL3sWQJ>QuizDGf699`%p8_IQ;%CMxE*-A z-|(jz#YN;--@=w8@i*x#(qI(4s04vCcgY+=9hG@N;ivbEMjTs1==AmSX|k?E;b*Yi zN&Y}IxS#>VHp8ZzUw9T&a1WlndHb^jN<(j0dlycjxBN|56Gl*CLa-Vf)XH@?tyj<+ zJ`RTX*vHDh58+wYr!Wl9ocerGDP*FYinwd=;ciILja+;&4OI!fzzdoCAoFAKZE^aW z@I*p#DUb6Dcu2D1rf9?a7)lVHp+17MLQ|+E$pAF!#aS19J%ne5=9)!d%9obr(!BOa#nEd<6C#nAc#=;by9@V79}Q z;Bx&Um_0B{tKvD#voM9Yitr@NL72WU55YVL(-rsZwufl~^H)fKb`^%goQ!`HVYW(-V!n4U20VH&_xhxsEIVSqUbvleDP%*!wnV0yuHhp7fL6L(QO z3FCr!5&I>%Fh-b2m>w`qV5-7YhWV}n!T|Fz%yJk9j1{IUOkJ4jFoi+LPnh*Evth7! zsr?=ppnVUs173NUA|q_PQS4NMlyNSL88Q7}JYY4SA8YcSnm z%KyE!G(dX=W-bi9jisTU;(vs^y{3WV_84>abgFZi_S2 z>Ixk)JT9&>)>J$;lgFK=ySn{fYK_QOhsov2v^&kWOGq2q3Z_45plA(Q{Gk6-)Bifq zpZ=rt-~4T5|7Lst*gi-6J^43(Qec+&d+Klg=s6aX{&)YdHlhcB(veJu!KKakaNBsB zJ<}E{aw}95vH^-4-EEmP)h+M*dnX0%q`;jNxRU~RQs7Ps+)07|g%qHXO#i`&|J9p2 zw9_oDJ9N-ua94J;4`v$wVc6;&Q~g&j{(ry`ZIX|~*P`i<<{4z}{M|``J1KA{1@5H4 zofNo}0{{0@K-W>DzL?f|^feomX~m!HkM1#OCrKw0fBKqPghBpR<%PhV|J+G|J1KA{ z1@5H4ofNo}0{>5>0PX6_oqg=_G1DGsBZb>2jN|HJuW>qD(NO?$8`mU28^V0{e(cvX zM?8pqY37q{1H`@Xv{Dcn7^Jz`es(+TjWf?%9H7zB2lBHB_H;Ug*wG$)ip*&pvA4?{ z)E9aH%rnBV*U6mM3;UAHE8yo3%=tqCv@6UfM`G`rdE^M}S7We4?`rc1^bDBi!5+a7 z_S5sR56}Ga8v$BB<^v0{N6%b18u4Y$9}}RZFkb{an2U_qhi8sV!k)M;V-C<>W$vCD zpy74my%GNj(B5W_%fNm+I2hq1U5#yQ-(f<4c9?m=>;UZ>=GkvS4}sZ?bhycU3>=KX z9>w<}xQ@cj6z;}Md&SWTCn#(IQ=T?Oo=#*A4GPj`vrNdQ0PPLt(c1&GcbVsX5}<8i zjt76nykQOUj(OJ}B|y6$OyL=aFtla+E0FKT z9K1I`>!WbI!b!~U><`c~n5TS-{e9*Ip9g5!%qPDO(4J$S34V=v+fl@kdHUDTS72W9 zbAa{*^XLoMKiBzp=u-v|kmzp>S1vTme6|BFNNNxTV4mfhm7yB7dWqkAdSAnH07^3415oS3|*` zqHwOlZ!kB3%)87@!5b9bqwsO&E|B?!xjVR6;YtW3#f9waGrs_C&pZ$Okir8LevEko zWSq=fz)vVVOW_3yFIM<{g>mh!2+tw-bC~%k_?W^!Dtw)}5Hb~^d_i%!2(GShsKOnY z1DhMP80KK`5QWDmY-b(@nW@Yp!Ot+8!OtvA7l=0VbH!&_-BPn6b?b* zr+7s|zB+R#zCl@+c^tT*Zr{qF-Oqdq{GcxLph4@Pb4LU8pQNATIvKQqI(NnwCYiT^ z$1v{&r-G5x+F6vbw+*6)wz3+_L9!ALE4)-;{ysyz!d(bJq%g_b7&OGt-^a0 zKF(}LV}4rUpB4U1;Sz-_;KUNWi`?F$aD9dESGbkJ9To1OaJ0g43MVK$TH$1c(-oee z@RJJ9R(P($Zz#M(;k62X!aM=-J<2>0d{W^H3g1w;Vr7|DBwt(M7R>Wu-<5d*xTnHU zh7##a_G6jf29IZc2kcV#DTQBFcnR}>7=yN%c^CLw=DPh1+D+z(;0Cx;g7SAd_IruOY(1&sOGz6A1F3eQ$} zA#*e6roGGD61-mF-3lLLZVQ>8m`ShgH-!VL%6O4|O)!$yp9?N_ToDL>G8zy2L!rTfxhq*oY zP3CUkHOvv<4GQm3_&9Ta$o$A02QE_hmcrHX?HUS0B))44%t;5xkJuFdF5PISBkAb9eA3%n{(vnT_D@na6<(nJ0p; zF;4+&HDnwYfU7d+gX<~WLg8>Q)vq8N*6qXgBgf$5uFPieqY9@fJem0w$joBS2fw87 zB8As6R~U=iCzz{&KU4Um!oMI=E6z8OMBZ9p)wAP=(to+=uxJWQH-9fX66| z&kl&PLH1L@lqSJQlc&K{&O>pI{&|*3G#a#g=8@o)3U5^SQ|4zO^9^$z_?*I56s`z` za4Mg>AXA6=060|P_6ql5t~k!14P~wd9C|<8a=3eG}a8rdlDICMx%Z&Df zITk!x;qeM*DLjMu669ZG-fS^wZ!zxzuT*%W!k;o9Prk0?s>ostVtya0liykmGN44Z$BU4*?%wUI0GB`~|p}x!yFa^WY=P zl%D;-O_|4m`!Y`lo0u1Xr!ogk#~6}11iVn;cNPAaxe;W(U=9U;tMEmIZ!!;pO!ZJ1 zws>$ugX;i=4XAoCJ)9(aMms}$bKybv-6nDfD3D|}wzV&*lF zsnSG-e;v4v!p#)!#{30j9%ViWPFC2d@C@c(Av2e`2>hnP?f4254|uKg_L7t9U8TNOT_@OR8{kh#vB z2o7v6!%192;ik-gz`h6b$eE}M%wK@hnNNZ}3eQmZ73M#4Fn(hWnq|=TFwf7$S_<>DZEo;d~fvCL`U$C$5xJd-+a-anVF}>0gC4Dgc*=PA4hToGYt ziFJvU%zN*_C2NYzF6OE)Bb>~OUcq`M^E=>M%z>|BT>794a}u~I^Skpf#%A6Cj#T(z zg-y({uVa3v@I-}YDV)cA2J&w(Uj(mYj$DBDiur{%Fe1q1BIRxBG;lTt?)7Cif>`fnK=Yp zr0^|;tGAKydL1&2nU{bcR5)DWLCjMZVXn$N6P&8>1chfZUxLg$<}2X0n5!?w{vdNL z@Fs=#Df|ty3o;j&r-T1sUJS0-R>oxs_#TBDDcqjK7r!Y^3jGK8n zI7{K#3NK_XSc?2&-T+>!@D7EKGT(&EdFFo0(Ec#Tf-AL?@glCHa7*T{%h66U4+qCF zj|V3)KL^fa&I3QGaGt`8z|;-|RSnWsDE4cZtFOTNKXXIye&*}o6U-rRW8BWX68t;! zI`A##`K!?8x99uvFFY_5j=`{ zO@TpsoOug)3UjwLSVsj@UQ|L}%xC*Z*e_=O47`^47HD<^$m4%;t5dJIn(& z8??We6Tub2WL$`ADcqbn3-%GrGr|279_l%p<{%D?DA{ z7nwhR%$v+xz$+A9ukb$RtJ{%B%-Rlvc2?ov6|T@p#<3@4>NCfJLlthXa3AKwka?K- z82C|z(-fY}++(Lf%VmxPzohUYh1W3;hs;jqk>CRgf1~g(%+Eq5sI!dAGH`w79pLuN zeRg3DggG7TVxA7pVV(hgN#R8buVe1M8+%^N(cnW0f3NUm=2*yFS2(zf3@6z)P`IhW zofM8?-nR$qy3BNrWt_rxg`Z>&+zWj+=3ww5h1V#&lQ|4BN0>WK4$H@L2IFK zSA}Dl?T{J8JQ19%uv6g~%-4AHRjRafCw3W;%W-t&-^6p zJ2TG!_hkMKJeXMv3e<)(Hw9amTY@u~W5HR>ao}f})4{JXJHT%;&j!ECoCjXVTmat5 zybk;s^LFqV=3U^QnGb<~V=e+4ddm1-0as=Ys1T?%U=9K|V-5v}GdBhIWo`>jVD11O z%N!4OGbe(lF+0GoGP}Wxn4bl2W}XS&#k>;yCG$Jr@0bsOFEJkiUt_)kuGCA$s~B8^ zxmv|QtvPcoa9ifi;0WgK;27rK;8DzxU=#Cbu!DIVcp~#e@J!|@;OCk1!3&v}fR{2K z0Iy>{1m4PA1U|@o1^gv*?Mi{#S>}4+Uzj_9Z!&iVSLn@U7+i~a9Jn#_Y;b4hJaBL3 z0&oKJI`C-bu9V%uj-^ zFwX$rV9p2M6Di}k1YD1KFZe;`1K^I#Mc}^7SHMFQ9;I-K!cK*!DLh-@*A#veTtU+` z8gHy(j>DK_Ei>s5Zeli1Lx0EIJqu$JX4=;-Vx~RxVsIr*)2=|bQ0pW8r*TL%W*X-= zVkW(s7R<3-u!he}^(&T{bn-_s(;nYA<`owMwDHWOr{rO#b|Xud>5n}Z=2P>rCdOP1 z_8&1*o!ZSjJpyZD%oMNhncG~#*$`&Z+bm|Lb-cj7GLEDJb2oD$&bHKHCLNOI%*D;I zHV&rr3Blaa%@4 zte3WBdn);z*`DUMJ()KQ#u}6^uLWpvEKldb6d5p9LM&gN0G`*``0dJ(!HF*Tx`akCNt@u z&tWEg$hpi*`eLt~ndTjDGlycWxPW;J;2$53a)^-G({X6Fdw=P`v}aW*V=}e<|*BnsqKwqCY{(=X1ZR>$$?`QkG#%PDZl@P5$oN4L;rutHh`Vz%5biN~rncC#>%*Rj%Co_}Y$TQ5ONBulA zjhE&#(_Y46=2(>fP0XbKa~MovsE2a?E!!V>5_3;x+E2gAoY({FHUnh5I-o7B$4v9k z=3w%tDe|Z*+oz!p_GBjg;eO1=PNRKb?z{|VfpvT2V=6PvPaVv(&-)}ZjVop`k3=1u z%S>hXO=jAYdK*mPiASHcp6zMBY#TGJCGKTT$DZI9%p*ggSHn#6&2!9j{Zg~)A!~r#(A@%4zBEO?tYLdv&)Lo#It}eVa|F&8f5S}YF3&Ir z{fhA_IW=8^EfD|0-?C%u^ItVDn2m*I98 znEY=8|BY1T$3DKA1%9_oU1x7}EV&YbpE?8hiPMd8=M6tB*R*D^5mn-QoBYna_= zbM`aSI`$D}+UNbA*@1Fd#Ditq(JYY(ttb(>_ir z^E#Ztw=>guz)8&AF}{78c^BG^d|iGzbWU`6%mF`VF2-F4Uo+F5MIl%(legHO^qOkM z%lMu`U(*OoX}$sZ*n;gxF2@{}IT9Sn9F4jb$4qMlBbaIZVH|U<9;lDZw4O7OIdLQI zreLOZq34`6SY_3G;%h__jOqmcAIzGt)V*o?uGDEl9(G zY)|@lqnKx)Ep;%DL|uM{c^$^3FEDq2{9C%rc+`F7ID~T}nA$7)PRb6pFZwM&`<$8d zF}`M|_1n|TZP51q!c2QcSDC5q-(se^96U_MJv0jYFU+)N*qoW}8R)`%>;dR$Gt=7d zU}n14Z8S68hhPDVehPC~58JOpe>aPH!FTv>2Q!`1$!Dg!9ae$KZ3)Kk>)E~o(&1ya zr*Cr}VtZOE{)U-!p-=1f7*7^5)0xvN%(Q=flbPyfr3B7*_*0FU*8dwa?>!ZuwP2?4 zKs#nyvOMF_T`+5N6WZ8_Vp#csPZb&a2vVd+bk5W=_L+V zv#vVb+$RA7>_g-4o1o=ff#xx~t(lGp+p=F|X*2J|a=3 z53T*yVm^ib;$AS7dAgss1>4U=TOFn|<~7}z=}b*O<`U#%A~Wp~7@0|b(#=fkx>?Mm zgPqGvYZr5w>0HkOW)1Dqa%R$DUc*dl`&*c4t#S`@Jj(D_%%p>KikZsE1ziU6zk{h9 z(#J~wWP3Vu6fj(-37r+K%sd+Pu`V;|nm))(YsekJCN_GrgL`vnU}m0 zpbciG{j5isLonV>W~TG|R%Ti=aWK>R^F(G^>z>YhHpQULWTt(kSD9(Qbushkj{>xH z%yfopGnm3m>l-`Rp4Q>_Gt(Z#QD$0iKgmpM5of?uHmDyjWcw8eXA$$ub1>H%A=B_A z*0pLf)BO+kg018he{I;FbP^(%1?DHda<)9SVu zU2ZczgQ6Kz@CutXy#k_S97J#$&_# zO%9O5t6;Msw8D~n5s+p{cL;ES(vc`8mz&b7UANAfF;*m40{It} zVMfFUo2<4tyB#hZh=s##OtCxhR{oR^ve4pAHd<{mw%%lNxt&&9s>f|jclna>DVDbM zbs+@R7inYsP?EOVQtS_lEI=@0Y!j?byDh_Fb9?PFOyeyv2=b)({v?k=!>(kiDZf*k z7Nn*3G2%4Agp?r*%Iv;M{(Br|6AGF+36V}g2{T(#OrCW25WCx&Y>9W;lkvGEJC#6q z>3wgy-R1pZvq!<(cHKIn0_dd*@uy<#Q{>6xM2~}tfyr!U62)ME%|V3+p{LNK$l@pi zCTxeo86seak4kbX_n;is63W*v(e_sNTLES?cDUna!>Tomx)J))#Y0} z9FNC)+z`Ruc4jj@oFk*ig?WBUw-bL=?ERo6sbn-g?|f z9i!8pDOv~Qt`WbzMc158ZG$fv;CLLZiOu9wgNC@!x3PTj)<}Y`3CTzeo5GG%Z)G#O z(9VcYZ5d(9;u@DxpI%`!#y^~p*p!`U$bOeSdA!XZx4IishDA$Fv%B0$ll*nhu7nS0 zQ`|{5lb<0VS9ZLZyg=b~+U&k~;It%9@I?;&l1L_!*C@^XaYXWPBofxAQ0Z^e-8kGD zWs1e8vgmazTxhOLlY`17{Y&j`vU8Hd-4;!vbCOSS$S`+7XPWLtQ*TMJPL%GA)QbD$ z++lJjr=?paSkloCqslpw!_cAH-BiJo(cD>F7F0Wj#hK9wzg$W7i5ePFtJ`Wy7q(O} zQL&i&4oDo_Ct;9gOhOxxVRDT}Pi42IN^)hG($i%Z?$Z50-8Z-EDk{BrGnxVUTKPuw z_Xt7?Ix<(9CnbeO1xYf7zC_NHObt7wDYfPJHznET7Rh39TRc`#Ml5c-Lu8x9?a*x; znew64WpcYI7wirTRTxN`oT(D5qKG+kpB*eh!vqK*(PY2qa+}C^B(2%wkYG*DAaW<8 zTEc&UC`b}L)G3dLofsP7-wbr+_~+k;VO#->MslGgyC*p)#{cRr8F^y&t?}1eBH==# zF3p!0=*3-h*H+(Mc`}U2PU^LVL){nS|74BMPe>yPCM8)=@{&>h^mKv4bWeuke-xls zsgA8acZ|wgP#?_3Bo8$Qx4&KH@4r1xvzSoi6+cDDsbm=c{t=CuZcixTD%oyI$H0>x zQ`L3)lx>uH?Vx_C27_GdgD0cYlIlq}Ic12bYWr7=q>EDTEg2JyZfS`uNVO(ws7wBO z%1$(o|HazKZr~QaxGf!hN+oX|u_Mjne@dWC%PQsJM&w^BZE2p63$-cn-KpOGIN{ve z{P^QsI&x~JB)ikMj!#G$Q_@YT8WMP-)i+n1#L@+gfApsNUuULz=CB)b%Z>fNI;E0M zy%J3aZI+2{BOGEps?S_(c3bHWw#CfDL-SSTnQrCE#E9I4-c<<^d58e%eU0xauRGGv zMdDMh{uEQ`LUUyLHax=EAkBzbBZki2pqH_8qdg_h!q7|*)8MXMSh)OQwmRE&>>ydp zTHAHR&_YQ82S)W}eqzv5YJ=kC$Sh-nQJS=IB{`{!^gYSQf##azLW23?&O=4ir#Y}U z{L+b*VaY(a@ecigv>^Lr2aO~YdsvWthJ6C{qsjxap%DXCLzD;7g6xyiC>FW{X+ie4 zKOh_7qRhL=1>Q~nh{1{KlL;ePx6^I+Eq$qGw8OBFb5Xh^59DCSj|>t{$fe8S*KkL= z5OML}Wip%yr(!^+!~!EUvgeVSU(p~pfH%2K(M62jAUECz`%S@$U}N7rC(?;>`)~Z!ynwSZNc3<8r%=QM^a|S7OuDq)`3Gy+?m8_zNc;Dc<5ZC@N|%9rc8K+2S~=2O{wE(h zL7(qmhmW2Y-M!y+U(|B%a+U89luo?sTmSA*ZW3a?SUNfQ8!Ne&h`!lOQ#YTAf?gX_ z%wjcCOUdxyE&k2>r5m~5Vlf+Kuc_A!WBI2jW$x0dQ~t52-v8v*iE?3b{j+1I<#7*c zt(a2EbxfbzKblZl&6?9>6^o?*o+El8CkL8Sq?&IDE@f#84DAR1;A+Uf+$L*j2cV0T zk>{%AO(%Bv57u&7#@kxyK9)^t_M%+ov8~yYk%3(~y|C!AwCQ$xhL?X@F2l<`{@YMs zs}^%rYpN+38`ZugtK9ma4RhfLa~hD@>|bsQ=i~^Dk2TdoTd@AVT{vP7tS-!L{q;aN zq76)hz{lM>J!7N`a)^zlWWV1m9MOJ-%a7vB>28#6&{v2mSUQk#IZT<1;T=IeKcxls zdfZ_MN~taFi*>|&#$vLG4He&0mfc`$#K%Q5TK!X2H;hJdX@(gNHYK%k9u3nLS741#@A4js)xV32(-z>Dk4U?GLK)Di4K!rOH-;Z z!m(L{H=-Z+Ee*MOQ39h60^pA;4f+=Utv|x?c+HAV!rxXJp>bKD$sk;MbB5wd)@c0U zVHs;FsZSEIZS3bh5qX{Lq^&)f6-KfUJ6qy6Jm$pp7Mp*3jt8`TW|R&}*DcA%au3Sd zl!=fcS;oFJOt6M~v3rRG@rJuJKmUhEdZgs;C6##J2DAUVT?d5#j8`b|niazm-?KqP zh0_0T(phGV_kmZGUr;7}q-^OE2#X|>uBrHx5x@OeIR_p`*&I|I$Y-}X_{SG`XuGwX zxY?dry6y1~4|OM{u`11E5uU$$pxdQpxP7h*W|!MV+a==P(rqOxlsAlKQ|b8Bm3f;L zq%$x_hWeY!EwwL%&W712WxZ)4_N~j=84<>g2&7ktie*PwYNTQb?F^r0>h8&?20pb_ zW+@n7uU`0_f@s{0l&y-Si#v=p1r-t=ps+Ne8% zk{_mAv~}Xo=s`LmmtvRAPp2aJXz$Licaj4vVwkXxB=(|wAM5CjCTN~?Xi@kVRp~@* znw8n=Lf66@S`I&V0I`ZrPRPr0yJSYTg3hEf-LFMj;Q&=B$>X0hasX#E`SU9?7TZMm|~gq8ldYvmj1wI$=trfr>kOp=_OFZ>JdzKf zOZc?NZ&EMU6$deoYR!Yf%X0iL%RzhA&G5Z}a=|rRHB$Oyf zW7GGZOLv5xk2X5|aw~R5(DG&2&Hg!LH_#&Xw^tA@c56H*OFVad@n`UuLL8vlpL?mY9Q(T8(c9sJzbE4Gn>i%v7Aq*ENw!bV|cb z0|c)_aiS$m%zS-orFEAy@wH8WUI)(b`P5k8JgJX6XI3#4(??Qbd0CF`O2@bu&O+zi zYwOIw=*_PJEnH|K*|6y5ms8ylbSdmf)M4pKf@5%Gqj^xG%+^kRd1_=w&{VgZ{dX)K zQCER?t3i@BT5=jBRD0}=!^W$DRvHDl-CBASPI)4aaPqjc)Lt2Pma)XR5{Cz{+fe4c zY$tXgc(*`5|5NIk70hTgtBm6mvVlgF(_<^EB#SW(TjDI8erBlDKWRlz^iz6eo(aox z$MDJs{QWt*G9t)&??F1Dx>RO^%qXp-8dRAID4%rnswUpN-K?(!%O9* z^0$5;P{7! zB|Z>FG8OiiY8k~`3oPahh>L75@vrDn84ivrHeE#f@BI2$CVY@)beY(yR*t7$G~wAe(-QI5b0XDjfGx|hk~bdlV*5R0^w z9P$`I44v#5jKizqMh)DQQF@GA$-ij3Djb*kM@W3=0zO6m9{v`Dqc*79cWxm zeUJ<>^^h{oM%e`*BUuS5ekkr3u;N5MWr}`2jh`YCH2OpOp{a-N2jwe%iT;*OKcG~Q zMl3m`3WNO{SzmPhDq3hKd0G68(TNWaGsX=_NHiL$Z1lId2Z(b(VxN^3?WNac&jyM* zD<=vRXfec~)J11a?MsWQe+O=F?dOijD{@LCB9|J7 zdZ$wu_R)q6UL_8Oc*}>khOifUt0+{-5LI!D0;O$&#XU?MGZE#h)N35F<_&Ps9E!pu zj$TE_4HFX%87v$olA#fkETd6xM-dk+v*DRk(xhw+d{o?}Br92f&CJ0qoap7olM z2>LoNr2#c?a6zFInytuE8;$Te99+osc3E7!A?gLUn2_|Ihm$ptrZ0#rUBf}ut6Wnc zmE4hbdh4#gmx@2c(QtUR?~F*Fcw7@vnmo~QeQ<4w)XfwNRP+MO@aUakRBtI8#QX^x zq;$1P`TB=wij>!jrrs9l<0xvHYpk>&e&ww7&&(3fT9Gzu@P zZ%MT$**c*zdK~ip1S;H=9o{iI@jrw< zW~y0Y=G##RTK9)fWmH<=ha40{$Mv_kW2Is`l?+jSDNwxqZM7SrKZWZv#K?g+qmg-B zTJ+6%qo}u>UvdH}FG)&tTB+f-J5#CQr^|Qn3wfn1D#!>?nGl|EV3b)86%}zzLzGF> zU6BH!-KR&af=agHd>vw|pN%e`x?*9U>N6&RE>DJq@515M!mB(c&l5;78<#I?GVCr{ zheW3-8r9OB73z7+c5yWY-6SDKL*4=~fJ!Yq&%mCz20GxKI9dd zl$vo{!B>k2nuZD3L_=vrGo+_82>Gwq6IR7SBlQT>Cn+(^R+l5)G)W&4;cXbv!4Wk> zNMO1wM|26L3sTOh*ail7lQ% zcDmw+VmM}UdIQFXiD?5}oLH4k>WnZKPpL0OKP`ats^l?qH z35oKWWN2n+s34jdq(3E-(lC{6sd}32VmRVz*Qq02U7)C3P@|^0RYk+8|CNz2%5&yM zR17$XLISwG-Gu6-Gkh0Uw+Ok1v0b7EN|ov&eNp=w^)d7w@sctnN`2f7@8IB|pAl^^ zS4X|%^7Ka63&f;BY*rSEAMsx?z_Q8H=#;-S&_u7{ZI9^|8pujz8d1>7 zE?dGkR?qNeAyq^x?oXq)vgR?B;}ls|F?dA|)6GZRhUt2^sOH$+gJ5!oyb+7ui#`qi z<>+~fa|V{Vks(6VTSH6dM{;hYADW}W#VwS+NlOzjT6GaMPv~XwJshZ+NEwkPc)NZ} z6s2`PTm>R;ltWrr;SyC!D5u_5Dm48qe6j`J#GB~$j|3SRRAAXoiPwlCUOE$s#}G)r z8h~T{ciU{@T%;9j-oq}9;JBiAgm@kx;v5p;4^ws7_D&tX7>n#W6uIWEA zcgyN@h=|cCF_~I1>2e^&D-4tk-1zXofbti<>B_+3CFtYCq^mTn8gBm}50K^`O}{mM194RAl+8 zKlHrl8OT!J6iK58>U!`Wv%hf?t1vlLc)T3*{mvo6jkK|&02 z^_xy8dS1N=T+B$TDX`)tY?0l(iy>21j_P0D+t6l{EG-G}4VF~o6`d}< z8KzzhYo*A1(W>f8!!n=ctPs<48>{KdOc(Qnj-(AI7kh5^7I`eQrQGpfj1Q>Uvzg-u zL?aH~eFl*r`f#VTr_!^A8f)*tAu43zMigvL$ta7w=cYyUE_4qj>IZKT0KFqMu}mU* z8d)Nde&PZQEO{Z7ale)*)v_q?Y)c%lrUd5+oE(inWkjs}DZ?~FVxk~gta)Yf@eU{dukf=O8@#cukA3m1OEsreC)G(o-@YXZ3o4bW5afd4F4`OYJ z*DS>7kP?OxkS4t}+N8R}%L}3e@Y#HkAtFL3UQ*9o_)k^P+q-gX&}FD&8~CfYUGQG$ jjp!|${##eoMPWumDyH2?N43+{@5Yj+>S-=a>nQ&RdCCxG diff --git a/contrib/pg_dumplo/Makefile b/contrib/pg_dumplo/Makefile index 0d4fb83424..0432e7308b 100644 --- a/contrib/pg_dumplo/Makefile +++ b/contrib/pg_dumplo/Makefile @@ -1,26 +1,50 @@ +# +# $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/Makefile,v 1.2 2000/06/15 18:55:10 momjian Exp $ +# -PROGRAM = pg_dumplo - -OBJECTS = pg_dumplo.o +TOPDIR=../.. -CFLAGS = -Wall -fpic -g -CC = gcc -RM = rm -f -INCLUDE = -I/usr/include/postgresql -LIBS =-lpq +include ../Makefile.global -COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE) -LINK = $(CC) $(CFLAGS) -o $@ $(LIBS) +NAME = pg_dumplo +PROGRAM = $(NAME) +OBJS = main.o lo_export.o lo_import.o utils.o +DOCS = $(NAME).doc +SQLS = +BINS = $(PROGRAM) +EXAMPLES= +MODS = -all: $(PROGRAM) +CFLAGS += -I$(LIBPQDIR) -$(PROGRAM): $(OBJECTS) - $(LINK) $(OBJECTS) +OTHER_CLEAN = -.c.o: $< - $(COMPILE) -c $< +all: $(PROGRAM) + +$(PROGRAM): $(OBJS) $(LIBPQDIR)/libpq.a + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ) + +install: install_doc install_bin + +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done + +install_bin: + for inst_file in $(BINS); do \ + $(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \ + done + +depend dep: + $(CC) -MM -MG $(CFLAGS) *.c > depend clean: - $(RM) -f *~ $(OBJECTS) $(PROGRAM) + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log + +ifeq (depend,$(wildcard depend)) +include depend +endif + \ No newline at end of file diff --git a/contrib/pg_dumplo/README b/contrib/pg_dumplo/README index b36cdd01d0..aef8f9f71d 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 05b19b1f76..e69de29bb2 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 6e6a20bef5..e69de29bb2 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

directory with dupm tree (for dump/import)\n"); - printf("\nExample (dump): pg_lo_dump -d my_db -s /my_dump/dir/ -l t1.a t1.b t2.a\n"); - printf("Example (import): pg_lo_dump -i -d my_db -s /my_dump/dir/\n"); - printf("\nNote: * option '-l' must be last option!\n"); - printf(" * option '-i' (--import) make new large obj in DB, not rewrite old,\n"); - printf(" import UPDATE oid numbers in table.attr only.\n"); - printf("\n\n"); -} - -typedef enum { - ARG_USER, - ARG_PWD, - ARG_DB, - ARG_HELP, - ARG_HOST -} _ARG_; - -/*----- - * Init and allocate lo_attr structs - * - * ! data is **argv - *----- - */ -lo_attr *init_loa(char **data, int max, int start) -{ - lo_attr *l, - *ll; - char **d, - *loc, - buff[128]; - - if ((l = (lo_attr *) malloc(max * sizeof(lo_attr))) == NULL) { - fprintf(stderr, "%s: can't allocate memory\n", data[0]); - exit(RE_ERROR); - } - for(d=data+start, ll=l; *d != NULL; d++, ll++) { - strncpy(buff, *d, 128); - if ((loc = strchr(buff, '.')) == NULL) { - fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", data[0], buff); - exit(RE_ERROR); - } - *loc = '\0'; - ll->table = strdup(buff); - ll->attr = strdup(++loc); - } - ll++; - ll->table = ll->attr = (char *) NULL; - return l; -} - -/*----- - * Check PG result - *----- - */ -int check_res(PGresult *res, PGconn *conn) -{ - if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) { - fprintf(stderr, "%s\n",PQerrorMessage(conn)); - PQclear(res); - return FALSE; - } - if (PQresultStatus(res) != PGRES_TUPLES_OK) { - fprintf(stderr, "Tuples is not OK.\n"); - PQclear(res); - return FALSE; - } - return TRUE; -} - - -/*----- - * LO dump - *----- - */ - void dump_lo(PGconn *conn, char *space, lo_attr *loa, char *db, char *prog) - { - PGresult *res; - lo_attr *ploa; - FILE *majorfile; - char *dir, - path[BUFSIZ], - Qbuff[QUERY_BUFSIZ]; - - dir = space ? space : getenv("PWD"); - sprintf(path, "%s/%s", dir, db); - if (mkdir(path, DIR_UMASK) == -1) { - if (errno != EEXIST) { - perror(path); - exit(RE_ERROR); - } - } - - sprintf(path, "%s/lo_dump.index", path); - if ((majorfile = fopen(path, "w")) == NULL) { - perror(path); - exit(RE_ERROR); - } else { - time_t t; - time(&t); - fprintf(majorfile, "#\n# This is the PostgreSQL large object dump index\n#\n"); - fprintf(majorfile, "#\tDate: %s", ctime(&t)); - fprintf(majorfile, "#\tHost: %s\n", PQhost(conn) ? PQhost(conn) : "localhost"); - fprintf(majorfile, "#\tDatabase: %s\n", db); - fprintf(majorfile, "#\tUser: %s\n", PQuser(conn)); - fprintf(majorfile, "#\n# oid\ttable\tattribut\tinfile\n"); - } - - for(ploa=loa; ploa->table != NULL; ploa++) { - - /* query */ - sprintf(Qbuff, "SELECT %s FROM %s WHERE %s!=0", - ploa->attr, ploa->table, ploa->attr); - - res = PQexec(conn, Qbuff); - - if (check_res(res, conn)) { - int tuples = PQntuples(res), - t; - char *val; - - /* Make DIR/FILE */ - if (tuples) { - sprintf(path, "%s/%s/%s", dir, db, ploa->table); - if (mkdir(path, DIR_UMASK) == -1) { - if (errno != EEXIST) { - perror(path); - exit(RE_ERROR); - } - } - sprintf(path, "%s/%s", path, ploa->attr); - if (mkdir(path, DIR_UMASK) == -1) { - if (errno != EEXIST) { - perror(path); - exit(RE_ERROR); - } - } - fprintf(stderr, "%s: dump %s.%s (%d lagre obj)\n", prog, - ploa->table, ploa->attr, tuples); - } - - for(t=0; ttable, ploa->attr, val); - - if (lo_export(conn, (Oid) atol(val), path) < 0) - fprintf(stderr, "%s\n", PQerrorMessage(conn)); - else - fprintf(majorfile, "%s\t%s\t%s\t%s/%s/%s/%s\n", val, - ploa->table, ploa->attr, db, ploa->table, ploa->attr, val); - } - } - } - fclose(majorfile); - } - - -/*----- - * LO import - *----- - */ - void import_lo(PGconn *conn, char *space, char *db, char *prog) - { - PGresult *res; - lo_attr loa; - FILE *majorfile; - long new_oid; - char *dir, - tab[128], attr[128], - path[BUFSIZ], lo_path[BUFSIZ], - Qbuff[QUERY_BUFSIZ]; - - dir = space ? space : getenv("PWD"); - sprintf(path, "%s/%s", dir, db); - - sprintf(path, "%s/lo_dump.index", path); - if ((majorfile = fopen(path, "r")) == NULL) { - perror(path); - exit(RE_ERROR); - } - - while(fgets(Qbuff, QUERY_BUFSIZ, majorfile)) { - - if (*Qbuff == '#') - continue; - - fprintf(stdout, Qbuff); - - sscanf(Qbuff, "%ld\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path); - loa.table = tab; - loa.attr = attr; - - sprintf(lo_path, "%s/%s", dir, path); - - /* import large obj */ - if ((new_oid = lo_import(conn, lo_path)) <= 0) { - fprintf(stderr, "%s\n",PQerrorMessage(conn)); - PQexec(conn, "ROLLBACK"); - fprintf(stderr, "\nROLLBACK\n"); - exit(RE_ERROR); - } - - /* query */ - sprintf(Qbuff, "UPDATE %s SET %s=%ld WHERE %s=%ld", - loa.table, loa.attr, new_oid, loa.attr, loa.lo_oid); - - /*fprintf(stderr, Qbuff);*/ - - res = PQexec(conn, Qbuff); - - if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) { - fprintf(stderr, "%s\n",PQerrorMessage(conn)); - PQclear(res); - PQexec(conn, "ROLLBACK"); - fprintf(stderr, "\nROLLBACK\n"); - exit(RE_ERROR); - } - - } - fclose(majorfile); - } - -/*----- - * The mother of all C functions - *----- - */ -int main(int argc, char **argv) -{ - PGconn *conn; - lo_attr *loa =NULL; - char *user =NULL, - *pwd =NULL, - *db =NULL, - *host =NULL, - *space =NULL; - int import =FALSE; - - /* Parse argv */ - if (argc) { - int arg, l_index=0; - extern int optind; - typedef enum { - ARG_USER, - ARG_PWD, - ARG_DB, - ARG_HELP, - ARG_IMPORT, - ARG_SPACE, - ARG_HOST - } _ARG_; - - struct option l_opt[] = { - { "help", 0, 0, ARG_HELP }, - { "user", 1, 0, ARG_USER }, - { "pwd", 1, 0, ARG_PWD }, - { "db", 1, 0, ARG_DB }, - { "host", 1, 0, ARG_HOST }, - { "space", 1, 0, ARG_SPACE }, - { "import", 0, 0, ARG_IMPORT }, - { NULL, 0, 0, 0 } - }; - - while((arg = getopt_long(argc, argv, "hu:p:d:l:t:is:", l_opt, &l_index)) != -1) { - switch(arg) { - case ARG_HELP: - case 'h': - usage(); - exit(RE_OK); - case ARG_USER: - case 'u': - user = strdup(optarg); - break; - case ARG_HOST: - case 't': - host = strdup(optarg); - break; - case ARG_PWD: - case 'p': - pwd = strdup(optarg); - break; - case ARG_DB: - case 'd': - db = strdup(optarg); - break; - case ARG_SPACE: - case 's': - space = strdup(optarg); - break; - case ARG_IMPORT: - case 'i': - import = TRUE; - break; - case 'l': - loa = init_loa(argv, argc-1, optind-1); - break; - } - } - } - - if (!space && !getenv("PWD")) { - fprintf(stderr, "%s: can't set directory (not set '-s' or $PWD).\n", argv[0]); - exit(RE_ERROR); - } - - /* Make PG connection */ - conn = PQsetdbLogin(host, NULL, NULL, NULL, db, user, pwd); - - /* check to see that the backend connection was successfully made */ - if (PQstatus(conn) == CONNECTION_BAD) { - fprintf(stderr, "%s\n",PQerrorMessage(conn)); - exit(RE_ERROR); - } - - PQexec(conn, "BEGIN"); - - if (import) { - /* import obj */ - import_lo(conn, space, db, argv[0]); - } else if (loa) { - /* Dump obj */ - dump_lo(conn, space, loa, db, argv[0]); - } else { - fprintf(stderr, "%s: ERROR: bad arg!\n", argv[0]); - usage(); - } - - PQexec(conn, "COMMIT"); - - /* bye PG */ - PQfinish(conn); - exit(RE_OK); -} \ No newline at end of file diff --git a/contrib/pgbench/Makefile b/contrib/pgbench/Makefile index 4e96100110..60182ca831 100644 --- a/contrib/pgbench/Makefile +++ b/contrib/pgbench/Makefile @@ -1,23 +1,48 @@ -# $Header: /cvsroot/pgsql/contrib/pgbench/Makefile,v 1.1 2000/01/15 12:38:09 ishii Exp $ +# +# $Header: /cvsroot/pgsql/contrib/pgbench/Makefile,v 1.2 2000/06/15 18:55:12 momjian Exp $ +# -SRCDIR= ../../src +TOPDIR=../.. -include $(SRCDIR)/Makefile.global +include ../Makefile.global -CFLAGS:= -I$(LIBPQDIR) $(CFLAGS) +NAME = pgbench -TARGET = pgbench -OBJS = pgbench.o +PROGRAM = $(NAME) +OBJS = $(NAME).o +DOCS = $(NAME).doc $(NAME)_jis.doc +SQLS = +BINS = $(PROGRAM) +EXAMPLES= +MODS = -all:: $(TARGET) +CFLAGS += -I$(LIBPQDIR) -$(TARGET): $(OBJS) - $(CC) -o $(TARGET) $(OBJS) -L$(LIBPQDIR) -lpq $(LDFLAGS) +OTHER_CLEAN = -install: $(TARGET) - $(INSTALL) $(INSTL_EXE_OPTS) $(TARGET)$(X) $(BINDIR)/$(TARGET)$(X) +all: $(PROGRAM) + +$(PROGRAM): $(OBJS) $(LIBPQDIR)/libpq.a + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ) + +install: install_doc install_bin + +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done + +install_bin: + for inst_file in $(BINS); do \ + $(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \ + done + +depend dep: + $(CC) -MM -MG $(CFLAGS) *.c > depend clean: - $(RM) $(TARGET)$(X) $(OBJS) + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log -distclean: clean +ifeq (depend,$(wildcard depend)) +include depend +endif diff --git a/contrib/pgbench/README.jis b/contrib/pgbench/README.jis index da33c31744..e69de29bb2 100644 --- a/contrib/pgbench/README.jis +++ b/contrib/pgbench/README.jis @@ -1,166 +0,0 @@ -pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp) - -$B"#(Bpgbench $B$H$O!)(B - -pgbench $B$O(B TPC-B$B$K;w$?%Y%s%A%^!<%/%F%9%H$r9T$J$&%W%m%0%i%`$G$9!#:#$N$H(B -$B$3$m(B PostgreSQL $B@lMQ$G$9!#(B - -pgbench $B$O(B select/update/insert $B$r4^$`%H%i%s%6%/%7%g%s$r]$H$J$k%F!<%V%k$O%G%U%)(B -$B%k%H$G$O(B 10$BK|%?%W%k$N%G!<%?$r4^$_$^$9!#(B - -$Be$K$"$k(B - - POSTGRESHOME = /usr/local/pgsql - -$B$rI,MW$K1~$8$F=$@5$7!"(Bconfigure;make $B$9$k$@$1$G$9!#(B - -$B"#(Bpgbench $B$N;H$$J}(B - -$B4pK\E*$J;H$$J}$O!"(B - -$ pgbench [$B%G!<%?%Y!<%9L>(B] - -$B$G$9!#%G!<%?%Y!<%9L>$r>JN,$9$k$H!"%f!<%6L>$HF1$8%G!<%?%Y!<%9$r;XDj$7$?(B -$B$b$N$H$_$J$7$^$9!#%G!<%?%Y!<%9$O8e=R$N(B -i $B%*%W%7%g%s$r;H$C$F$"$i$+$8$a(B -$B=i4|2=$7$F$*$/I,MW$,$"$j$^$9!#(B - -pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!#(B - --h $B%[%9%HL>(B PostgreSQL$B$N%G!<%?%Y!<%9%G!<%b%s(B postmaster $B$NF0(B - $B$$$F$$$k%[%9%HL>$r;XDj$7$^$9!#>JN,$9$k$H<+%[%9%H$K(B Unix domain - socket $B$G@\B3$7$^$9!#(B - --p $B%]!<%HHV9f(B postmaster $B$N;HMQ$9$k%]!<%HHV9f$r;XDj$7$^$9!#>JN,$9$k$H(B 5432 - $B$,;XDj$5$l$?$b$N$H$_$J$7$^$9!#(B - --c $B%/%i%$%"%s%H?t(B $BF1;~JN,;~$O(B - 1 $B$H$J$j$^$9!#(Bpgbench $B$OF1;~JN,;~$O(B 10 $B$H$J$j$^$9!#(B - --s $B%9%1!<%j%s%0%U%!%/%?!<(B - - -i $B%*%W%7%g%s$H0l=o$K;HMQ$7$^$9!#(B - $B%9%1!<%j%s%0%U%!%/%?!<$O(B1$B0J>e$N@0?t!#%9%1!<%j%s%0%U%!(B - $B%/%?!<$rJQ$($k$3$H$K$h$j!"%F%9%H$NBP>]$H$J$k%F!<%V%k$N(B - $BBg$-$5$,(B 10$BK|(B x [$B%9%1!<%j%s%0%U%!%/%?!<(B]$B$K$J$j$^$9!#(B - $B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!#(B - --v $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B - history $B$N%/%j%"$r9T$J$$$^$9!#(B-v $B$H(B -n $B$r>JN,$9$k$H!"(B - $B:G>.8B$N(B vacuum $B$J$I$r9T$$$^$9!#$9$J$o$A!"(Bhistory $B$N:o=|!"(B - $B$H(B history, branches, history $B$N(B vacuum $B$r9T$$$^$9!#(B - $B$3$l$O!"(Bvacuum $B$N;~4V$r:G>.8B$K$7$J$,$i!"%Q%U%)!<%^%s%9$K(B - $B1F6A$9$k%4%_A]=|$r8z2LE*$K9T$$$^$9!#DL>o$O(B -v $B$H(B -n $B$r(B - $B>JN,$9$k$3$H$r$*$9$9$a$7$^$9!#(B - --n $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B - history $B$N%/%j%"$r9T$J$$$^$;$s!#(B - --S TPC-B$B$N%H%i%s%6%/%7%g%s$G$O$J$/!"8!:w$N$_$N%H%i%s%6%/%7%g%s$r(B - $BpJs$,I=<($5$l$^$9!#(B - -$B"#%G!<%?%Y!<%9$N=i4|2=(B - -pgbench $B$G%Y%s%A%^!<%/%F%9%H$r(B] - -$B$3$l$K$h$j0J2<$N%F!<%V%k$,:n$i$l$^$9(B($B%9%1!<%j%s%0%U%!%/%?!<(B == 1 $B$N>l9g(B)$B!#(B - -$B!vCm0U!v(B -$BF1$8L>A0$N%F!<%V%k$,$"$k$H:o=|$5$l$F$7$^$&$N$G$4Cm0U2<$5$$!*!*(B - -$B%F!<%V%kL>(B $B%?%W%k?t(B -------------------------- -branches 1 -tellers 10 -accounts 100000 -history 0 - -$B%9%1!<%j%s%0%U%!%/%?!<$r(B 10,100,1000 $B$J$I$KJQ99$9$k$H!">e5-%?%W%k?t$O(B -$B$=$l$K1~$8$F(B10$BG\!"(B100$BG\!"(B1000$BG\$K$J$j$^$9!#$?$H$($P!"%9%1!<%j%s%0%U%!(B -$B%/%?!<$r(B 10 $B$H$9$k$H!"(B - -$B%F!<%V%kL>(B $B%?%W%k?t(B -------------------------- -branches 10 -tellers 100 -accounts 1000000 -history 0 - -$B$K$J$j$^$9!#(B - -$B"#!V%H%i%s%6%/%7%g%s!W$NDj5A(B - -pgbench $B$G$O!"0J2<$N%7!<%1%s%9$rA4It40N;$7$F(B1$B%H%i%s%6%/%7%g%s$H?t$($F(B -$B$$$^$9!#(B - -(1) begin; - -(2) update accounts set abalance = abalance + :delta where aid = :aid; - $B$3$3$G!"(B:delta$B$O(B1$B$+$i(B1000$B$^$G$NCM$r$l$3$N%H%i%s%6%/%7%g%s$N(B - $BCf$G$OF1$8CM$r;H$$$^$9!#(B - -(3) select abalance from accounts where aid = :aid; - $B$3$3$G$O(B1$B7o$@$18!:w$5$l$^$9!#(B - -(4) update tellers set tbalance = tbalance + :delta where tid = :tid; - $B$3$3$G(B :tid $B$O(B 1$B$+$i(B10$B$N4V$NCM$r$H$kMp?t$G$9!#(B - -(5) update branches set bbalance = bbalance + :delta where bid = :bid; - $B$3$3$G(B :bid $B$O(B 1 $B$+$i(B[$B%9%1%j%s%0%U%!%/%?!<(B]$B$N4V$NCM$rr7o(B - -pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!#%i%$%;%s%9>r7o$O(B pgbench.c $B$N(B -$BKAF,$K=q$$$F$"$j$^$9!#$3$N>r7o$r $@ + $(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 -.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/soundex/README b/contrib/soundex/README new file mode 100644 index 0000000000..e3ba4ee231 --- /dev/null +++ b/contrib/soundex/README @@ -0,0 +1,53 @@ + +SELECT text_soundex('hello world!'); + +CREATE TABLE s (nm text)\g + +insert into s values ('john')\g +insert into s values ('joan')\g +insert into s values ('wobbly')\g + +select * from s +where text_soundex(nm) = text_soundex('john')\g + +select nm from s a, s b +where text_soundex(a.nm) = text_soundex(b.nm) +and a.oid <> b.oid\g + +CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS +'select text_soundex($1) = text_soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS +'select text_soundex($1) < text_soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS +'select text_soundex($1) > text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS +'select text_soundex($1) <= text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS +'select text_soundex($1) >= text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS +'select text_soundex($1) <> text_soundex($2)' +LANGUAGE 'sql'; + +DROP OPERATOR #= (text,text)\g + +CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, +commutator=text_sx_eq)\g + +SELECT * +FROM s +WHERE text_sx_eq(nm,'john')\g + +SELECT * +from s +where s.nm #= 'john'; + diff --git a/contrib/soundex/soundex.sql.in b/contrib/soundex/soundex.sql.in index 89b9fa5222..d8e66cd02a 100644 --- a/contrib/soundex/soundex.sql.in +++ b/contrib/soundex/soundex.sql.in @@ -1,57 +1,4 @@ ---------------- soundex.sql: CREATE FUNCTION text_soundex(text) RETURNS text - AS '_OBJWD_/soundex.so' LANGUAGE 'c'; - -SELECT text_soundex('hello world!'); - -CREATE TABLE s (nm text)\g - -insert into s values ('john')\g -insert into s values ('joan')\g -insert into s values ('wobbly')\g - -select * from s -where text_soundex(nm) = text_soundex('john')\g - -select nm from s a, s b -where text_soundex(a.nm) = text_soundex(b.nm) -and a.oid <> b.oid\g - -CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS -'select text_soundex($1) = text_soundex($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS -'select text_soundex($1) < text_soundex($2)' -LANGUAGE 'sql'\g - -CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS -'select text_soundex($1) > text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS -'select text_soundex($1) <= text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS -'select text_soundex($1) >= text_soundex($2)' -LANGUAGE 'sql'; - -CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS -'select text_soundex($1) <> text_soundex($2)' -LANGUAGE 'sql'; - -DROP OPERATOR #= (text,text)\g - -CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, -commutator=text_sx_eq)\g - -SELECT * -FROM s -WHERE text_sx_eq(nm,'john')\g - -SELECT * -from s -where s.nm #= 'john'; + AS 'MODULE_PATHNAME' LANGUAGE 'c'; diff --git a/contrib/spi/Makefile b/contrib/spi/Makefile index 639a6247da..efc99a5df9 100644 --- a/contrib/spi/Makefile +++ b/contrib/spi/Makefile @@ -1,29 +1,64 @@ +# +# $Header: /cvsroot/pgsql/contrib/spi/Makefile,v 1.13 2000/06/15 18:55:17 momjian Exp $ +# -SRCDIR= ../../src +TOPDIR=../.. -include $(SRCDIR)/Makefile.global +include ../Makefile.global -CFLAGS+= $(CFLAGS_SL) +NAME = + +PROGRAM = +OBJS = autoinc.o insert_username.o moddatetime.o refint.o timetravel.o +DOCS = spi.doc +SQLS = $(OBJS:.o=.sql) +BINS = +EXAMPLES= $(OBJS:.o=.example) +MODS = $(OBJS:.o=$(DLSUFFIX)) + +CFLAGS += -I. $(CFLAGS_SL) ifdef REFINT_VERBOSE CFLAGS+= -DREFINT_VERBOSE endif -TARGETS= refint$(DLSUFFIX) refint.sql \ - timetravel$(DLSUFFIX) timetravel.sql \ - autoinc$(DLSUFFIX) autoinc.sql \ - moddatetime$(DLSUFFIX) moddatetime.sql \ - insert_username$(DLSUFFIX) insert_username.sql +OTHER_CLEAN = $(SQLS) + +all: $(MODS) $(SQLS) + +%.sql: %.sql.in + $(SED) "s|MODULE_PATHNAME|$(CONTRIB_MODDIR)/$@|" < $< > $@ + +install: install_doc install_sql install_mod install_example + +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done -CLEANFILES+= $(TARGETS) +install_sql: + for inst_file in $(SQLS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_SQLDIR); \ + done -all:: $(TARGETS) +install_mod: + for inst_file in $(MODS); do \ + $(INSTALL) $(INSTL_SHLIB_OPTS) $$inst_file $(CONTRIB_MODDIR); \ + done -%.sql: %.source - rm -f $@; \ - C=`pwd`; \ - sed -e "s:_OBJWD_:$$C:g" \ - -e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@ +install_example: + for inst_file in $(EXAMPLES); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_EXAMPLESDIR); \ + done + +depend dep: + $(CC) -MM -MG $(CFLAGS) *.c > depend clean: - rm -f $(TARGETS) *.o + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log + +ifeq (depend,$(wildcard depend)) +include depend +endif + + diff --git a/contrib/spi/README.MAX b/contrib/spi/README.MAX index 025ed4925e..e69de29bb2 100644 --- a/contrib/spi/README.MAX +++ b/contrib/spi/README.MAX @@ -1,109 +0,0 @@ - -Here are general trigger functions provided as workable examples -of using SPI and triggers. "General" means that functions may be -used for defining triggers for any tables but you have to specify -table/field names (as described below) while creating a trigger. - -1. refint.c - functions for implementing referential integrity. - -check_primary_key () is to used for foreign keys of a table. - - You are to create trigger (BEFORE INSERT OR UPDATE) using this -function on a table referencing another table. You are to specify -as function arguments: triggered table column names which correspond -to foreign key, referenced table name and column names in referenced -table which correspond to primary/unique key. - You may create as many triggers as you need - one trigger for -one reference. - -check_foreign_key () is to used for primary/unique keys of a table. - - You are to create trigger (BEFORE DELETE OR UPDATE) using this -function on a table referenced by another table(s). You are to specify -as function arguments: number of references for which function has to -performe checking, action if referencing key found ('cascade' - to delete -corresponding foreign key, 'restrict' - to abort transaction if foreign keys -exist, 'setnull' - to set foreign key referencing primary/unique key -being deleted to null), triggered table column names which correspond -to primary/unique key, referencing table name and column names corresponding -to foreign key (, ... - as many referencing tables/keys as specified -by first argument). - Note, that NOT NULL constraint and unique index have to be defined by -youself. - - There are examples in refint.example and regression tests -(sql/triggers.sql). - - To CREATE FUNCTIONs use refint.sql (will be made by gmake from -refint.source). - - - - -# Excuse me for my bad english. Massimo Lambertini -# -# -# New check foreign key -# -I think that cascade mode is to be considered like that the operation over -main table is to be made also in referenced table . -When i Delete , i must delete from referenced table , -but when i update , i update referenced table and not delete like unmodified refint.c . - -I made a new version of refint.c that when i update it check the type of modified key ( if is a text , char() i -added '') and then create a update query that do the right thing . - -For my point of view that policy is helpfull because i do not have in referenced table -loss of information . - - -In preprocessor subdir i have placed a little utility that from a SQL92 table definition, -it create all trigger for foreign key . - - -the schema that i use to analyze the problem is this - -create table -A -( key int4 not null primary key ,..., -) ; - -create table -REFERENCED_B -( key int 4 , ... , -foreign key ( key ) references A -- -); - - --- --- Trigger for REFERENCED_B --- - -CREATE INDEX I_REFERENCED_B_KEY ON REFERENCED_B ( KEY ) ; - -CREATE TRIGGER T_P_REFERENCED_B_A BEFORE INSERT OR UPDATE ON REFERENCED_B FOR EACH ROW -EXECUTE PROCEDURE -check_primary_key('KEY','A','KEY' ); - -CREATE TRIGGER T_F_D_A_REFERENCED_B BEFORE DELETE ON A FOR EACH ROW -EXECUTE PROCEDURE -check_foreign_key(1,'cascade','KEY','REFERENCED_B ','KEY' ); - -CREATE TRIGGER T_F_U_A_REFERENCED_B AFTER UPDATE ON A FOR EACH ROW -EXECUTE PROCEDURE -check_foreign_key(1,'cascade','KEY','REFERENCED_B ','KEY' ); - --- ******************************** - -I write TRIGGER T_F_U_A_REFERENCED_B ( AFTER ) and not BEFORE because if i set -BEFORE , when i try to modify ( update ) a key of A , i start a execution of TRIGGER T_P_REFERENCED_B_A -( check_primary_key) before the real modification of key in A , then the execution of ( check_primary_key) return -not ok. -With AFTER Clausole i modify first key of A then a update the value of referenced table REFERENCED_B. - -Try also the new_example.sql to view the modified policy. -I wish that my explain of problem is quite clear . -If there is miss understanding ( cause my bad english ) please send email to massimo.lambertini@everex.it - - - diff --git a/contrib/spi/autoinc.source b/contrib/spi/autoinc.source index 3423ec92eb..e69de29bb2 100644 --- a/contrib/spi/autoinc.source +++ b/contrib/spi/autoinc.source @@ -1,6 +0,0 @@ -DROP FUNCTION autoinc(); - -CREATE FUNCTION autoinc() - RETURNS opaque - AS '_OBJWD_/autoinc_DLSUFFIX_' - LANGUAGE 'newC'; diff --git a/contrib/spi/insert_username.source b/contrib/spi/insert_username.source index 4b7a684305..e69de29bb2 100644 --- a/contrib/spi/insert_username.source +++ b/contrib/spi/insert_username.source @@ -1,6 +0,0 @@ -DROP FUNCTION insert_username(); - -CREATE FUNCTION insert_username() - RETURNS opaque - AS '_OBJWD_/insert_username_DLSUFFIX_' - LANGUAGE 'newC'; diff --git a/contrib/spi/moddatetime.source b/contrib/spi/moddatetime.source index 2aafedb38b..e69de29bb2 100644 --- a/contrib/spi/moddatetime.source +++ b/contrib/spi/moddatetime.source @@ -1,6 +0,0 @@ -DROP FUNCTION moddatetime(); - -CREATE FUNCTION moddatetime() - RETURNS opaque - AS '_OBJWD_/moddatetime_DLSUFFIX_' - LANGUAGE 'newC'; diff --git a/contrib/spi/refint.source b/contrib/spi/refint.source index 0432344661..e69de29bb2 100644 --- a/contrib/spi/refint.source +++ b/contrib/spi/refint.source @@ -1,14 +0,0 @@ -DROP FUNCTION check_primary_key (); -DROP FUNCTION check_foreign_key (); - -CREATE FUNCTION check_primary_key () - RETURNS opaque - AS '_OBJWD_/refint_DLSUFFIX_' - LANGUAGE 'newC' -; - -CREATE FUNCTION check_foreign_key () - RETURNS opaque - AS '_OBJWD_/refint_DLSUFFIX_' - LANGUAGE 'newC' -; diff --git a/contrib/spi/timetravel.source b/contrib/spi/timetravel.source index 8012cb93c2..e69de29bb2 100644 --- a/contrib/spi/timetravel.source +++ b/contrib/spi/timetravel.source @@ -1,12 +0,0 @@ -DROP FUNCTION timetravel(); -DROP FUNCTION set_timetravel(name, int4); - -CREATE FUNCTION timetravel() - RETURNS opaque - AS '_OBJWD_/timetravel_DLSUFFIX_' - LANGUAGE 'newC'; - -CREATE FUNCTION set_timetravel(name, int4) - RETURNS int4 - AS '_OBJWD_/timetravel_DLSUFFIX_' - LANGUAGE 'newC' WITH (isStrict); diff --git a/contrib/string/Makefile b/contrib/string/Makefile index d372aa0845..39254cf52b 100644 --- a/contrib/string/Makefile +++ b/contrib/string/Makefile @@ -1,65 +1,53 @@ -#------------------------------------------------------------------------- + # +# $Header: /cvsroot/pgsql/contrib/string/Attic/Makefile,v 1.8 2000/06/15 18:55:21 momjian Exp $ # -# Makefile -- -# -# Makefile for string I/O module. -# -#------------------------------------------------------------------------- - -PGDIR = ../.. -SRCDIR = $(PGDIR)/src - -include $(SRCDIR)/Makefile.global - -CFLAGS += -I. $(CFLAGS_SL) -MODNAME = string_io +TOPDIR=../.. -SQLDEFS = $(MODNAME).sql +include ../Makefile.global -MODULE = $(MODNAME)$(DLSUFFIX) +NAME = string_io -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 -$(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/string/README b/contrib/string/README new file mode 100644 index 0000000000..4b4d10166f --- /dev/null +++ b/contrib/string/README @@ -0,0 +1,23 @@ +String io module 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. + + +These output functions can be used as substitution of the standard text +output functions to get the value of text fields printed in the format +used for C strings. This allows the output of queries or the exported +files to be processed more easily using standard unix filter programs +like perl or awk. + +If you use the standard functions instead you could find a single tuple +splitted into many lines and the tabs embedded in the values could be +confused with those used as field delimters. + +My function translates all non-printing characters into corresponding +esacape sequences as defined by the C syntax. All you need to reconstruct +the exact value in your application is a corresponding unescape function +like the string_input defined in the source code. + +Massimo Dal Zotto diff --git a/contrib/tools/Makefile b/contrib/tools/Makefile index 95e97d72ba..9b7d8a29f3 100644 --- a/contrib/tools/Makefile +++ b/contrib/tools/Makefile @@ -1,21 +1,21 @@ -#------------------------------------------------------------------------- # -# Makefile -- +# $Header: /cvsroot/pgsql/contrib/tools/Attic/Makefile,v 1.2 2000/06/15 18:55:22 momjian Exp $ # -# Makefile for contrib tools. -# -#------------------------------------------------------------------------- -PGDIR = ../.. -SRCDIR = $(PGDIR)/src +TOPDIR=../.. -include $(SRCDIR)/Makefile.global +include ../Makefile.global -all: +NAME = -install: +PROGRAM = +OBJS = +DOCS = +SQLS = +BINS = +EXAMPLES= +MODS = clean: - rm -f *~ + $(RM) *~ -distclean: clean diff --git a/contrib/userlock/Makefile b/contrib/userlock/Makefile index 983f20a547..35f748e7c2 100644 --- a/contrib/userlock/Makefile +++ b/contrib/userlock/Makefile @@ -1,65 +1,52 @@ -#------------------------------------------------------------------------- # -# Makefile -- +# $Header: /cvsroot/pgsql/contrib/userlock/Attic/Makefile,v 1.8 2000/06/15 18:55:28 momjian Exp $ # -# Makefile for the user_locks module. -# -#------------------------------------------------------------------------- - -PGDIR = ../.. -SRCDIR = $(PGDIR)/src - -include $(SRCDIR)/Makefile.global - -CFLAGS += -I. $(CFLAGS_SL) - -MODNAME = user_locks -SQLDEFS = $(MODNAME).sql +TOPDIR=../.. -MODULE = $(MODNAME)$(DLSUFFIX) +include ../Makefile.global -MODDIR = $(LIBDIR)/modules +NAME = user_locks -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/userlock/README b/contrib/userlock/README new file mode 100644 index 0000000000..4c923a4657 --- /dev/null +++ b/contrib/userlock/README @@ -0,0 +1,55 @@ +User locks, 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, together with my user-lock.patch applied to the +backend, provides support for user-level long-term cooperative locks. +For example one can write: + + select some_fields, user_write_lock_oid(oid) from table where id='key'; + +Now if the returned user_write_lock_oid field is 1 you have acquired an +user lock on the oid of the selected tuple and can now do some long operation +on it, like let the data being edited by the user. +If it is 0 it means that the lock has been already acquired by some other +process and you should not use that item until the other has finished. +Note that in this case the query returns 0 immediately without waiting on +the lock. This is good if the lock is held for long time. +After you have finished your work on that item you can do: + + update table set some_fields where id='key'; + select user_write_unlock_oid(oid) from table where id='key'; + +You can also ignore the failure and go ahead but this could produce conflicts +or inconsistent data in your application. User locks require a cooperative +behavior between users. User locks don't interfere with the normal locks +used by postgres for transaction processing. + +This could also be done by setting a flag in the record itself but in +this case you have the overhead of the updates to the records and there +could be some locks not released if the backend or the application crashes +before resetting the lock flag. +It could also be done with a begin/end block but in this case the entire +table would be locked by postgres and it is not acceptable to do this for +a long period because other transactions would block completely. + +The generic user locks use two values, group and id, to identify a lock, +which correspond to ip_posid and ip_blkid of an ItemPointerData. +Group is a 16 bit value while id is a 32 bit integer which could also be +an oid. The oid user lock functions, which take only an oid as argument, +use a group equal to 0. + +The meaning of group and id is defined by the application. The user +lock code just takes two numbers and tells you if the corresponding +entity has been succesfully locked. What this mean is up to you. + +My succestion is that you use the group to identify an area of your +application and the id to identify an object in this area. +Or you can just lock the oid of the tuples which are by definition unique. + +Note also that a process can acquire more than one lock on the same entity +and it must release the lock the corresponding number of times. This can +be done calling the unlock funtion until it returns 0. diff --git a/contrib/vacuumlo/Makefile b/contrib/vacuumlo/Makefile index c9484024b5..1e67847b5a 100644 --- a/contrib/vacuumlo/Makefile +++ b/contrib/vacuumlo/Makefile @@ -1,24 +1,48 @@ -# $Header: /cvsroot/pgsql/contrib/vacuumlo/Makefile,v 1.2 2000/05/29 05:44:32 tgl Exp $ +# +# $Header: /cvsroot/pgsql/contrib/vacuumlo/Makefile,v 1.3 2000/06/15 18:55:31 momjian Exp $ +# -SRCDIR= ../../src +TOPDIR=../.. -include $(SRCDIR)/Makefile.global +include ../Makefile.global -CONTRIBDIR=$(LIBDIR)/contrib +NAME = vacuumlo -CFLAGS+= -I$(LIBPQDIR) +PROGRAM = $(NAME) +OBJS = $(NAME).o +DOCS = $(NAME).doc +SQLS = +BINS = $(PROGRAM) +EXAMPLES= +MODS = -TARGETS= vacuumlo -CLEANFILES+= $(TARGETS) -CURDIR=`pwd` +CFLAGS += -I$(LIBPQDIR) -all:: $(TARGETS) +OTHER_CLEAN = -$(TARGETS): vacuumlo.o - $(CC) -o vacuumlo -L $(LIBDIR) -lpq -lcrypt vacuumlo.o +all: $(PROGRAM) -clean: - rm -f $(TARGETS) *.o +$(PROGRAM): $(OBJS) $(LIBPGEASYDIR)/libpgeasy.a + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPGEASY) -dist: - tar cf vacuumlo.tar README Makefile vacuumlo.c +install: install_doc install_bin + +install_doc: + for inst_file in $(DOCS); do \ + $(INSTALL) $(INSTL_LIB_OPTS) $$inst_file $(CONTRIB_DOCDIR); \ + done + +install_bin: + for inst_file in $(BINS); do \ + $(INSTALL) $(INSTL_EXE_OPTS) $$inst_file $(CONTRIB_BINDIR); \ + done + +depend dep: + $(CC) -MM -MG $(CFLAGS) *.c > depend + +clean: + $(RM) *~ $(OBJS) $(MODS) $(PROGRAM) depend $(OTHER_CLEAN) core log + +ifeq (depend,$(wildcard depend)) +include depend +endif diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c index 7a0d6d6264..ac41d551c3 100644 --- a/contrib/vacuumlo/vacuumlo.c +++ b/contrib/vacuumlo/vacuumlo.c @@ -8,13 +8,13 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.3 2000/01/26 05:55:52 momjian Exp $ + * $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.4 2000/06/15 18:55:31 momjian Exp $ * *------------------------------------------------------------------------- */ #include #include -#include +#include #include #include diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 4626d666c1..399f30e4e8 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -7,7 +7,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.77 2000/06/11 11:39:47 petere Exp $ +# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.78 2000/06/15 18:55:34 momjian Exp $ # # NOTES # Essentially all Postgres make files include this file and use the @@ -54,10 +54,12 @@ BSD_SHLIB= true ELF_SYSTEM= @ELF_SYS@ LIBPQDIR= $(SRCDIR)/interfaces/libpq +LIBPGEASYDIR= $(SRCDIR)/interfaces/libpgeasy LIBPGTCLDIR= $(SRCDIR)/interfaces/libpgtcl LIBPQ= -L$(LIBPQDIR) -lpq LIBPGTCL= -L$(LIBPGTCLDIR) -lpgtcl +LIBPGEASY= -L$(LIBPGEASYDIR) -lpgeasy # For convenience, POSTGRESDIR is where BINDIR, and LIBDIR # and other target destinations are rooted. Of course, each of these is -- 2.40.0