diff --git a/contrib/mysql/my2pg.pl b/contrib/mysql/my2pg.pl index 82e368f..283f679 100755 --- a/contrib/mysql/my2pg.pl +++ b/contrib/mysql/my2pg.pl @@ -39,7 +39,10 @@ # $Id$ # -# $Log: my2pg.pl,v $ +# $Log$ +# Revision 1.10 2003-01-07 22:18:43 momjian +# Upgrade to my2pg 1.9 +# # Revision 1.27 2002/07/16 14:54:07 fonin # Bugfix - didn't quote the fields inside PRIMARY KEY with -d option. # Fix by Milan P. Stanic . @@ -731,7 +734,7 @@ close(LIBTYPES); open(MAKE,">Makefile"); print MAKE "# -# My2Pg \$Revision: 1.10 $ \translated dump +# My2Pg \$Revision$ \translated dump # Makefile # diff --git a/contrib/pgcrypto/blf.c b/contrib/pgcrypto/blf.c index 06040d3..da2047b 100644 --- a/contrib/pgcrypto/blf.c +++ b/contrib/pgcrypto/blf.c @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $OpenBSD: blf.c,v 1.3 2000/06/17 23:36:22 provos Exp $ */ /* * Blowfish block cipher for OpenBSD diff --git a/contrib/pgcrypto/blf.h b/contrib/pgcrypto/blf.h index 7ee728e..81159b1 100644 --- a/contrib/pgcrypto/blf.h +++ b/contrib/pgcrypto/blf.h @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $OpenBSD: blf.h,v 1.3 2001/05/15 02:40:35 deraadt Exp $ */ /* * Blowfish - a fast block cipher designed by Bruce Schneier diff --git a/contrib/pgcrypto/crypt-des.c b/contrib/pgcrypto/crypt-des.c index 38bce17..8be5640 100644 --- a/contrib/pgcrypto/crypt-des.c +++ b/contrib/pgcrypto/crypt-des.c @@ -36,7 +36,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: src/secure/lib/libcrypt/crypt-des.c,v 1.12 1999/09/20 12:39:20 markm Exp $ * * This is an original implementation of the DES and the crypt(3) interfaces * by David Burren . diff --git a/contrib/pgcrypto/crypt-md5.c b/contrib/pgcrypto/crypt-md5.c index 3c51fc3..e900d40 100644 --- a/contrib/pgcrypto/crypt-md5.c +++ b/contrib/pgcrypto/crypt-md5.c @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $FreeBSD$ + * $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $ * */ /* $Id$ */ diff --git a/contrib/pgcrypto/md5.c b/contrib/pgcrypto/md5.c index e66e21a..5b749b8 100644 --- a/contrib/pgcrypto/md5.c +++ b/contrib/pgcrypto/md5.c @@ -1,5 +1,5 @@ /* $Id$ */ -/* $KAME$ */ +/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. diff --git a/contrib/pgcrypto/md5.h b/contrib/pgcrypto/md5.h index 11435fa..63ceae0 100644 --- a/contrib/pgcrypto/md5.h +++ b/contrib/pgcrypto/md5.h @@ -1,5 +1,5 @@ /* $Id$ */ -/* $KAME$ */ +/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. diff --git a/contrib/pgcrypto/misc.c b/contrib/pgcrypto/misc.c index 734ad9f..5c803c0 100644 --- a/contrib/pgcrypto/misc.c +++ b/contrib/pgcrypto/misc.c @@ -26,7 +26,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: src/lib/libcrypt/misc.c,v 1.1 1999/09/20 12:45:49 markm Exp $ * */ diff --git a/contrib/pgcrypto/rijndael.c b/contrib/pgcrypto/rijndael.c index 72611a7..8b2b99f 100644 --- a/contrib/pgcrypto/rijndael.c +++ b/contrib/pgcrypto/rijndael.c @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */ /* This is an independent implementation of the encryption algorithm: */ /* */ diff --git a/contrib/pgcrypto/rijndael.h b/contrib/pgcrypto/rijndael.h index aab1f51..41c1a2a 100644 --- a/contrib/pgcrypto/rijndael.h +++ b/contrib/pgcrypto/rijndael.h @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */ /* This is an independent implementation of the encryption algorithm: */ /* */ diff --git a/contrib/pgcrypto/sha1.c b/contrib/pgcrypto/sha1.c index 5be954d..9c40f61 100644 --- a/contrib/pgcrypto/sha1.c +++ b/contrib/pgcrypto/sha1.c @@ -1,5 +1,5 @@ /* $Id$ */ -/* $KAME$ */ +/* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. diff --git a/contrib/pgcrypto/sha1.h b/contrib/pgcrypto/sha1.h index fcbcb17..53d94a4 100644 --- a/contrib/pgcrypto/sha1.h +++ b/contrib/pgcrypto/sha1.h @@ -1,5 +1,5 @@ /* $Id$ */ -/* $KAME$ */ +/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. diff --git a/contrib/reindexdb/reindexdb b/contrib/reindexdb/reindexdb index 7db6a26..2b2aeb9 100644 --- a/contrib/reindexdb/reindexdb +++ b/contrib/reindexdb/reindexdb @@ -1,6 +1,6 @@ #!/bin/sh # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # -# Package : reindexdb Version : $Revision: 1.5 $ +# Package : reindexdb Version : $Revision$ # Date : 05/08/2002 Author : Shaun Thomas # Req : psql, sh, perl, sed Type : Utility # diff --git a/contrib/spi/README.timetravel b/contrib/spi/README.timetravel new file mode 100644 index 0000000..0b4727f --- /dev/null +++ b/contrib/spi/README.timetravel @@ -0,0 +1,116 @@ +2. timetravel.c - functions for implementing time travel feature. + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +I rewritten this, because: + +on original version of postgresql 7.3.2-7.3.3: + +the UPDATE not work on timetravel.example if I added +>create unique index tttest_idx on tttest (price_id,price_off); +>update tttest set price_val = 30 where price_id = 3; +ERROR: Cannot insert a duplicate key into unique index tttest_idx + +And UPDATE not work on table tttest after +>alter table tttest add column q1 text; +>alter table tttest add column q2 int; +>alter table tttest drop column q1; +>update tttest set price_val = 30 where price_id = 3; +ERROR: Parameter '$5' is out of range + +And I add a new optional feature: my new timetravel have +3 optional parameters: +inserter_user, updater_user, deleter_user. + +And I add a new function: get_timetravel for get timetravel status +without change it. + +A big difference: +the old version on UPDATE changed oid on active ('infinity') record, +the new version UPDATE keep oid, and the overdued record have a new oid. +I sign with '!!!' my comment in this file. +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + Old internally supported time-travel (TT) used insert/delete +transaction commit times. To get the same feature using triggers +you are to add to a table two columns of abstime type to store +date when a tuple was inserted (start_date) and changed/deleted +(stop_date): + +CREATE TABLE XXX ( + ... ... + date_on abstime default currabstime(), + date_off abstime default 'infinity' + ... ... +/* !!! and (if have) */ + ins_user text /* user, who insert this record */ + upd_user text /* user, who updated this record */ + del_user text /* user, who deleted this record */ + ... ... +); + +!!! on INSERT my new version: + ... and optionally set ins_user to current user, upd_user and del_user to null. + +- so, tuples being inserted with NULLs in date_on/date_off will get +_current_date_ in date_on (name of start_date column in XXX) and INFINITY in +date_off (name of stop_date column in XXX). + + Tuples with stop_date equal INFINITY are "valid now": when trigger will +be fired for UPDATE/DELETE of a tuple with stop_date NOT equal INFINITY then +this tuple will not be changed/deleted! + + If stop_date equal INFINITY then on + +UPDATE: +original version was: + only stop_date in tuple being updated will be changed to current + date and new tuple with new data (coming from SET ... in UPDATE) will be + inserted. Start_date in this new tuple will be setted to current date and + stop_date - to INFINITY. +On my new version: + insert a new tuple with old values, but stop_date changed to current date; + and update original tuple with new data, and update start_date to current date + and optionally set upd_user to current user and clear ins_user,del_user. + +DELETE: new tuple will be inserted with stop_date setted to current date +(and with the same data in other columns as in tuple being deleted). +On my new version: + ... and optionally set del_user to current user. + + NOTE: +1. To get tuples "valid now" you are to add _stop_date_ = 'infinity' + to WHERE. Internally supported TT allowed to avoid this... + Fixed rewriting RULEs could help here... + As work arround you may use VIEWs... +2. You can't change start/stop date columns with UPDATE! + Use set_timetravel (below) if you need in this. + + FUNCTIONs: + +timetravel() is general trigger function. + + You are to create trigger BEFORE UPDATE OR DELETE using this +function on a time-traveled table. You are to specify two arguments: name of +start_date column and name of stop_date column in triggered table. +Or add +3 arguments: + name of insert_user column, name of update_user column, name of delete_user column + +currabstime() may be used in DEFAULT for start_date column to get +current date. +!!! I deleted this function, because I newer used this. + +set_timetravel() allows you turn time-travel ON/OFF for a table: + + set_timetravel('XXX', 1) will turn TT ON for table XXX (and report +old status). + set_timetravel('XXX', 0) will turn TT OFF for table XXX (-"-). + +Turning TT OFF allows you do with a table ALL what you want. + +get_timetravel() reports time-travel status ON(1)/OFF(0) for a table. +get_timetravel() and set_timetravel() not checking existing of table and +existing of timetravel trigger on specified table. + + There is example in timetravel.example. + + To CREATE FUNCTIONs use timetravel.sql (will be made by gmake from +timetravel.source). diff --git a/contrib/tsearch2/README.tsearch2 b/contrib/tsearch2/README.tsearch2 new file mode 100644 index 0000000..e018073 --- /dev/null +++ b/contrib/tsearch2/README.tsearch2 @@ -0,0 +1,210 @@ +Tsearch2 - full text search extension for PostgreSQL + + [10][Online version] of this document is available + + This module is sponsored by Delta-Soft Ltd., Moscow, Russia. + + Notice: This version is fully incompatible with old tsearch (V1), + which is considered as deprecated in upcoming 7.4 release and + obsoleted in 7.5. + + The Tsearch2 contrib module contains an implementation of a new data + type tsvector - a searchable data type with indexed access. In a + nutshell, tsvector is a set of unique words along with their + positional information in the document, organized in a special + structure optimized for fast access and lookup. Actually, each word + entry, besides its position in the document, could have a weight + attribute, describing importance of this word (at a specific) position + in document. A set of bit-signatures of a fixed length, representing + tsvectors, are stored in a search tree (developed using PostgreSQL + GiST), which provides online update of full text index and fast query + lookup. The module provides indexed access methods, queries, + operations and supporting routines for the tsvector data type and easy + conversion of text data to tsvector. Table driven configuration allows + creation of custom configuration optimized for specific searches using + standard SQL commands. + + Configuration allows you to: + * specify the type of lexemes to be indexed and the way they are + processed. + * specify dictionaries to be used along with stop words recognition. + * specify the parser used to process a document. + + See [11]Documentation Roadmap for links to documentation. + +OpenFTS vs Tsearch2 + + OpenFTS is a middleware between application and database, so it uses + tsearch2 as a storage, while database engine is used as a query executor + (searching). Everything else (parsing of documents, query processing, + linguistics) carry outs on client side. That's why OpenFTS has its own + configuration table (fts_conf) and works with its own set of dictionaries. + OpenFTS is more flexible, because it could be used in multi-server + architecture with separated machines for repository of documents + (documents could be stored in file system), database and query engine. + +Authors + + * Oleg Bartunov , Moscow, Moscow University, Russia + * Teodor Sigaev , Moscow, Delta-Soft Ltd.,Russia + +Contributors + + * Robert John Shepherd and Andrew J. Kopciuch submitted + "Introduction to tsearch" (Robert - tsearch v1, Andrew - tsearch + v2) + * Brandon Craig Rhodes wrote "Tsearch2 Guide" and "Tsearch2 + Reference" and proposed new naming convention for tsearch V2 + +New features + + * Relevance ranking of search results + * Table driven configuration + * Morphology support (ispell dictionaries, snowball stemmers) + * Headline support (text fragments with highlighted search terms) + * Ability to plug-in custom dictionaries and parsers + * Synonym dictionary + * Generator of templates for dictionaries (built-in snowball stemmer + support) + * Statistics of indexed words is available + +Limitations + + * Lexeme should be not longer than 2048 bytes + * The number of lexemes is limited by 2^32. Note, that actual + capacity of tsvector is depends on whether positional information + is stored or not. + * tsvector - the size is limited by approximately 2^20 bytes. + * tsquery - the number of entries (lexemes and operations) < 32768 + * Positional information + + maximal position of lexeme < 2^14 (16384) + + lexeme could have maximum 256 positions + +References + + * GiST development site - + [12]http://www.sai.msu.su/~megera/postgres/gist + * OpenFTS home page - [13]http://openfts.sourceforge.net/ + * Mailing list - + [14]http://sourceforge.net/mailarchive/forum.php?forum=openfts-gen + eral + + [15]Documentation Roadmap + +Documentation Roadmap + + * Several docs are available from docs/ subdirectory + + "Tsearch V2 Introduction" by Andrew Kopciuch + + "Tsearch2 Guide" by Brandon Rhodes + + "Tsearch2 Reference" by Brandon Rhodes + * Readme.gendict in gendict/ subdirectory + + [16][Gendict tutorial] + + Online version of documentation is always available from Tsearch V2 + home page - + [17]http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/ + +Support + + Authors urgently recommend people to use [18][openfts-general] or + [19][pgsql-general] mailing lists for questions and discussions. + +Caution + + In spite of apparent easy full text searching with our tsearch module + (authors hope it's so), any serious search engine require profound + study of various aspects, such as stop words, dictionaries, special + parsers. Tsearch module was designed to facilitate both those cases. + +Development History + + Pre-tsearch era + Development of OpenFTS began in 2000 after realizing that we + needed a search engine optimized for online updates and able to + access metadata from the database. This is essential for online + news agencies, web portals, digital libraries, etc. Most search + engines available utilize an inverted index which is very fast + for searching but very slow for online updates. Incremental + updates of an inverted index is a complex engineering task + while we needed something light, free and with the ability to + access metadata from the database. The last requirement is very + important because in a real life application a search engine + should always consult metadata ( topic, permissions, date + range, version, etc.). We extensively use PostgreSQL as a + database backend and have no intention to move from it, so the + problem was to find a data structure and a fast way to access + it. PostgreSQL has rather unique data type for storing sets + (think about words) - arrays, but lacks index access to them. A + document is parsed into lexemes, which are identified in + various ways (e.g. stemming, morphology, dictionary), and as a + result is reduced to an array of integer numbers. During our + research we found a paper of Joseph Hellerstein which + introduced an interesting data structure suitable for sets - + RD-tree (Russian Doll tree). It looked very attractive, but + implementing it in PostgreSQL seemed difficult because of our + ignorance of database internals. Further research lead us to + the idea to use GiST for implementing RD-tree, but at that time + the GiST code had for a long while remained untouched and + contained several bugs. After work on improving GiST for + version 7.0.3 of PostgreSQL was done, we were able to implement + RD-Tree and use it for index access to arrays of integers. This + implementation was ideally suited for small arrays and + eliminated complex joins, but was practically useless for + indexing large arrays. The next improvement came from an idea + to represent a document by a single bit-signature, a so-called + superimposed signature (see "Index Structures for Databases + Containing Data Items with Set-valued Attributes", 1997, Sven + Helmer for details). We developeded the contrib/intarray module + and used it for full text indexing. + + tsearch v1 + It was inconvenient to use integer id's instead of words, so we + introduced a new data type called 'txtidx' - a searchable data + type (textual) with indexed access. This was a first step of + our work on an implementation of a built-in PostgreSQL full + text search engine. Even though tsearch v1 had many features of + a search engine it lacked configuration support and relevance + ranking. People were encouraged to use OpenFTS, which provided + relevance ranking based on coordinate information and flexible + configuration. OpenFTS v.0.34 is the last version based on + tsearch v1. + + tsearch V2 + People recognized tsearch as a powerful tool for full text + searching and insisted on adding ranking support, better + configurability, etc. We already thought about moving most of + the features of OpenFTS to tsearch, and in the early 2003 we + decided to work on a new version of tsearch - tsearch v2. We've + abandoned auxiliary index tables which were used by OpenFTS to + store coordinate information and modified the txtidx type to + store them internally. Also, we've added table-driven + configuration, support of ispell dictionaries, snowball + stemmers and the ability to specify which types of lexemes to + index. Also, it's now possible to generate headlines of + documents with highlighted search terms. These changes make + tsearch more user friendly and turn it into a really powerful + full text search engine. After announcing the alpha version, we + received a proposal from Brandon Rhodes to rename tsearch + functions to be more consistent. So, we have renamed txtidx + type to tsvector and other things as well. + + To allow users of tsearch v1 smooth upgrade, we named the module as + tsearch2. + + Future release of OpenFTS (v.0.35) will be based on tsearch2. Brave + people could download it from OpenFTS CVS (see link from [20][OpenFTS + page] + +References + + 10. http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/docs/Tsearch_V2_Readme.html + 11. http://www.sai.msu.su/~megera/oddmuse/index.cgi/Tsearch_V2_Readme#Documentation_Roadmap + 12. http://www.sai.msu.su/~megera/postgres/gist + 13. http://openfts.sourceforge.net/ + 14. http://sourceforge.net/mailarchive/forum.php?forum=openfts-general + 15. http://www.sai.msu.su/~megera/oddmuse/index.cgi?action=anchor&id=Documentation_Roadmap#Documentation_Roadmap + 16. http://www.sai.msu.su/~megera/oddmuse/index.cgi?Gendict + 17. http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/ + 18. http://sourceforge.net/mailarchive/forum.php?forum=openfts-general + 19. http://archives.postgresql.org/pgsql-general/ + 20. http://openfts.sourceforge.net/ diff --git a/contrib/tsearch2/common.c b/contrib/tsearch2/common.c new file mode 100644 index 0000000..3006218 --- /dev/null +++ b/contrib/tsearch2/common.c @@ -0,0 +1,102 @@ +#include "postgres.h" +#include "common.h" +#include "wparser.h" +#include "ts_cfg.h" +#include "dict.h" + +text * +char2text(char *in) +{ + return charl2text(in, strlen(in)); +} + +text * +charl2text(char *in, int len) +{ + text *out = (text *) palloc(len + VARHDRSZ); + + memcpy(VARDATA(out), in, len); + VARATT_SIZEP(out) = len + VARHDRSZ; + return out; +} + +char + * +text2char(text *in) +{ + char *out = palloc(VARSIZE(in)); + + memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ); + out[VARSIZE(in) - VARHDRSZ] = '\0'; + return out; +} + +char + * +pnstrdup(char *in, int len) +{ + char *out = palloc(len + 1); + + memcpy(out, in, len); + out[len] = '\0'; + return out; +} + +text + * +ptextdup(text *in) +{ + text *out = (text *) palloc(VARSIZE(in)); + + memcpy(out, in, VARSIZE(in)); + return out; +} + +text + * +mtextdup(text *in) +{ + text *out = (text *) malloc(VARSIZE(in)); + + if (!out) + ts_error(ERROR, "No memory"); + memcpy(out, in, VARSIZE(in)); + return out; +} + +void +ts_error(int state, const char *format,...) +{ + va_list args; + int tlen = 128, + len = 0; + char *buf; + + reset_cfg(); + reset_dict(); + reset_prs(); + + va_start(args, format); + buf = palloc(tlen); + len = vsnprintf(buf, tlen - 1, format, args); + if (len >= tlen) + { + tlen = len + 1; + buf = repalloc(buf, tlen); + vsnprintf(buf, tlen - 1, format, args); + } + va_end(args); + + /* ?? internal error ?? */ + elog(state, "%s", buf); + pfree(buf); +} + +int +text_cmp(text *a, text *b) +{ + if (VARSIZE(a) == VARSIZE(b)) + return strncmp(VARDATA(a), VARDATA(b), VARSIZE(a) - VARHDRSZ); + return (int) VARSIZE(a) - (int) VARSIZE(b); + +} diff --git a/contrib/tsearch2/common.h b/contrib/tsearch2/common.h new file mode 100644 index 0000000..481f004 --- /dev/null +++ b/contrib/tsearch2/common.h @@ -0,0 +1,24 @@ +#ifndef __TS_COMMON_H__ +#define __TS_COMMON_H__ +#include "postgres.h" +#include "fmgr.h" + +#ifndef PG_NARGS +#define PG_NARGS() (fcinfo->nargs) +#endif + +text *char2text(char *in); +text *charl2text(char *in, int len); +char *text2char(text *in); +char *pnstrdup(char *in, int len); +text *ptextdup(text *in); +text *mtextdup(text *in); + +int text_cmp(text *a, text *b); + +#define NEXTVAL(x) ( (text*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) ) +#define ARRNELEMS(x) ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x)) + +void ts_error(int state, const char *format,...); + +#endif diff --git a/contrib/tsearch2/crc32.c b/contrib/tsearch2/crc32.c new file mode 100644 index 0000000..dc93db7 --- /dev/null +++ b/contrib/tsearch2/crc32.c @@ -0,0 +1,103 @@ +/* Both POSIX and CRC32 checksums */ + +#include +#include +#include + +#include "crc32.h" + +/* + * This code implements the AUTODIN II polynomial + * The variable corresponding to the macro argument "crc" should + * be an unsigned long. + * Oroginal code by Spencer Garrett + */ + +#define _CRC32_(crc, ch) (crc = (crc >> 8) ^ crc32tab[(crc ^ (ch)) & 0xff]) + +/* generated using the AUTODIN II polynomial + * x^32 + x^26 + x^23 + x^22 + x^16 + + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 + */ + +static const unsigned int crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +unsigned int +crc32_sz(char *buf, int size) +{ + unsigned int crc = ~0; + char *p; + int len, + nr; + + len = 0; + nr = size; + for (len += nr, p = buf; nr--; ++p) + _CRC32_(crc, *p); + return ~crc; +} diff --git a/contrib/tsearch2/crc32.h b/contrib/tsearch2/crc32.h new file mode 100644 index 0000000..97254a4 --- /dev/null +++ b/contrib/tsearch2/crc32.h @@ -0,0 +1,10 @@ +#ifndef _CRC32_H +#define _CRC32_H + +/* Returns crc32 of data block */ +extern unsigned int crc32_sz(char *buf, int size); + +/* Returns crc32 of null-terminated string */ +#define crc32(buf) crc32_sz((buf),strlen(buf)) + +#endif diff --git a/contrib/tsearch2/data/test_tsearch.data b/contrib/tsearch2/data/test_tsearch.data new file mode 100644 index 0000000..29a26f2 --- /dev/null +++ b/contrib/tsearch2/data/test_tsearch.data @@ -0,0 +1,508 @@ +\n +\n +\n +\n +\n +\n +\n +\n +\n i8 hy qo xa jl wr le l5 ja jx zf ro vw wd wa cc mm wh fn yd td l8 ec rv th oc ix ir sm y4 gh pr qg ue cx ww zv c9 zv tx eo f5 gd km b9 wb rm ym yl xj u7 xz uk iq tm ux di if uc hc ge +\n gr ty ph jh po wa iw ag wq r3 yd ow rb ip et ej yl a9 dk pu y6 su ov hf xe qe sd qr zt kp ml ea tp pg dq e3 s3 hh gn hz j7 hb qs qd v0 v4 w0 nu ee wk ez un rd sz wx e7 pn yf gh uh ki kx rb qv f1 bh sr yj ry r2 +\n q1 q8 wp w9 vs ww rq de qt wo qp sa rv mc sn u8 yl +\n hv ra sa fr qs ps 4w z5 ls wt ad wy q6 zg bd vt wa e4 ft w7 ld es yg et ic pm sw ja qv ov jm ma b3 wu wi qy ug hs wh ex rt tj en ur e2 ut gv as ui dy qy du qo gv cy lx kw xm fl x2 hd ny nu hh dt wg wh rs wb wz yy yu tj ha ak rw sw io h1 ux ku v6 wc qa rv xb s8 qd f2 zo k2 ew w4 yh yu yi +\n rs tt gp qh wt q6 lg zh vr b8 uy uu lh px jm ww qe xu fp fd rs qu ki dr fn gq gw jv oq zt 2r lc ke wg l9 x3 x5 7g vs ar e7 u2 s8 t0 av dj kl nm u2 zp gf yw ee oc tw a1 +\n qs uz wr gq q9 rl e0 pe dj a9 hp qw aw er kq pp uu pl zo wp fr r6 ej pv u5 hh av lw ko qc pn qj ez n8 wn eu tq +\n po h9 rd qs hr la u0 um me wp 0p rl mv rc ab r0 fe fj fk qn jh iy cn lb bl ln b5 ll yg yh qt qp uz od dq as gn cr qa wa cu fy zy vo xk eq vg mr ns yy t7 yi op th yo ov pv em tc hg az io s5 ct os wu lq dr mp hk si gx +\n hm k5 pw a5 qh nb q3 ql wr wt z7 oz wu wh kv q8 c3 mt mg hb a3 rz pz uo y1 rb av us ek dz q0 d3 qw j2 ls wy qq jf ng eo gl ed ix em he qt du hp jc f2 m9 qp hb l4 gy zf l6 qr dn cp x1 oh qk kk s3 hy wg zs ot wj sl oz ie e9 ay it u5 ai hm gh py hz qk ki h8 ja zu qb ei vc qj hg ev h6 yh u0 tb id +\n qg d1 bt c5 r3 iv g6 d7 rc ml gk uh yn y0 zo uh qd wh ib uo u4 om qg ql yz +\n hb a3 q5 pl yj lo qy ki sy fo rj kk zq dl wn 7a zi wn wm yr w3 tv r1 +\n ft k6 iz qn qj q2 q3 bl zd av ro wo lk tg ea ew ed y1 ia yl ic g6 po aw sc zm qn gl wq qw zr jp wt j5 gs vt qt yc rr op yw tl ye hr i8 tb uu j0 xd lz vu nl qd fu wg pf wj bt ee wh t2 tp sz um oo tg ha u4 f5 sw pq pr ju qk mh ki zb vj ob cx df hj ef cj q6 u9 tv rv o4 sy ru fq ir +\n ps ko uk tz vv um t9 uk k2 ja o6 ob +\n qs nb gh ld q7 jc sp el w0 py qx i2 qe la rl qw tu ti dq ue iv oi wa qr ed t3 fg oa of rr fv qz xn wu wq te hx +\n yb ty pq az fi qg qn la bu ji lg wg q8 mi cv rl up lg om oq ym pv in aq gg js ha on ww qr bj vn pv he b5 mh qe cc mk qt rb eu qy rw tr qo ec op sn oh e2 ao iv e4 hy dt s6 qt p1 hb ih qs wg x1 bd l1 t1 ro r9 uv wb aw gu os t0 ah e0 s0 hj pe or qj zz ql fd ks qv bq qm bg ec ry oj u8 u0 yj ru r1 yx o7 +\n z4 wr qz cg nq ir bb gb w7 e5 zc pj e9 px uo fp ts aq db q9 iy qe zv xu a9 l1 mb qw tc qu fi hw ur de e4 hk lj wo wf fi ep rl wh vh ek vp oi sv rh ay hj px aa er tv do ir +\n tr o9 gb tt pp qa qs a5 ps rf q1 kj by ub ru ox co o8 ny wp wa ws rd kk b1 zc rl rz uo ts ig fh db qm q0 bg rr fu ld lr wb en nd cw vr hy rn qr en em au p8 so oh ut hz gq wp ow be ky wj dw t1 pl er wc ot na r9 wl ou un um wx iq sc e8 sn re rr f7 hz h4 ce wz qx wx kp px tl tx ai wq hf ec 6u rz og yt ok yy yp +\n sa pp a7 qm qh of je qj lo ph wt h0 ji cg z8 2v xs zl mo ik hm on tu d8 av ot pn iv ez ja qn pq wy 7r mq qu p1 tu p6 ti ur pj uy ui qo i9 qa nj xm s1 ya fb 7j ro wn t6 wz yu iq yi go en pb aj f5 hf ug uh hk av pr wl wz im ja v9 u2 ks it br wv wn se ia o5 ox ei r2 ig aj sp +\n sa tn z8 ew uo eh g8 zt wy 27 ff uh te en pd eh hv 2e wh ty oi sw xx 2p qs mx wb q3 rl eq aa eu +\n d4 ef ta zq j2 em c0 vv wf kj dw uk ql y9 rn +\n sq nm kl w8 ur kz c1 pc y1 g4 oi jv wr zy ew by se ec yn ti gq gt rd l5 ej yp tk da qz qx ir wm on q2 to ew +\n rd gu z2 kj qk bl 6d wy nw xq iu 8t ri uc kq nx ql oa vi kd o6 +\n ra gr he wy q0 ow ti ia pb ha qr lv ms qu pu qw qr ml qt ep sv i5 of fm oe nl xh x1 xz u4 ha ao fc ug pw nh n9 qv kh vx uq w1 u0 ei if +\n q1 d2 qz zd jd qb wj nt ah mj ea ed y1 et fj qe en b8 ty iv ht fv tn tm sg jb ky ai en us tl ud iu zj ql u1 ci ru iw tw +\n fr ub h9 pd ub jk vh z6 wu wh wp 5z yt w9 w0 uy om tl rc r6 ax d7 et y2 tw dz se vf ii m3 lf b4 jf vr qw qy uf es qp en tl to ye ue ph e3 uy i0 jl pz oe qo zp wp ft ka zf qd wd kr qf l9 mm wf qx ef t3 x8 ex rg ev s8 ys it da rw al hn tc f6 fv nd nc ad fj nr x0 bx yq ti rx ok tb hx o8 dp +\n o0 jq un xu q8 wo qq gg ta oj ec az dl bl wb +\n o9 ij pq gu gp nv qk gg la q4 nw bo z8 9a iw wu q8 eh wi nt jk ut ys c1 r5 up y1 yl py oy ht gd td db qn cz qw lp re c7 dh j5 ia bz dj qr qt wd wf qi rt sv ul uz tl ta yr e4 tm sg pc jv hc hv lc xg xm br vf r8 na wl ou td wc up rj s8 e8 ir ys ii qk p0 lt ho wb x8 bv lw w1 rz ew aa rv ry gx o8 +\n tt hn gn un db fu uq qf d4 q3 pp ji lf wu bx q8 hx kb ny t5 bn hb ex yf ef yj g1 g2 to yk g3 ej sk hy dv qc gj qv sy bg wr na wy bx z0 rc rm ml ug te qp i5 ue oj s4 im oq qt gx sa gt l4 sv at v3 bq mv wd x3 80 x8 aq xk rg yp en gs us dq ak tz al tx o2 dg f9 kv or h4 jy k1 jo h8 kp lt os kh as tn eu ul tm su an tw sp +\n za yi pe sh pv y4 y5 hy th jg qy qt ke ti ue qk yy ie cq wl p0 lw mf er w5 +\n k9 bt xu kc me is o5 z9 kb gv ur rc oe sk qn ve wi mm rn eu to ue uy qa xf by t1 td t7 aw up yf pr dk cg zr sc 3d at rw ec rl st zo rn do +\n o9 z5 wy vi ya ea ee fo gf va ov ww rr wr lb ro qq vr gj nw ru ym iv s4 hu tm wo wp zs br fs wg ej du y1 yt yu e7 eb em dd pq v7 cr um ae oz 0z kc tq rw zl rt wb y9 xv tm tq di eo te gc +\n tt un qs qn a7 qh je qj k0 o1 wr q6 wy ab q9 qm wr ea er eh pi hi sc hs m6 w1 bv lo zr tn yk ep op es ve xx sb ux hg sa gq qp wd n2 zh wf xf wj y3 wl e7 os u4 on ip kn ko qp s7 ly zn ba wu u4 kh f4 zo y9 q6 oh iw tq +\n qa a4 gu a7 cp z1 he ma q7 lu dp w7 ea rc ee d8 y4 tw ez im ae bv ii qe vb zt lc lv wm ro lk qr hp re tw yv es fp as zu oe qu qi bp wg cp p7 v4 ek rd wc ar rj tj e8 od e0 pm h2 h4 in qf wu wi 19 bj rl rc ee yj et tw ep +\n gv qd kj cd t3 c3 ih ws rg mc rx lh fd g8 gh cc vw b7 qe at j7 qo ws wg oy t6 t9 go eb e8 us u5 rq oe zj jy oz cj wb be ei pm og se w4 yu xw su yx if +\n o9 ub rd hw gs z3 ql nq ru wg jc 1t kv mr zm ah dd jk w8 ej aq ig y8 pp fj li wq jj cc qr no wy wu en bx yr qy oo es fy pd tk ix ph yr sf vx pn p2 jq fs ed oy yk os ie s9 u5 ak ud gd uf kb xc u1 xm eu xw 19 wn vh w1 to ee er aa rb rn ru an r1 ei +\n se kl 7h b6 xs ym tp an ta qb gn uo pt xi cl qp qy op vr ym ri ti tl i5 e1 e4 i9 ff i5 qp jx ht ql uo en pe ku h7 iw wn w4 ey ia si +\n ql xt wi k6 ew sf eg up eh oy sq ja g9 i3 qe cv l1 qq bv w2 la eu wg ec ef oh fs tb pc xd qs nl qu fn dy oi iu yf re fc hj hk xv zn zz w1 ew +\n po al hm qk jt cd ju nm li rs w9 ev ut ea 2f r4 d6 ey im pa nu wr m4 is bc xz w3 eu tb ha ft p4 ti to hr dy af i6 iz r4 jb x7 wj xg na rf gi at pn gd re wq qz ze bo wc vz sm zo my ye u7 oh dk w5 is yx tw fe dp +\n jl za gk cm wu vq jc zc iu mb oe fo fp ic sc 2l hy qr eb p5 pf dq pa fy lc td sz oo aw u1 rj fl tz nx aq xx oz xb 55 y0 +\n uq wr lh jv ri i7 ss qo gy bt s3 u1 dy ox hg it +\n ps hr lf jx bn qq up eh ab yl pn jg ng bz gd qr yw i9 j8 zi 3v oz at hd cx oj u9 rt uz ro ov +\n sq ga ny se cj id rg r3 pk kv ee sh ek dk sz pp q0 mn az kp ei qi ry em ph p9 gw hc m0 cp ea mn yf t1 5y wx ol e6 ec u2 e7 uh uj uk av ql lw qx zr qv mw qg cq ww wb pw tu w2 mf ut gk af yo ie ob +\n hn um a6 q7 af du r4 up tp ej sk lo le m8 rp eu ei qi ky op of tp ur oj hu tb dy qu gt tf oz wc s7 e7 ua pw ax nb wx wy fj wn 18 wv es yq ok w4 uz yx yc +\n pa qg qh q4 fv qz kx q6 cp gb c6 pr eh id in qw we bk wn qq b6 qy qu es ic s1 og gn wp op qf ic ro os yp rj fj ag oc ay da fv wl qp f1 yx n7 ea w2 ly yj iq iw rm o5 +\n o9 ps d3 lp wr qc md e5 rk w0 pm gx lf ku qt qp to tc pk fb tb qi lh nt yd vt ot ra tg gd zx wx vj rq cr hm ma jp vg u8 rt ei it +\n dx dv h9 rf qf uw a8 qh uv k3 ri is yr r3 eq uu tz yn y6 qc ps jf wq xe wx lc qr j4 ku xx nb 4z sr tr uq p6 uz of i6 s1 fs pj tc hu qu hz f1 hp lj s4 qx tg yp gs ob tz ds sw pm ug hm ip ql le vl wq tb xv eq w2 yg w4 st o6 +\n qd q4 pa z6 qz ia 70 r3 mb iu es r5 gh t9 cj vz qw mb ko vt qr qt gh qo ty eb kq n1 xb ef rp ek gu rg s7 rj sn ai hg o1 uj pr jt fg v0 tq tx ww bj bm ct w1 zi rn ox iw ri +\n al rd w8 vp yd yk r0 pi po se sr qa l0 qk ir e9 hm kc rz aa w6 +\n un pq qd a8 z2 qk z5 ws bi xy qx wg wp t4 mj gv qm rg c6 w7 w9 es y1 g2 ej yz gg qc qn wq qw m9 wx qe kr 27 fp fq m7 xp 3p qr rr tr ij il eh au s1 uc fx ut qu sj j8 j9 ya nr rz wg wh eg x8 sl t7 yu vf ay ds ap re dh qg qh qj hz qk zz qx k3 cy iq ox qv eu nx n6 6r lq n0 y0 uq tb sy iw fm an +\n yv dc qs gm q2 cv ok wt b2 cj wu mr zj kn e5 iu pz r8 pe fp ot tq a9 y5 sz ez cl wq qq wv a7 ln ky jd qe qr yx rm qi ea ln te y9 ev en eh iv tx e3 as tn j8 wf xh co fl nc wk xz es rx ee wh ub aq u1 ar e7 up it iu o2 wl ko jo cu pc wo al hm uq rn ul yz ro +\n pw na wu jd yf oe qr xr sk wa hw ql wg x6 s9 u7 am +\n uv tr ub k7 qg he u6 jt gs z3 by tn bi av z7 jc ck q7 2n ny cx km mk rf pj xi lh sf up yj to ia ab tq fq pm fd qc qv ps su qw fu xu cm zb bc qr qt tn ei rw gl p1 xi qo tt ed ef ri iz yw oh tc uy tv as qu l4 qr t4 wx e5 ae op oa em tz gd dq rw ug dr ux qj be ko cg nl je aj xw q1 vv ax rl w2 yt aa u0 eu ah +\n dc ph sq jt ql un q5 cg lk w9 ur uy pz uo sx qv qq cc ln fu ym ho su pn qa bq pd wj wj yk ou wl rk o2 pt uc km ja wm ry rm ob +\n gb pw qf we q3 ls q4 sy bl lg q8 t3 wl rg ed io ef if oi hp lo kw wy qw ei yz rt es p6 fp hi qo bn qw wg cy np uv yy oa uo ir of em ug x9 qh nj n8 ea u8 er w6 +\n ij dg cd lw gk wu zl dd eb eq sg ia am in wq xt nk wr xj qq p5 pd pk as sd fn lj jw fk l9 nt wl oo fj sb u4 gs fx hg o1 dr fb hj h8 xc yq ch er e2 aa af ah ob +\n a2 o0 hn pd iz hw jg q1 jl qz ip le me wi bb r3 z7 g1 eh td sw g9 qq c9 vy ud qo es ec tj uw dq ur hj dy oe zp lk l5 fl wj ys t2 ej t4 ek rs sl yu oa u3 gd pm rw h1 pr h2 py wl 2p s7 wq 6r mi 10 ox o6 +\n i3 qw ee ur cy nx r2 wj t2 ub ir aj cl qm u0 oz +\n qd qn un qz xy nq an kg hc c6 w8 93 eq ts g9 wy mg w3 rb 3f wf rw kt op es ef at em s6 pc wg bw x1 xl wg hl yk yo eb ud hm hl py wb u4 zp bj bm se sr sy ox am +\n rc ix qs ls qy at ut pk yo ys ec hs lq xv ks +\n yb al zf ws cn ac ih th ww vb kt b3 xo qe qi te ea p8 tn qd ci ix xk pk bg rc tl f4 wb rb ru +\n iy qd a5 jq jw qh sw fv oz cj hc qq ya ee yn pr av or us iv fa qb q9 bh ns d0 qe i1 b0 fh qy qu qi ry os ul hq ri ix e1 ao p0 qt sf qi uh ll ko lx nz sg jz hq sh p8 x3 wg rd sx yo yp u3 pv rq ds tc rr wx lr xb wn ep hh bk yw q6 og yr yg si tq do if +\n hv qa qf jg he q1 kj qz bh lr kn rj th kz ef eh av pp i1 ar gl ur lr bz xp yr ze qt tn es fl hw s5 qa ed t4 wz sx rg sv e9 fz hf al h1 av bg ym ee yg +\n k8 nn jy q4 wd lf xu q9 a1 4v yd mb r6 yh pb ta g6 dn d3 pl j1 jk wc cn wy 26 rr te ti fa e4 uy fb gr hb kd lc qf p5 wh au fa iv xo hf ot eg ra wv tp ec yo ah iu pw hj ac h3 py k2 u1 wb rl rz yt er w6 ru af yo ep +\n qd uq qh qm q3 vg qc c5 rd vp ut eq on yn ii xp up r8 d0 sz qx ue pl lx qe wr qr lm nh qt ha qo ki ri e2 tx iv ao s3 ow kp xf rh ya r2 rk cw nt by wd j8 t1 hk y1 ns t6 wc ev sq rq yf ux aw ch qs u2 zn sm rt wb bk yq dh 8w w3 rc yg o3 yi ox ov ir +\n u0 q7 qb ml or nu b5 1l xb tr tp in qt hz so v6 dq o2 qh wl nb rv fw +\n ss jr zf zh xt oy hy aw y8 js ob wq ny or vy fi en tb qi j9 gt ib ot oy rd e5 y6 tg th pt gq wz rt rl ew fm ie ri ir ro ah +\n o0 qj h9 wy ee g9 gk jd fg qt 3d fu ru iz tl fd tv ad hl wp oo wf nb ez sv tl f4 dr oy rp +\n ak il k6 qh q2 vd k3 zd bo lj k7 km 5c ut rz yd up ua is r0 qn zq wq j1 qe cv pw fu md bw yw qq ra rw qu ex ik at y0 ru ti yw fz ic ao ow gm jc i7 nf p4 fj xg kr br xk bs mb pk hl wl ta ez sv e9 us om rw ap gq wl k2 qz h8 gu kf et ru tq ag uz rp +\n yb az dd fu rf hw qg we u9 o3 q5 q6 ag c2 o7 wa kh w8 vo mc yg tu ua uh ta tw ih hu fj su bg ww bh kw ry ru wy ky wu wi fw 20 b9 qo ik oa ev hw s1 e1 e3 fc uu s5 tn qy hz jc do ou jq gb kf pf xl x3 yv lz iq eb e8 os sn fx dw qg ql wc ka n8 gf ly se tv yk di si o7 r2 rp +\n il mj vi sd ia y6 wq rm p5 ux ho nr ef ej wq iq fn +\n ft cs uo io er ic tw ig mm c9 xk ab ze uw i5 s1 e4 pl ui f2 lj p4 sf x4 kz ej ez eb ov of rw dy av qh f0 h5 ki qx cx eb og gk oz uc +\n ul io zd kn w9 y3 wt qq wp jl i9 jk ca h5 wx wb tm do +\n iy hv cs a2 ee yz y6 gk kq em qy uq ts w0 rq rr vt pb nc q5 +\n qn q3 vt vu yk ej fp tw zm qq qy y9 hh wo wg rh ep x5 wk mr el l9 av hz w5 +\n hq qz wy cx rh ur w9 e8 r4 fq im fj gj dm qn gl jn iz l1 yh mz rw e2 qo wh nt wk zw t7 e5 iq fh eb sn ud az uv fh sv dq q1 ku zs eb ue xq rn o6 do +\n ub lo sq wr d1 mt o7 ts t5 rd xe iu yg ot gg se pp qc js lu xt j3 j4 wt pc vz 5o yr qw zw qr eu db sy eb em fo i0 ad gw m9 ig ih lc od n4 pg rx bi ni kq wl aw e7 az jo mk bo wb ei mi ep wb eq di do +\n q1 ub xt db wt ws ik pl ee or to ej ic is fr jk ls c9 qq yg qt eo rw tp p8 dy pz gm hz or xs bt x8 t4 t8 s7 oj lt wv vx u7 w4 et ox yo +\n po o9 ih dx qa rf qf pd d2 kl ad lh kb bd qm bb b1 z8 ew d6 yg d7 ym ti eh ic iv oi y6 sz dx qn ut qm gz pj zw jj 4d bk wb lm xb ke yx oo qp yb yn en fo yw fp e4 aa fd jz qu gw qa zs nl v9 wf qt qi vg ni wx hk 9f sz tg t0 ga de re io av h2 jt x0 h4 wx wc fg rb rn nc yz iy zp ds ep zw pr xv rz yh yk zp do hc ep +\n hb ty z2 qz qz zh gw mg kb ve zz ti tp py el jp tg qc ar qv gx la qr cn lr nd ng ve qt 6g ml op pd uq uw eh i8 uy dt ho j8 wp wd qe xm w0 x4 qk el e9 pb sm pn tc gt ce oj jr mi ds wb ym ew u8 +\n ij yb hn u7 cd gj co dp lp b2 r5 ed ti pn qx g0 jb jn jj we bl ri ot pi rb yc sv ty oh ph hh e4 hy sd wp ll ft l7 wh ca ys wf wb t7 sv uo sb sn ha pb sw de un qc bz wo en as tb eu af eo +\n d2 k0 wr q4 q5 c2 sj iv pm g8 m1 l1 5s ij aa lb xm vf ej ta ar th od sm cw gy bu qd q1 u8 ry rn +\n qa ux q3 mj ex yu zx rk gi rl ya is py am tw ja js db ps dn qb qn gn lc pe qq vr qr eo qi ec oa ev uz yq of in ho qo jj jk wk wd zp wf lz t8 tk ha pv fz pn ug o2 pe uk kv gq v7 oi qv wv dj tv fn fw +\n dx a3 k5 um uq jd og nn q5 qx cu wp rd ws d6 px ac oe rb up tp ej ek ih ff qc gj qm xk b4 dz jg sq jh eu yx eo re es ul yw tp i6 pj ho qi qf sn og xo yv pk wj wb go ar uo eb ir iy pq uh qg h6 vt wv sn n0 rx af uz hx eo +\n yv ub ty gn gu fu dm ca q2 d4 cn ad iw k6 bf zl zz 2o w7 uo ee yk ix g3 am fw oi jo se ha vs qn iy qq 24 bl j6 g4 cw jv 1l ei qy ke j4 qi ep of ao hh tb gm sh lh vc uf vu wd p6 xm qt kh rk l9 s4 wh mr t4 oi rf iq op ox u4 e9 fk u5 it re uk f0 kb nd qk ce jp lr cy js qd qb sb tq n7 n8 ed ue tn ox o6 id r2 it +\n qa pa jd qn qg jt gh q5 lg ag qv ah qn vr da rh w7 b2 rz rx d6 d7 eg eh yl a9 ek dl tw sc hp ha su gz lo qe le ns kt qy qi 1h kp mz qu es yb yn p6 eh fs ok as im dy px gq qp qs l6 iv rl zw dr 4r hi wj rp t6 go s8 e8 at e9 f3 ak dg f9 qh pt dz ww rv wb oc pv be wq cs q1 xr xx eq yr u9 sr tb yl tq if hc ig +\n a5 co dh bt lw ck lh w7 3e mp r3 rz yf yh uh eh td y8 fg pa ar va dm su q9 d5 qw re vh he jc 1g ib xz qq qw yg vt rn rb cb ry ym em i7 hr ff f2 qp rd lx wg lb kh va jv qi xd wh wc el un sz tf gu oz ae e9 e0 iu dr io dt fb dh jo um wx s5 oa kx ly rn oc zy f3 hb tt wb u9 oz hx if ig +\n ak o0 qd q7 eq g1 y2 pt dk g8 qb vs qe dh 5i pt yh qo ul tp oj sp oq di uh zg xn rx tp tf ie f6 cg rv zm xw zq 5f md sr yk ru ro +\n a2 tt ub rs ij ml ow pe el gd va ue zm sa pq lc yw qi qw lv ep qo uj ym tl ye hj s6 uf qp 82 fk y1 wl oi t8 fk pb tx o1 sk lm oo xv n2 ad fk n6 dp on q6 rv +\n qf jf kk nm oz q7 b2 xo fw kj rh ua oe yl gh vd qe gn wb pt wi z0 se gj 48 of i5 oh so hz wp ae wg nc kg xf ev pv ov au iy az f7 qb q5 eq yr tv yy ol ry o4 oc di ep +\n po o9 dc a5 jd z1 sq ws b7 ti r9 sl ez aw tg zm si ng qe ky b5 pp eb od jl ff oe ce qp gy yv qk r4 xf kw iw sn tx gg uh cq ql qa 2s mt eq rb dp +\n qs qz cd dl se q0 lv eu yi rw qo uh uj ul en tx wo qd e6 pv gg je zx kp qc q3 ye en +\n un qs qh se ws lf so eq yf ef y3 g4 zb hs q0 no qw j2 y0 uu fb di f1 kq oa ul t3 ot fh ak yf fv dt f8 jo sx wx at wn cs lq zc +\n ub qa qs ik pw uq a6 pd dm d1 qm d2 qk cv zd bi wd ne ah qb kg kh ij 1p rk w9 wt r5 d5 px uf eh yk oy pm i2 hp st qn si qm zw we ls px lr ri qr sr db hp qu xk fy os eg en uc ur i7 sa hp vn qs kw dn od rh xj w9 wk ph ap yh el oi oo e7 gp ay s0 f4 gf az jy qk ql qx 1k v9 qc jq zy n5 kg hd ww wv bj hj ur er rn ry eo o7 +\n df a6 dn je ql no q6 ox wo zl bn rh ya mv e0 yn pr gd pi y8 i4 c7 g1 j6 wo rv eu xg eo c0 yx ea sv os wp qw wl ou un t6 u2 os of f6 dt f0 jt wc ja ae qv rm ds pq y7 qk ck aa ux +\n db iz jk zd wy wh c3 zk 2o rj hw vp on ed ac to g2 r0 id ta th qb dm pj m8 np oe pu bb tc gh ml rq uf tu eh ye tx gv pk jv j8 lk xs kd fi mx be wd t3 mr wk wl td eb ie tz dw rw pm re fb dj h6 ql wz wx qx qv u3 vz xe ex 2w ty ew xm oz an +\n ty a6 we wi ro lj bn rh r5 g4 aw jd q0 gz xy m6 wu qq et oo ex qp tr y0 fi au e3 oj gm px lg wk tu ek tg u2 ov em dg uk nd qj cy hp wq mi bj q4 ia fm r1 ei ie ux +\n tr qg h7 qk jl kc jr am mo w8 e8 td gl kw sd jo qr vl gs qe b9 mm fh eo uh ft ik e2 i0 uu ff qu f2 jq v2 wg kg ek aq wm yi yo s8 e8 sq ab cw wt ck pb pn xl bj yq wm ew xq su r2 +\n qk wa q6 jj ws ut gd gf ly ec pj sa pd wl e5 wc da kx zk zz zb wv rm te +\n jq uz nv ql as jx z8 q7 o7 yt rl ea e0 ym y2 pr ia sz sq sr qq qr vk oe pe lr bl ll rm yx y0 eg ti e1 ue uu ui jx zd oq kd rg lv lb r1 fx ro me ts ay f6 fc io qg py qj qk qs ky qh y9 ok o4 am +\n qh dl jt wy a2 yk y2 i4 zq kq we bb dg m6 qq zw rt ta tc ff xs xd qf g0 1d yg du wz iy sw tc dd hj hk mh ov zi wn hk ee yj af +\n ra ak uw q3 cb ji wy fw gw t4 mu ts qw ww rj vo rl yd ug d9 gj i3 zw qw wy md qq bv rn qy pd tl ic p9 hr dr hh ui sf f1 i6 ws cy es ef t5 kr ek oo t7 ec e8 u4 od dq ji ch jr zm jy q1 zp yq 2e og yo tm +\n tr tt qa qd jf pg qh jr sw ao q3 qz za wt js bl vw q9 ws uu w0 ya pl yf rx ee tu r7 gg dv it lo ww up js qq qe lz eu qy rr yb ri ay ye ta tv im sh ss uk qd qf bw ro sl wl t5 e5 um th ha fx re ii fv je hk ot cq km h8 ks bk vl qn xe te tt rl u7 iq ry ag dp o8 +\n sa z1 qj q2 nn wr z5 mq xu q7 gv t6 w7 r4 c1 mb sd ed ym ot ta ht ts tw gd tf g8 se ar gh fh qv qn zm hs qw qe oq wc xj vz xl wo rn i2 sr rq at yq uw s1 tx hy fm pc wo hv gy vu wd lc ul p8 wk wk el oz oa rh gp pn gf fx fc f7 rr dy x9 uk f0 py wl v7 cr ch qs wv nz lv lu 5o xe ym ly er yi ia gl ox r1 dp +\n uv qd hm qf gp k9 kj we lf bs ej 2i el wl t7 rj w0 rz yf ys r8 tp py tq tw dl im qc db qq sd ry c9 oe if qw aw qu uh tt p5 p7 p8 oj zi oe qu qi lk j9 sk zs ka lc wh wk zq mq vh t2 ej r9 mr ez t6 e5 op rk ga pb dq ap f9 py qk qz wc kd pv bd sm dr u7 mf o3 yk di r2 +\n po a3 uw q5 q7 ck kb zj td zz yf jd wq xh ld qr w4 p1 ij fu tp qq sv y2 yt t6 e5 op dw iu pw jp ka qv 4u qf rm vb w6 +\n fy a6 qg cs z3 ql dc jz wy me cj o6 ba kv wp w8 ea r5 uo fw ib ig g7 gg sy bg qr cb cq ro xl xv ex tt ru pd hg im oq gq ao rl pl aq sz t7 e6 os uf ug gg pr ql qz vt mj px wb ci qf ov be bg ww mp mi rz u7 w3 ei yc +\n gh cm ca rg uy pm y7 g8 lx yc qi re uh yn uq eh tz ph wo cr sv fp kh sl oi sx ov ga iu h1 je fd rv qv wi jy yy ry o4 tq si +\n qd iz qh q3 cg lf wy xa ez eq om ug eg yj fo fp yz qx qe wb or jg xb c9 p4 tj y0 iz tc oj tb i6 p1 ka zf qe yp wj mv ra ez rd uh pt zl lm sz wc lr bq oc zq sr af gl ei ux it +\n a2 qa h9 qh q3 fn kx ve wz us sj yz fd g7 vh c9 xq xj ln tz wp wf kg kk by vf j9 5y un yi e6 rh sn tx hj kn rb +\n un qs fi qm jk js bd o8 bx vt eq ya xp yg pz ym dj fp tp ta oy dl qc cx qq m1 rt wn d0 wm yr qw aq qt tb ha p1 uk yn ef tj gv im sd hk pz jx zi wa wf ba l0 wd mq ej wv t5 ek iq pv ov f3 em ak rq hn hh f7 uk qh ot ju ng ji h7 wz cr v9 bj bk rc er ia is iw ei id ov pu hc aj +\n pw gm qd jf u6 z3 jl q4 wt bi lr id wa wz w8 ya ev ew r6 yn ee io r8 ip ej td im si j2 jo d7 m4 pv iv yg qi il ti i6 ta ib ap fb hz wd vu wf wh kt kh og kk nm rp ti ek ns t7 y5 wc ae ir pv hf ub wc ho wb wn mi rn w6 yk tm te rp +\n o9 un h0 a6 pf iq xi tg w8 z7 r5 om oq eg or y4 sr fh zv vw zq tc ws rq db rw eo ym tl fv i9 pz jx j7 hx oi qf x2 l9 x3 qj by to el sx ys yd ao az uj hl dl tj nz wn kg kh on wv w1 w5 gl ei +\n gv az ql nm rc r7 yl ja zn q9 xw no iz qt pk x4 l4 tg u3 of zk wc go qb mo eq u7 tv rm ig fe +\n o0 ik qd um qg k9 mb bu wy bx ny ws hm ea mb iu pe eg ey sh uh g2 ic iv aq td qx ja qb ha 2j lp xr wc vl wn wi sl tx qt rq ec vw of uw sm ic qy j7 ns hb 2q kw wf vp 1f x1 5c zs y1 rg tg oz e7 fh eb ie up e0 ap ve wq zz cr wz h8 wv go ly fk az pr rz h4 ew w2 ok w5 ia si ro am +\n dv d2 cd qc zt 25 xp wd te es sh eo wn f4 wo tv oc +\n uv qd qn hr bj b1 mw lg io sh lo qq xh m6 28 rn xx p7 im qt jn jw bm qf r1 mn ny ed em ii dd wn cz ds vc wb hh q4 yw ur rt ie o6 ux r2 +\n rs dh z1 jr cb vq r3 eq om y1 sg r9 if tw qb qn m2 vy dc b0 ik fa ib aa jz qu sg qs 1s be of w9 oz sv t9 oc pv rw dd o2 dh lq ka lu 1m qk q4 y0 ye yq w2 w6 si ob it +\n o9 db iz fi qn qj mw 3v wp li e3 km zz yy mo ya rz mv yg r7 yh pc or r9 pm a0 td ih db lt pg jf gl re ww qw m4 j5 xi wi yd nh yg qr rm et ey ug re rr y9 y0 sb tu od ay of iv oh i8 ok uu sf gq lg wa nn uj qs cu kd xb wg cs 3k yv hk pn ii hh cw km wz wx wc n3 jr wm qn bd zo mo jo wm q6 w3 rt an hx ah am uc dp +\n ps pt vq kc bs vu vo xu ee ib hv wj x3 nu ud yf qh wb lb gz +\n ra o9 qs ty rd ps db pu qj u6 k9 nb qk oj ql wt jx bo ri xo o0 mk rh bm mj ut mb rc yn et yl pm ih i1 g9 qm xq oq bj wt jp xu pt bc eo ep qi ky sv uk fy ri i5 im dy hk ui tm f2 uf ug qd kf nc s3 fs 12 t2 ro du wk ek yt ej t7 s7 oc ay s9 pv fl s0 gf tx fc ac py v5 qk ce qz cr jp ck hp u3 zm xr ii yv ea cf hj ye w3 tp do tw ux +\n o9 qa ik wt kc q8 wk sp yy w8 w0 ys ea om tu yz pn fe ae g9 ps g0 i4 qb fk qn qm ut j1 d6 4d cb vj vk xy j5 be wi ve qq gf qr j3 ug qo p4 sm s2 ut fd pl qt jz ui qy qu qa nk fj iz xh wk iv qz fb ro x6 ti sl rs hc oi wm us ai dw o1 hh ab qh qj ju ng wl zr vk tw 5a vc hk md yr u7 w2 yt tn eu ul ah +\n uv ra qs ty jh q4 o4 bc vr o9 rg jz mc r4 ui g1 ey g3 sj am sq fj qn it xt ln dl jh b9 g8 dv qt yz ea ue ss w9 wj kk bi ym tg t0 ob ys iu uj qk nf v6 nj ox qb wy mw 1n pq eq w1 rx rp ge +\n a2 pa e4 xy yd sj vs jj xj lm qy qp ri ux p8 pj tv xs wd wf oz gd sw rw uj uk qj k1 xx um eu bx my em ey +\n az h0 qz iq bl kb xp yf y8 qn rv hx oc re gt k2 bo qg cf rl +\n yv uj d2 mq hx ws w7 mv yn r8 ab an ae jn xw al up be qr zr ep re qo ec ur ap hp pn wp i9 rf wf vo qk t8 eb yd uk kv ww wx wt ox kh mi eq yj oz fn ie am rp +\n ik df qg jg k9 wy kc ro wi ve bb rl ew io or eh sq oi qc qe d7 m4 pu gd db oo yv yq ix eh fl pg ib hu pl cr fr xd cy ke mx yh wk ag hf hk qg sj we mz gp u4 ak ma rz rv af ox di yx ob +\n hn pa pw qd il qh q1 z3 wr t3 wo ws vu uu ld pe fo dj ot dx pp vl qq rr ls j4 fs dl ve c6 rq ln xk ec rt ty ik y0 tu yq fz s5 sd sh jn wa uj ws lx qr ca rz wd nu ek yy yi y6 uo os up f4 fz qk h8 qc wr at 18 ca ww rv sy ox o6 +\n dv wu wo uo m2 we rp b6 qe ik e1 bq w8 x5 ez fh u4 iy jy wu li f5 u8 w3 yl te +\n sa ds qd no q5 ra jd qo ru r7 uo ar ud on ak fv dg wl qx qv ye yl ep ge +\n ss rf qn bu gj rj uo yz tf m1 kw zr oo y0 pf tc dy qu v6 xh t4 oo um df je qh dz v8 ho wn wo 0w dj rv o3 du ro +\n ij uj k7 me lg ih hv ws rj pl sd uo y1 yk d0 pt y4 g4 ou tw sq td fj ha qm qq 4a kw d7 xy m5 bx c9 yx nw tr qo uj fu en p6 s1 ht tb qo zp kq x2 wk wj wk yt wz sz ae iw ay fk ao ug pq qg k1 ql xx qc cl qk 56 bn oj yt et ut uy tw ir yc +\n k5 pg cp z5 wr no zd tk ej an qx gj i3 su we up 3q yq fx ib tv qp ik wj yf u1 os rk jt qo qx n9 w1 rb +\n k9 uv gs wr 3b mh km bm we w9 es or yk r0 g5 aq gf nq qv ll m5 yd zq qt qp sv ed p5 of eh i7 pz hl sg jn wa m0 nm kf w8 wj de e7 ar iy pn ly wn fx w3 rb ey am +\n o9 d2 vg gk ex rf rc hy qm j4 ga qw rm ls yl cm en tl tp fp tb i3 qy qo j9 vn zf wf qg mb kj qi jb mq wl rj s8 lw um zt wb f4 xw f9 +\n ra go ls qx wi c6 b0 rw g1 yz fe g8 ow qq ra mz ex oa fu iz tl uc e1 p6 x1 tf rh tk fz ap hl qh k3 xb mw zm yb yw q5 aa rp +\n yu qx sc xe j2 oq gs i6 i9 l0 +\n yv ss tt gu fi qj bt ql ls io nw gk hl up zv gl ni xt wy dz qe ud nw rw qu uw e4 qy px qf zw za ty ek t7 pv dg ho wn uq rx yx ep +\n ga 1w ld wy o7 xr pk r9 g6 hu jg lx sd no xt wr zy ku l2 nw 9r rt i5 to tp tc s6 f1 ud ko xb rj qy es t0 f4 fx ii rr hm hj fb ji oi n1 vk ci 9e mt yc 2r tv gk yp ux +\n hb hn k0 wy m4 w7 rc ts y6 j3 qe ve qy rt so di qo dp lk xf mq wl em f5 pr wl wn 3k ew yt w4 ri +\n qa ss lq wr bx t3 r5 ed eg sx dn we 7n ra qe b9 rm wd rw eo oa ri e1 e2 ut ap hu qo ws uz ai tz nl cu wq ln wn ie aj +\n yb rs un hm dg qm qk ao mw fn kv ur uo pj e9 sf ia tp tw a0 td sx fg su xq m1 om na vk wy xk em l1 z0 nh b0 mz qy p2 ru au iv p9 pz ug lz xn wf xg fk zu wj wd u1 e9 tl ak hf sw o1 pw dt gq v5 lm h7 nn nl wq uq zt o3 ad ry id ig +\n a3 pp dv qs gn u6 jy kk io dt wt ck rg ua yd ya yh ax ac y1 pe pc pv fp fw dc qv zb dn q0 ju jj m1 ui lx qe qr t9 ja he wi vw m7 l1 jn qe wa qt xg rq qy yi qu p3 yb ed en tz so s3 tb ho fm px gw zo lx wf sm mc dq wj yg l4 uv yk tp t5 wz ol fk f4 pe kc dj wz qb zm wi br zk ww ty 6i vm eb lt eq w2 ey yp yz o6 ei +\n fu ga io nt wp jz yf rv oe eh pt dz ih sx qx g0 qm hf xe lz gc d5 bh 2z cn d9 1r sz li bv qe 6d bb er xv yx p2 ea tj p5 ay uq dq pg oh qt s6 px sh ko qa nn oa bq cs kk hh cr wg tu y4 t6 e5 oz th sn ov u5 dw qg dh uk n1 zr qv 3d n4 yx xe wv eb h4 yo ro hx o8 rp +\n ra gu hm a7 jw qm qh jr gs k0 ql xt q5 dt ru wy k5 wh fw lu kb am m6 bx vy qq ev rk 2s mc yd es io pc pv g2 ek tq tw in ih ae qc d5 ui qe wt qq m8 vr nb ee hu rw rr tt ed fi em e1 e3 hh hi sh zp qo wp l4 ws qf qf pg eg to un gu u1 t9 ox e7 u4 od ds de hh py ql h7 gy js vz gf y8 uq se do ro rp +\n qs qg gk ta bf r3 hw r7 r9 sh ua g3 sq td g7 ha lu qw xr wy wu rz ko bb i6 uy as di qi za hv jw rf 1f 2u va ap qi rc du wk yt t7 u2 ob re ax v8 cg qb wy wn kg pn yi rn ru +\n gr ra jq qf go ga jh gs q3 tm q8 k7 o8 mj ym er ip ua ej hy i1 dv qb vg cv m5 wy xk g5 wi ng w3 3w ud rw ug ep hq ta fc fd aa i5 hx qp wp v7 qs l6 l9 l0 jn ty t6 ie rj tk od ys on pq tc zl nh qc xv wc cu ks ei lm vm cj yi ad r1 si sp +\n qa hm a3 ac q9 na rj if qw rr vw tj ib su qu wo dp j0 wf pf 2y wk ym ra wb ae ga gs f8 gq im ar pb ec f9 yu rm +\n t8 ej an y4 td ez ln z9 lj qy sm uw dq us cp nu tg vn +\n qa ds k5 hw k8 k0 ql hl 1r wi fw c6 w7 mz rj xy r4 e0 ym yh eg r0 us fs ib oi qv q0 ww lp gm ln bx nc qi l1 qe wg ea qo eb tk eg to ur jc oe dp hv wa 2q nk at rg wf wg ca xk jn pk yg er ot uv wb aq ol wx e6 ev sv uo vf eb ah ud da pe qg jr kn ju ng ae wv n3 iw ly kf cl pb wv tt vn eb vm u7 ew aa w6 rm gx r2 o8 +\n q4 q6 vk d6 eg pc pv r0 tw i3 q0 we tw sm e4 ow sn kg up hm qx zv nz wm u9 ul ri do +\n po uv dc qs qd hm qg q2 jj sw kl me q8 xa wa xf z5 yd r4 rq sf px ti ia r9 yl dj dk ek qx i2 sr qv qb lb wi nf wu qe tv fh qo rr yb fy eb ri ai ok qt pc ud qi qa ws qs lc zh nc x2 cs t2 di ke wk sz oc yp s9 ys ai ln wz cg wc wv os qb f2 ec y8 dg wm rz yr ee rn sy du su eu fm ei o6 dp hc +\n ft qj q6 wq up ut lg er uw db ll ws of og e4 1i r0 wx fh th vf re hm zi +\n a3 ty pw ph cg uo r7 oi q0 lb c0 vl xx mh hu b9 qy tt sv p5 eh to hh ow tm oe si sk oi gt kq cu vi j5 wf el tf yu u3 ya uj dy qh ql ct wc el y0 o3 o6 if ge +\n a3 dd by wt lf 2v bl 7c bn cf yo go yf ii et ey yl aq aw g8 ho i3 qb dn qn lu vf vg 2k le ml wy t0 4h xk qw b7 bb eu xr qu tt y0 os sn tl pf og tz tx pl ss us xd cu oa qd xn ke qf vp kh ny wk r8 ej rd t7 sc e6 rh ud tx al gg re hj ux qj gw xx zv xm iy ca vb yw en oh u9 aa w5 w6 ul oc an uc +\n qa un dn hq hw d1 jr jy kk kl wt kz zf z7 cm q7 me xp wp mj rh ue e7 ys rz eq ew ed xp ee yj y1 to fw aq po i2 jn li on m2 na vq wu ck er yu db yi gl ty eh uw fp tx e2 fs uu sf jx oe jb qp cy bn qd wg 3z nu j9 mr t6 gp pv ha tl ai fx uf fc kx qh gw xb zt qv qb ir cq vb y9 ct ol fn ah hx sp +\n db wt cm ch jc wi dd ys on td po y8 q0 wq kt eu tc tv or fr s3 na e7 uf gg re f5 tt aa tb ie +\n a5 jw qh q1 qj oj xy my b6 es yg yl y5 zm pv qw qt qo ea ri ao in s4 gv i0 ad lh wa qf gm rk vs oy r0 ez ab lm qs qh ry ox +\n ga ca z6 nr wo rg bm vu uu rj e0 ui io pe eh d9 ab tw fe tf fk wy ln md rk sk qq qw hy kp dc qy y0 p5 p6 p7 ic pg e4 jb ge wp qa bn xf ks zi oy e5 um wx ie yp fv je ng oj ja v9 bp qv er an pu +\n a4 jw a8 o1 q3 un gh le nq q8 ig rg rl ea io er tu fp dk hy sq ae lo qq wt wy 5i xj cw dz oo qo yn ty y9 y0 sb ef tj uw ta ur i8 tb oq af hz qi wo sk zs qs vi wf kt nb y1 oy wk r0 ol ex ec tg t9 eb ap fv qk ji cr s6 et xq bf ep mi ax rt yu iq af am yc +\n gr uv hv tr a3 qs lo u7 jy qz kl z6 gk gz ag kn rg k0 w7 wr rl pj ii yh up ac ot d0 g6 td y6 fr se pp dc g9 cl gx qw pl m1 ii qr vz oy nf eu eo p1 os y0 ri ix au uc ai fx p9 nm jj lz pa kw ul rg gw qh 4m eo qc l5 rp oy ej un yy yu t8 sv ud fx ac dy av gq qj ve sl bu th u3 rn nz n5 zm yz bd tx el ex n9 es rt rz rx ol sy rn yo +\n ph cb jx wu ib vb ih ty oy tl vu +\n df qd k7 z2 q2 ju jz zf cm mw yr gu rx yh ym ef pc qx jd q0 ow pw wt rj xo mf xl qq qw ud tw ku ik oa od ti hk f1 xs qd wf dm s2 ph xo ou sx ae iw t9 eb u3 rk ak hf dw ax oe zl zz wm sm el cx cw lq za tu yw rx yu rn fn yi ei +\n a6 ql wr jx z7 wu xi ym fo if a0 dv ww lx zv dk tu sn hh ff hu zo ws rf wf aa ni kq uv t7 um go e8 ob sm tz hl uc zz ol lr kc n6 bk ry if +\n qs gm tn rp iu pi qe ec to l1 wh ra wl it kx fd vx q1 ri +\n gu pw qg we d4 ws q4 cn q5 me qv zj zl ex wr xo yg r7 eg et ey us iv po aw se cx az lb nz nc qq ew rs rq yx ep tj uq eh fz hg gv jc di wp sa nc ya cs fv qz ti wn aw e7 ox u6 pn re o2 hm fv qg hl dl v9 qv tz 6y rl ye rx ur tn eo +\n gr qj z6 ld tm jw hc ed y5 se ke ht tn jb 12 yt ek ao io wv ew ey fm tw ir +\n gv fr ak o0 gb rd dv gu qf qg qh jg ux qj ph k0 oj wa jz bi ja eg c1 fe qn b5 rs rg b1 vo z7 us d5 r5 ii tu yh y1 or ek sl pm hy dc th sy ww ze vb wt m6 iv mj qe 6f qt gk tq ru yq au ap dr hh qy sf qa ik kt wd rz ej t3 ot ej ub wx oz th s7 t0 ag ga pv em fz sw o1 ip qh nd h5 et ho cu yz tq wq wn et tn yo si ov a1 +\n ij rs rd qd pd qg qh z4 ql ip nq q5 xu bz lh o7 my 3w xe ws 2p w9 rk es er d8 pu y6 qc gl bv qa rv qt rb os ru fn qy qu hx or wa qs at zg mx xo bg yh ec os eb hd rw dw ip vw ki ok qx cu wb sn wm yj o3 tm ei ah +\n tr rd pq qd um qj u7 q3 cf db k4 gl mr gw c3 bs k8 vi 4v kz cg rz et ey tp fq y5 el gd dx qx hp mn cz wq xh m4 av t0 vz m6 qw tv rq ei il sb tk eg uq tc wo qo zs rd nx 2y fo j5 l0 l1 hy vy t3 t4 yt va y5 rg e7 uo ox at ir ys hd uf fx re rr ac kc cq qk cw h6 kp xn zu bd cz ca pn pq w1 rx vc w6 yo is fw ir ov +\n ra ij a3 qs qn jf qm nv cs cv kz q5 um q7 q8 km ya ys rx yn d8 sh pt fe se js ue rk m7 wp et ei qy to tz s4 af 3i lc wk ej hc ex t7 oc sm s0 tl fx re fb jr jp qc kc jr cc w3 yl oc ob ep +\n sa yb qn k8 lf d1 c3 wp vr wl yd iu kb sz g7 mn jm lz sd m3 lv qq j1 ex qo ry ru em pk i3 hi rf fk nc wd vu yt td sc tg s9 tz tx dh x9 qh ku dz my yr w3 oj se ei gz tq hx ah fe +\n w9 rl rc or fq a9 pp db gj hs lc qr ec p4 ph hb x1 ez u5 qx ea 6t tn +\n a3 qa dd qf qn qm qj vj wi ag wo ig e3 wz r6 d7 ax pe rb ey r9 is ot tq oy if hy se qx ar qb vd qw qe np xy nd wi in gj qu y9 ev ti tb qt px ud wo ll cy wd hw kh fp wk wg wh ym vo ub rd t7 iq yo ox eb yp ys au u6 rq ii io pe qh nz vl be n8 wv hk og rc er yu u0 rn yl is do eo +\n dd nn oc el yu tl rc rv r7 y2 hi qc qm wu cq qw xc kp tr fu ib zi qu wp vi ci qj nu zw t1 wl fh ev os f4 f6 f7 cd zc qx zy wu bs qn u0 +\n o9 gr fu a7 qk xu q7 wp el yu fp ou y5 pm pp qm jm st op uc fx tn hl zs kp bq p7 hi ys qj ki qc qa n6 oj ey w6 yk si +\n q7 xo sr he uu sd s6 gy ws iz fk sw al v6 lq fh ie oh uz pu +\n of ch zj rk rx rc g8 i1 jk tv ul fi e1 ic sp in jl jv j7 nm rp r8 go hf wx tb oz tw it +\n se kc tj rx yh eh td pa zb qv c8 j5 ri eq b9 rm ik ev ul ti p6 en ok tn wp jm ws ke br wj rp en gd rq f6 ac ab zc rz ew tb ro +\n qd wr d6 i3 j1 ww if qt yn fd e4 qf j5 yh t8 u1 ev qc wv pw u7 oj ok yz tw o8 +\n un pa jd qh qm dz pi z3 ny gs k0 wt xy z6 cj k5 gl bz d1 fq ye yr rh t7 ot if g6 im pa ps fk zw lx kr lv na wu vw eo cm te qo tr ec ty sb y0 i5 to ye so tc i5 sg ct qs sc ws qr xj 2u n5 rl cw dw ys qj yn qc y1 sl t9 ox sv s8 ya s0 tl ys rw tx fx ds rr cq cd ql qa au qg vg rx yt iq tn yl uz ei si r2 ob +\n rs gm qk gg m3 rj eq mv yf sk gx ve eh iv i7 n3 pb uf gh uj tg ox ww bg oz su o6 +\n ih a3 uj rd qs df h0 jd d2 kj q2 ap wr ol nw bz q7 fq ir ra w0 eq ya r6 d6 eg ej pn py pp sr qb jb wq ni xe we lm be xo w2 qo mj qr hp tr qo qp ef of yw ai e2 i8 fb tm do dp i8 l4 wd p5 sn pf gr vs rx kz vh t2 wj ot ar t9 at ir dw qj nc cw fd sx qc mz lt pv br wv dr q3 yq vn ye yw dk oh rc w3 yt se ov ge +\n ds h0 jw he qh jr jt ql me na ah xa tf wt pj pk om 97 rc yg ym oe yj eg dl fe sz g9 lo qq qw wx rr c8 ns vq m7 xl gs vr qw qr kq qi qo eb tk ue dw e2 i8 i9 hy hh qt f1 pc vv qs bn ij i0 uj xh wk qz ns ej un oi yi rh od ha tl re tc o1 uh ac ip qj we qh lq eb w3 w4 ia oz eu ri uz ep +\n fr ij dl qk z3 qz wt z9 gq mr wo zz rd dd rz ee sw pp g0 sy vg ww iu pz uo cb t9 ld qr ei yx rw es ts zi wp wd gw wj hf r4 tt x8 wl t6 hc gp eb aj ai iu o2 nh qv ey kg dp wq f5 rt cg yw sr tb gj rb fm ro ah ig +\n ss ux q4 ji xa mj mi ld rl pj r4 rx yg ti ix a9 ig gj j1 ww ii qe j3 mz vl qq ye m8 b8 yl qp ik ki eg uq fi ok fb oq fm sf oe hp v4 nk wg mx kt vs j8 yn wc wj ot td wn iw os u4 tl u5 rq de io x9 dl ql n2 ji wb if hx +\n iy jk ql q4 wt kz fb q7 vy w8 ur ax uf ym yl py ou dl pm in sq ho j1 qr ls j6 ic sl ko xq jm qe qr qt yc es ry pf he i8 s3 pj tm oe qo lk wp j9 nb yd bu rs e5 yi ar rh ga ud al hh oe wx s6 do kv be pm w5 fn ey du do pu +\n po rd qs il rf uq of jf nf ih w8 b0 ur pl us ed tz tu ef rb sj tf ff i1 pa dv ue fk m2 qr wt j5 c0 vw xo b7 p7 qt zi wo gt qa oo qd bt nt zq x8 ou e5 u2 fj s0 yd sw re cd qx jp wc ja ga jt bh hm eq rv hx gx +\n iy ij pa gy qd qg he d2 qk d4 qz q5 nw wu am qm ft w7 rq yn ef oe pv ek fq sk y4 ts am fd qx q9 jf ju wy lm zw wp er sy qu oa ta jl ss gq fe wa p2 kq ws 2w dn xz t2 ej rp rs yy e6 iq ag e0 u5 tx dd pq fv jr qj ku oj ql wz fd s5 nj qx zt 2d qb nx pm ce f9 w3 er tw rp aj it +\n ss qa gm dm qk c1 jd k0 t8 mk rk tk om yn tz r7 px ac av ot ts if fw ez y6 se qb ha su qn cl wx we qr zt kr mj rc qo es tj ym iz tk i6 fa i7 s3 pl jx du qu j0 ws v2 wj ys yv wd s4 wf nm dt wv ub ez ta wx e0 fz al ap qg wr ar wb fj n4 cz qg wq fc mp yq ev se eu am gx dp te +\n a2 hv yb nv h7 jt lw xt lu wp yr rg 2o 93 uo pr ej ez jb lz ww az oq bk b5 wi qw rq hs te ea es ed fu ti uz fd tm jc do qi j9 zs j0 wd xv iz hr wx el ns oi t8 sc t9 sb fk hg cd rb mz wn 4i ov ln yr oz tm ro o8 +\n iy pi jt kz st tm rh ya b2 om ef eh tp el in sc qc g0 ps zq nu pq j3 oe a7 ja js ng tc qe pp eo em fc s3 hh i9 jl qy i8 lk wa ae 1p vh ox rk em hf dd jt rn tq is oc o6 so pi +\n qs gm qn gw qb cx w8 ur yp up uy ek ez ar sy qb hd bx rl qt yi nw tt eb fl eh pg oh ib qy qi bp jz lf eo ph wh oy y5 om az tc ab wv wb kg ww eq ok aa uy w6 ag ig pi +\n ra a5 db co qn d4 bu qz kx me nr q8 my lp t8 gu rk yn et y1 ej g7 yq d0 j6 b6 qq rn kw ei yc uq e2 s3 oj s6 jl kf rl ny wg mw t2 co el yy ez eb e0 al qg km k3 n2 zr tk qb n5 n7 et tm ul +\n po uv a2 o0 rd hq dh hw a8 d4 wi z2 vt ww kb d7 pv tq fa ta dl oi y6 im ff ae qv sy si wq pq bn b3 lm b5 wi ku qu ru ul ri tx fb ss or sk wp qd w7 kh nn es hy wh rp um sx e6 rh rk pn sq rr hm dt ip dh pt wl h8 qc vj ly bq zn gd wn q4 hj yq xb mf ok tm ge +\n ub pa fy qf dh qj q4 wt mw cm k5 gw kb el w7 w8 mx ya ii dj dk gd dc gh st qb iu jk qr bz vz ab b5 mf pu qe xd nq eo yb pd i6 ue dq e1 qo wo sp 1o n1 4v at qf fi of xj rj dq ew nm x5 wh na ub e5 um sb ob em pb re ip x9 h7 zv xm bw 1v mp zr w3 xm ee yg rv rt ia is ro ep +\n cm bp hc rx y4 sr q9 jj rt qo uk ev to ff so bg eg y4 l0 go os ay tx qh hl qc wb +\n z3 nn o9 xf fs gd g8 ns ec p0 tb wf uv iw jt wr dq bj u7 e2 +\n da td ta tw tf tt ay dq sf gi ae rl e1 gk af dp +\n un fi dx wt m5 vo ys j3 i5 ad nr wj mn tg ox bs ia +\n hv yv qa qf dg qj do ek w0 is sl ez sr i2 ww we rl vr qw y9 tu p5 uc hj i6 ud ws l5 qf xh kh lg wf wj uv tf t7 e7 dt qz ka xn cx xe fn it +\n iy yv rs qg uw oh q3 lr vq bz ab zm wa ds b1 w9 rl rz uy wy om uo ef fo py tw fe qx i2 qc qb qn ww vg ke wr j5 j6 oy qq ng sl qw mj yh xf yk xg qu te p2 ft y9 uk ym uq so fx ff fn qy du f1 na lh wo qo ge sk v1 wg mc dq wj iv 1h pk 3s ej oy ek td ex ae yi t9 go e8 rk tz ud rq ax hz dk qz kf wm yq cy w4 h6 rt ry tn r1 gz ux pi +\n d2 we aa cb o3 xi tu ti gd wq pl xg wc lm de e4 sj hc ic wc ra wc go o1 dd ip wl in wx js tv rx yi yc +\n ty um hq co ux ql q6 wi bc kn q0 r7 yz ib pm g7 po qv re we bh 8j ru xo ra eu ud qy uh ec ty ry yn hw sm e1 pg p0 dr qy oe lc x1 kt xz pl t4 el t5 ex sn us dq rq ao f8 pr md ql v7 v0 n7 kh vn wm u7 cz et w6 gl yo ei di tw +\n ub jg ph q1 q2 d4 q4 qz kl ld cn ji z9 ro ek gb w7 rh pk ea ax yj pv ot yl an sl y5 po im i1 zb fj qb i4 gl xq si m1 jj lb l2 ul sn ue s1 ta hg zu lh nd j9 ci qu wd bh ef ro ra aq t7 ex t8 od en fz fc df h7 qz n1 v9 zy 4a tc bb ea yw mf ia yp eo aj rp ob +\n o9 qa h9 dn vo a7 qj jt ji ne kc cj zh wo q0 w7 e5 ui vi ya wy c2 r6 ui px yh y2 to pr ab dj pn a9 pm tw sq ig hi bg ni ry lv wy ic bc li qe im dv rq xy ki i5 fa fv uu af do vv za l3 bi kd nx w8 nt lh hu ra ub un ec rj ua fk ir s0 f4 uf dw jt k2 kz ml cl km wv vv es tb yj w5 rn yo af ru ah ig +\n vg wr zh wo on ew ef ae ha id uf eg p9 ef gi al ng 16 rz o3 +\n qs jw qh cv z4 ok wt k8 kg km wa uu us sj oy iv tw jm c9 fo nd 20 qw w3 yi re qo yv rr op qp ue oh s3 uu px jc hx wf v2 br ep wg pz t7 t9 au re zj kn xc bo kg 1v hb wv tt u9 gj yu ry iw dp o8 +\n qd wi ij rh ef fe jm kw xj wh uk ef ti e2 j8 ou xo ny wh rp wj ub s7 pb nb qv ev o6 o7 yx +\n gr dc ft qs gm qd dn k6 lo k9 nb as zg bz lw ui ee g4 dl qv q9 lu jg rx w4 yj ep oo sv uq hq yw ao fc e3 ui dy du sk gc gy qs l7 kz ed ej wl un yu wm oc gq qk qc ks tk ti eq em ly vl er ry sy yo ro eo +\n lq d7 i4 7w y0 qt gw ch o6 eo +\n fr hb dc o0 yb hn gi jh sw kj we o1 vg nm q8 bz zk bf ml ev ed r8 iv ht fg th qv vz d3 ng xj 0h 42 ew vt yg qr qt ha qu hs qp ij yn eg of tl p8 fz oh iv jl ss dy zu or sk uj co kt rp wb wx fg ev t9 rj yp u5 us ys ak rw al io kc dt jr hl ln wl wz gy wy qv qb mu hd ky ku zp ww yw rl oh ee w4 yz +\n fu dg qf pg jg o1 dc by q4 st t3 lj ve jr am 2i rz ea lh pl ed pz y4 g8 i2 db g0 fj q9 qn bl en hr m8 qw rn qt yi ei yk qu xi uh fy yn ix uy gn jx f2 gr fi x2 zo pl vh ek sz u1 s7 ya em u5 da re f7 hl qh ju oz ar zb ci tk ob n7 vh og w1 ok er o5 ri ro tw rp it +\n gv ra fr ub h0 hm pf qj kk zf zh rj eq d7 oe eh ib oi gg i4 jd ph nu gc qw rr m3 vj ry is dk qi rm qy qu ep p3 ed pd ta s3 tc fd sa im ow jc oe qi j0 gt bm vm zf nj rg w7 x2 nr wf hi rp wk co t6 t7 e6 ag eb u3 e9 f4 om o2 dk h4 gq jo cr oz ka kx rn wn do ep wb vn ef rz ew yi r2 ro so ob +\n ft a4 qs pq iz pd u5 cs q3 qz ra rh w7 rk mv kv ee y1 to dj sj ta pn oi tf i2 th q0 vx vf ww 2l cb wt yq ku ye gs qe w4 qy qi xi tt es qp ed ef ti i7 tc pl jz ho zo qi za fy zy rk x2 r3 ht yv ex op ae iq u2 ag pb of dd h4 lq wx cy cu zy wm ry ef dj vx st ia ey te +\n rs al qd uq ga qj sw we pa bi ba e4 yy mo d6 er et ti rb py ek am ib fe y7 fh jv mn qe qr oe c0 l1 qi mh 44 xe ei ev hq ix e1 pg pj ui hp pm fr qs kd nk 1v wj fa wf yt t5 vp ex wx fh pn ug fc pq io gh dg oy nf v6 bt jo qz gu me wm n7 br tx mt q1 su eu di uz am if uc aj +\n da a6 q1 ph uv oj ji mp t5 mi rj cf jl w0 pk ew ii rv oe r9 ic id sl se su q9 vd we j3 ac d9 yw ew w3 y0 tk ao hr in e4 hu du qu jb wp cr qs v9 p5 vi xm kf s1 ea t2 wh y1 co iq yo au iy on ds fx yf qa zv qv f1 y8 wm u8 rc o3 +\n iu r5 el dz rt m9 hb lc x2 zp aw uz +\n k0 px qe qr i2 yz qo ap t1 ou n4 +\n qg q1 wr wt wu 5x ij rg lq eg ia r9 is dl aw g9 xx w2 qt au i7 us jc f2 ge qa gt l7 lb mc x3 3p tz u6 kx f8 fb ku ag hd oj o3 fn tw +\n ds rs k5 go qg ga qj gs by q3 xy q6 k5 4k o8 ws td mo w8 th ys eq pk yf r5 uo rb r9 td y8 tg ho qn gz li m0 oq kw qr g1 wy iv b7 vt qr qu ti to ta ut sa i0 pl oq sd ho qa gy qq l4 ks fu wg qg kj eh ez yu tf s7 os s9 ya em pq tc fv qg ve sx af ci ah qj bj df ry rl wm zy tv ol ey ox ri ie tq ir yc +\n ak ra yb ds gt fy qh d3 ql jk jl ni zs q5 zf lf so wo mu yt wa w8 kl ue e7 2d mb yn tu ac pv id pm sq sw jo dv jd jg qq qw qe wr j5 wu 1h b6 vr yf cx lz rn ho gh qi es ev ty p7 fx fs s5 pl sf lh sh i8 qa xs 1o kq zg qh wk fs vo wl ez iq uo tj u3 gs ii je jr hk ql xx 1j v8 nz kf vz ww yw yt w4 rb ol o4 rn ux ig sp gc +\n yv fr qa rd gm ps jd a8 qh ls vg q5 lg eh z0 vt mi vy rg lp ex ew d6 yg rv oe fs sz g6 sy ha cx qq wy j6 dk hr l1 qe gl ex ln uk sv ty at ru uc ts hi hl lg jv qi vc m0 fy xg qg eo hf mu mo kz ot np oy na el yy wz fh gp up ir e9 s9 f4 gf pw uh uj jr ab qh uc wl ce qz h8 v9 wv ie 37 eu gf yv 1m ma yw wm oh dk sr oc ei o8 +\n qn cd zf y4 oi dv xq q0 lc av cw ki xd lx qi gn bh em uf we ja ox iw qb wn my zs y9 ux +\n qd qf we ls lf k4 eg bc e5 rl ea r4 oq er ip g2 yl ot iv ps gx qr wy xj vz xl bx 3o qr eu qi uj p7 uc ph in pk qt i4 gq wp v6 kw kd xk zw 11 yj wj rd oz th yo eb ya tl au tx qj wl dz wz cg zv qa rb wm 7a zs vj yw ee eo +\n jd go qg d2 ji qn wa bf t8 ys eq ui d6 ed yn r7 is qb q9 lp lz qe c0 wu tx wa te qp 64 uq in qt qy wp j0 lz l5 og ca sz un ec rh pb pw h2 kv aw wy qf 16 rw ew tb aj +\n a2 gr qs fu db qn q1 uc jr qk cn q6 b2 ne lg q7 q8 wi wp b1 ec rk yj pc fo iv sk gk jb qm zw m1 wx zt xy wy em 41 ee gh xg cn yv qp sn od ao pj fs ut s5 tb ad jc j9 xa uj ws kf wg vp nv fa wk mq x6 vh wv t4 ex iq 7r y6 sv ox ev eb rj rk em aj pq gh f8 th os sb mt ak q1 xr yw ti ee tb as ox o5 yo gx uc +\n qj lp z0 aj wp vr wa bb xt w9 ya on ew ym ia ix pt tw dz jo ae cc qe lc qr cn b3 c0 ib ml qi uj qp pf p8 e1 s3 tn ui sg pn i8 hb ij qw pd ld fo ap ty ro 3b r0 sz ie gp rj e9 fk gd pw rr uj cf qz zr rq 4p kp pr vj w5 iq ey rn ie eo ir pi +\n gr rs gy pw qd ga jj z3 kj ql nn bg dm zz uy pl e0 lh ef oe am y5 fd qx hi uw i4 q9 hs jb vd cx ni qw wx zt qr d0 wi 43 w3 cc b9 qa rw oa ev ry p4 en tk ti yq pd i5 og ic ye so tc de pj ff hl oe sj qs wf v9 xn gm wg xm 1f ph dr vg wk ns t6 um oa e8 sb t0 gs sm fx o1 de h1 uk qh zj zk ng ct gp nx xe 3z wm rz yk tn ro +\n qa pt k7 og kl wy rp hx wp wa ui mx eb 95 ac eg dj yz aq in ih i2 q0 cz cb dg xi cq jc qe qt es ed sb en iz fp ta fc tv tn gw ka i0 lz sd il qf 1s iz qf nc xj xk ep r7 rp gu t7 wc t0 en tl iy iu pw kn km ql ct qp ch fl wm n6 rw eo qm vx ty ee ru ig +\n um rf qd db qf od d1 mb u0 le xu wy q6 mt bc qw cm uu us r5 uf or tq ek sx i1 it la cb ax t0 wu ab 1t qq g6 ko g7 mk qr ey ha ea qp y0 en ue tv ho i6 i8 sp xs qf v9 jl kt rk qy ot 14 na ub aq op yo en tk ob on tx f0 qk jp vi iw tj x9 zi n6 wo wb se aa ag oc gx +\n iy ub gy pt pd qf me xp w7 rj tk r4 rx ui ii r7 us pb pt g5 fw gf dm wi w1 eu re tq oo es pd ri tl og s2 fx ap ok i4 di lh f2 1i vm cp bh wj wx of on tx dt h2 hl qk wq qz lr tl f3 ce kp yr yg ro yx +\n k6 qf cp la wp gv es pl uo eg am tf y7 i3 hd jk we d7 rl b8 gg ug es rt p5 eg em tz ow 3y eo wg t1 lc wk ol tj en ak fc f6 df gt ol qc rn tz wv rx di ov +\n pp qd iz qm vk jg r4 pl ym y7 sc qn jf qy rq p8 yr di qu hb wd rf ks gw qg s1 x7 ec ae iw eb ai sq v8 h8 le ea vh yw yp +\n ik a7 cp sq q1 lq ql wa qz lr zh rp ra gb w9 ys ui ym px up r9 pr ek qv qb hs bg wt ku pu dc p1 qo ik uk y9 y0 en hr tx ts pk jl ce lj l5 p6 v4 wk nu vg oy aq aw rg os az uj kc py ql oj qc pc fj jr bf cx es vn q4 y0 og w2 ue u8 is ag ie yc +\n rs dd ik k5 hm dg k7 go q1 qk wt q7 wi ws t6 k0 go ii ee io ym ey sl sz sw jg si d3 qq qw nh lp cc kw xt m3 ip ln nf zm qq tc ex ry at iz p7 ux of he og dq e1 i7 pj sp s4 ok qt gt sd xf ow qr pd hd wj qh x3 yb lx wx um e6 t8 s7 uo u2 it sw pm rr qg h3 aq ze h8 ks zb kb bh ec wb vb w2 oj af +\n ak ds dh jg cp ws q5 nq wy su q7 kb o7 ys sf et r9 ta sq y6 dn sy cx na j6 jc qi qw qe qr rb tn 3g eo uh tr ft ri uw of i5 ue ta fs s3 uy as ss qu ns lj wp zf wg sm x1 ix mc va mi rx ej yy y4 t7 ex u1 y6 u3 up en au ds ap kv qh kn gw k1 zv eu lu kh tx qk dr dh wm ti h5 o4 w6 yk af fq so aj +\n uv sa hb ps q4 as wi ej qm zc yd yn fp y3 td hy ue qw qy es tu uq tx e3 jz ud sv l6 fu xh dq wk wx yi dj qz v0 qd ga mp wm yy tn fn yx +\n qh qz ar qq ma kq rx qa st ei +\n dc df il he c1 jt qn yd yn pe et pn pi d7 ke g2 j6 rl sk ng z0 m8 mh qw j1 eu qu rr es ec uk ev ul pf e4 sg jv m9 qf vd wk gu rh e9 f3 on qv vj dh aa ru ux yx o8 a1 +\n ra qs h0 qh bf q3 dv bl mr if ws df ev b2 pl om tz ax yk ta y7 aw dn zr ax qt m5 xx wp qy qi qo at ti p7 tv i0 fm qu sh so lk qp hb p5 xk ib vd hk t2 np ek yt um u1 ir sm yf ug az qj v5 wr fg zv af qv ck ay cs ww pq wn w1 yh as yk ei +\n tr yb df um qf iz k7 q3 we cb cj ne zg a2 e6 ya r3 ut on rq io ow qx ja qv cx cv bh vj qr lv pc 3a rm ep uk ed ev au p8 so fx p0 ts e4 fb hj qt dy px sf f1 zo vx qa wa sa qs vm wf xg kf fz r3 bu t1 tu ez t7 va e6 fl tz uf gg io qg qj h5 zz nh qz zt et ba lu tq vz xe bb md u7 oh 5k rv rt tb yu tn ah +\n gr da ty qj by we ls av kc qc wi wo xr mx cm yg oe xs pr ua pt dk oy hp qm qq zw vk xi ln he rx ko dz yt qe tv eu qi yz tt y9 ev ry ym ay uq pg oj aa s4 sg hp f1 qu wp qa bn vi os iz hw kt t2 rs wl r0 ez rf pv hs om dd f8 uj dj pt dk km k1 qz qx wc n3 nl wv qn zo vx ww dr yr oj r1 tq +\n ra jg jr ao c1 wh rj fp gz iy lo gc dh qw qr 8p eo ev fu tl i5 uy uu ui qp mb hk yt ou aq oi e9 ip dt k2 qx vb mf id +\n rd h0 qn ql la vg qz lw q8 ra sp ts pr av qc vs vg ku am z0 lo ry ev eh i8 aa pl dt du i4 zs w7 wj xl yg yh ra ex u4 pn lw gu pc on n9 n0 wm em tn +\n gb ik rd ql xi bd yr e3 qq w7 ex rz on ui yg ax fo pv ab ta jp qw xi wi qw qe fh mz eo gk qu uj ed ev en fo ux ye fv jv ws lx kr kf n5 qj ea s4 vh ez um tj ir od ga tk f5 dh uk pr pt in v9 js sv qb zn wb vl zj wm ca mu zs ef rl yw u8 er id uz ah +\n iy ij ub qs lo ql jk dv h0 wy cm q7 wu eh fq w8 hm w9 mv yd rz rx rv r9 eh pr ek dk el hi qc sy i4 qq lp jj we m2 g2 fo j5 wy m6 ve tx yg w3 rv rn rq qy hs tt y9 ry ym eh to e1 ur ff hk do wa kq jw p7 yp ky r2 wx oy uv ra yt t6 yy sz t7 wc s0 of ds om kx ng ql qz vj wt wb ly wm lw dh md ew w3 tv er as yu an gz si ro do +\n o9 k7 q2 dt 1i wa uu t8 ut mv ef uo g3 gj hp jn nt cm rj ms wi b6 im qu eo yc ex qp eg sf do sh i8 ih qa wa wf kd yo xj ql wf ek un wx t7 s8 rj f9 qh qk k1 lq h7 in nj um bu qv ov n7 bh bn 3z w1 yt et o4 gl +\n a2 gt rs ty rd rf qd qn jf qh k8 q1 qj ql d4 cg wt q5 z7 lr wf wu q7 sd yg yh g1 eg to el ih sw tf fg qx dv q0 wq qq uu px vl xi js jd ze la ud qy rr ky ft i5 em p8 p9 i8 hg im as jz tn qo ul wg 8d vs ap mq x6 no t3 ub wl tf iw rh ox ua pv ir us pb tx pw dg h1 uk ux cr sz ko wx jw vl rc tv af du ei +\n gm we cm jx lf vq vw kb wk e3 df r3 r4 ew yf ti id fe fr su xr sl jg rq rw uq tp ss qy ws od nv wg ro t7 ar th ak da yf sw io jt cq v9 kb iy u9 +\n qd ga q1 h8 xt um wt nq wy wp a2 rg w7 hm cf tj ut r3 ch oe r8 pa qb jb zw mm wq pl m2 wr wy mh hi ei qy nw uf yv s1 fx ut sa tb ss hl qu qi zp nf zd ar l5 5h gm vo ix xk wk wf vf el r0 sx e6 uo rj f3 em dd uh qj cf wz n9 ga tc qk mu rt ye w4 o4 ad ag +\n qa jr kz c3 c6 vp e0 ng wu ug ty uk tu to hr sp ud m0 ar pa qf wf kr fi ya kk wl xs ed mp x6 ub gu fh rj e9 ya om wl vj ha ex y0 id +\n qm q2 oh cd q7 kk ld ys yd rv yk id wt qy iz ri fi i5 ic e1 ht 5z iq ha ai sq pn al gh un kt wq mi dr ax u8 u9 gk ru ov hc ep +\n iy sa un h9 rf fi he uc u6 cd q6 wu zl zz rk lf yd rx d7 ef er rb d9 r9 im hu zv ps qb jf qm m8 qq ji g2 kt qq ew la xy qo es ft ik tl ye ur as tb m9 i8 qa ka qs bm zg ix ya kl t1 wj r9 oi um aw yo ie ys yf hg gq nh zc sb nw qf xm bc xr bj es rx w3 yj iq tm di gx o7 pi aj sp +\n il qf pd k6 h0 na is q8 4p zl jl z5 hm ec io sf dk if gd qw 1a ld lf qr yx re tq y9 pd iz yw sa wp bn jq w6 v3 x2 br ta yi ha en o1 io ip pr kp nl lt kd eu kf kn n8 zs rx ux +\n ih db gm jd wr zj xp vp qb c8 pc g7 uf uz p7 sh or xh xm wh mt no fh dh wv tk li qm vb ms if +\n he ql wi bn c1 rc ip ia av or y8 mx yr dx ex gz 1p ic wf aj kn 51 bj wn o6 +\n hb ty dv gu ps qj ls qz ch q8 zh xp bs vt rh oe ot pb y5 y6 fr ih sc q0 re zx lm id xp yy qr ry ay p6 he dq s4 ff qt sd vx jb qo qp gb ws wd sd co fp kg s1 nm rp cu 8l y2 tf ev sn au us fz hj qg wc u4 au qh wv bn eq r1 +\n uw vr eq rx et rb fa ek id qx ui kr wn uf p4 tl au hw tx im sf yd dz bo wb xw +\n uv yb ik qd gm gp k8 qk ao z6 ps mw zf jc eg a1 wa 7c zz rh yi lf pl r7 yh d8 g2 r0 tq su cz pl qe qe wr wv ku ho qt yv uj ij es ec ik yn ym uw tl sm he p8 fa ho wo gy ws zf bw nb 5q ql t1 ro rp ej xg uv el l8 rd wz rg go rh sv fh ya it pn hd ao az tc dr ac dy ot sj nd qz ok um ol sx xb wb wi n8 ji rz yr sr h6 et o3 ru rm pi +\n rs fi ag c3 lw ys ef sg qu qi uq eh e4 gy qt ya ro hx oa f5 1j qa cl wq rl yh pu +\n ub rd qd fi jl zk oq r8 y1 tp sl i2 qn sd cq 6d mj w3 p6 ta fm bo nv qi wh yj e0 ao uh kn h6 r2 +\n pa q1 fm c4 ig ex 2a yi mx ek ez dv jf qw qe 4s xt ld dh qq mg qr yc eh s4 hj yy s9 pv rr uj or qj cd wc ly x0 wv hh ye ew yh rb yk o5 tm +\n pp q3 mw rd up td j2 lv af ih hb ee xh yy ua ug aa tb +\n sa tr ds az qd fi dn hw qg dh qh nt z3 qz ad q7 q8 tf vu ue mx vp lg tz er yj to hy fr sw th qn hf gx jj pz wt lb cm m7 wi b7 vr lo yl qi ry ef sn uq ri fx oh i3 sd i4 ho vb wa qa ik uk ar hw l8 ya cw s4 wg r7 ot wk gu u1 fh th rk en sm u5 iy iu re pr hk qg kn gq cf h8 nj ct gp wb qg hj wm cy ok er tv u0 sy fq o6 gx eo sp ob +\n yv ak ra co wy zj e7 ew tl fo ek ez im q0 jm bj lc tc rm ec ou bn sd os x2 lh wj ot oi y6 e6 yp ob sq p0 js qh el bg rr rc xw pu +\n ih um k9 q4 ls jx ej om sf uh dz oi qx cl zm qw qr zc qe i2 i6 uu qp wp ws qd sd fj mx qk yn wj ub gu ar pn rr qg ln dl al vg mf w6 +\n tr ub ds jd gp qk jk d4 kv xo ws gi yo sj sl el tw i3 ow qe zx nx b4 qq ee eu uf uh ex p2 rr ea ry ef eb y0 en ri eh e1 oh fx fv sj jn xf qd vi l7 wg x7 r9 uv ek yt ns aw sx sc vf tk ud ds o2 pr kv ab gt v6 un qz wr wv rb os ie u4 rm zm rw n8 vc za q3 zu yy o3 yi ag pu +\n ij a4 uj gg jy dt 1w rj a6 r3 ii pe r0 ej ta ts ff i2 ho ov wq kw qt ot m7 qq xv ei lv kr yx yb ri fa ur de pj hi si jq wg r4 x5 hj oy 5i u3 tx tc nd v6 oz wc qv bz qb qj zl dg ed ka vh w3 yt ey w6 +\n o9 ft az ps hq uq a8 ql we wg z8 ye wk bf rs wa c6 dd ys rl wy om pe ix y3 g4 dz gf se tg pa va jn jj al qw sf ma j5 qy wu xo dc rn se eu xb nw qu qi p4 ef ru sm eh im ad gm jv pm zd g0 wg qf ai qz ym qc t8 op iw ox ay tc av k1 ko vj qb zo wq bg q2 n0 rl yt as rn uz +\n o0 jq qf he qh 7k q7 kb wp z5 tl ew yg et or ez jp g9 jv gk lx vk vw qa qo ou qg kk xz rx ro wc oa us ip x0 ku hp jr o3 +\n pp dc gi fi qf ql by we la za un qz q4 jc zh wp kg o9 qm bm wt r6 rw eg ix yl tp am a0 aw i2 fh th xq gc eq xx yr qt xt nw qu ri uq tl ue pj p0 hk vx uf jm kq ws jl 1s p6 ca he x2 wk wd r5 wg bi hk ro wj t5 sx fh sv e9 ya aj e0 pn ao ug ac kn h4 gq nj wr cu qs kf vx xw k1 og yt u0 yk di gx dp +\n ij tt ss dv a6 uz gp qk cv lq ql un kz gj wt 4y fq lh z0 6h w8 vp r5 ee tu sg pv y4 pu a0 tg q9 gx qq qw we la wx rr ls zy qu wi xz wi xp ew qe rn ei qo uj rt fy ik tr tk sn pf i5 tc sp s4 in gv i0 f1 si ks nl kw bq co mu eh oi ec sc wc u3 ga fk sm om kb wx bo zj hv y0 en og q6 er tv tb rb u0 w6 tm +\n rd ik og q3 q5 cn xp c4 ig mi e0 rc ym id tq ou po gg qb sy ob hf pk xr qr up j6 ng xx b0 qt tm eo vw ux yw pg tc e4 gy p4 xv pd wg n5 r3 wk iv rl ht oy uv ub wc ar t9 ga s0 em pw x0 pt bw wm vv vm yg fn ad af do +\n hb gg kl q5 t1 mi a4 b9 r4 ee up pr g8 gl q0 cc kr c9 vq yy wa qy mz ty yn yq ai og tx tn nd ws 1d ky x3 sz td gu t8 op gs tz de av sk cy zm be wv qk og uc +\n ph qj d2 cd q3 q4 bi wp vt oq y1 ps cw kn gz ij p4 sp e4 wa sx nj v1 w7 me s7 e9 tc k1 lw zc vj wb kb tw a1 aj +\n rd a5 hq qg qh q1 la cd kl mp k8 mj vy zz yu ut uo sg yz hi gk sy q0 m1 qw b5 wi dz qw rc aw eu zr uk ti em yr lk kw nz wg fx tt wg x7 rr lm ju th tt eq oc o6 yx ro o8 a1 +\n a2 dm wy ej rh rg pe a9 oi y7 zt vk ga yf pp fh ml tj p5 sn tk im jv v6 lb pf zq ty wh t5 go sv e8 it f7 ac p9 cu bw kg qk f7 w2 ee w5 tq ep +\n vs rg rj 70 ys nq uf ex hh jn kg ep e0 +\n df q3 u9 4j bn rj hw up td i1 dc hi zb wv g3 l1 rz qt qy ty tj ef eg sm tx ap in px af mx r3 r6 t2 t4 rd uo e0 iy ii hh qg zc v8 qc ch px zy zi ye og er tm if +\n gr pq se pp qe lq n1 cy qb wb ey +\n gn q1 ji sc nh pe yh qt ss rw hf kx zm o6 gx +\n ih hq ap bl wi wa 3y er pc eh r0 yl ta ts dl gg fg i3 hp kw lc ls rl ff wg qi uh uk yq yw ok as wp gc jm qf to yy fh e9 pn qk sz nm li q1 vb yq 2e rl tv sy di sp +\n o0 yb rf k6 qm fv q5 wi rp fe dd mz rz ee oe ia yz am ig hp fj su gl li we m2 ls xj md z0 uh yx eb eh ur i8 qy oe i5 jv ce jb jm lx ci kg oy hx e5 u2 tj kv qh qo af pv tz az vg yz ri ge +\n il z2 d2 cs ba wa 1o ys uy ed er d8 sh qx sr qb jd ov xq nu lv g1 ku pu rp qq ee et rm eu xh i5 p8 tx in i3 bn v3 ap r5 oy sl oo dr dg hj lm sk ff vu cu wb kd zi wv mu w3 yt ok rv ol ey yx ah +\n hv qs qf qm ph o2 zg wa a2 rl pz ow uo y2 ey ix us d0 ek fg ww j4 wv a7 wu qq bv te tr uj tp ue ts do qo cy uk j5 ra ou aq iq ev tj u5 tx gg df dg h4 qj nc wz v7 im kv jt y8 rz w2 yy ei ge +\n gt df jg og k0 lq kz zf iw kh gv cn ur ea eq yj ix id ez dc qc st wq c0 lm fa lj qq mj sw qe xb rq qo yn ru at e1 p9 s2 ts i8 s5 i3 sf jc xa hb qq gy wd p5 ow qf wj 1n wd qz yt ex e5 op at sm ud tz yf tc ax f7 dg qg ve sl qv tl wn 2h ky yv f8 rt o8 +\n yv dh kj jl wr bi kc 4j nt c5 lo z3 e8 on or g3 g8 uq sr qm hd ll c0 nh ws qu ug ph tc dy oq qo nj wn t7 ox zj qj km h6 ql zz qz qc hn bk fw ob +\n un qs fu k7 co je gp o1 bg dt vu rj mc rz rx r6 g3 ek qc uw fj li qw lx ku z9 br b6 mz yc ty tl yw yr e4 i3 ud ce i9 rf bq xh ep wf ej rp vu wl u1 os ay of pm ap gg dt hk ab ql lq qs lt nl u3 wq n7 bm ef xm yh w6 ru fq tw +\n qn ql zj rg ed hs we qw re p7 p8 yr tv pc lh gx i8 wp lz cp fv lq 1b di +\n rs q0 is q0 yq rl qq vr qa v3 tu in h7 zy u9 o7 +\n ak pw af z0 wa jh tf to ey r0 ta fe tf th wt m5 xu wu xo l1 b7 bv se w4 qi es dy ge vm l8 nv kh l0 j9 bi ez iw ux f0 gt zc 6w bf cx u8 w6 yo o6 fw +\n gb py gp pg ql um lf bx 6q ra w7 vu rj ui pj tl ii y1 r8 ac eg yl sj tp y3 py im tg zv ll ip wt av fq qw dc yu ei uf qu tw y9 em tl dq fx hk oq zu jx hb i9 bq iz mv wd qi pz lx ek aw fg ag u4 ir tk of pb az f7 qk wz le qs wy wn dd bj mp yq zb cj rc tm yo +\n o0 pa rd qf dn qg nm ji q6 cm wp ec uu ax r8 us aq se lt g1 bl vz jc mj 6h ul en yw e1 ye tc i0 do ge gn v2 r1 7f ed x8 rf oo t8 s9 u5 pb fc ug ab pt uc ce qz h8 u3 ga fl bc yq iq iw id o6 r2 te +\n da qf qn nm wr jw c2 ig rj vi ys pl ed ii ax y1 ua r9 ia ab tq an ek dl sl jo g8 qv gl hs jf d5 c7 kt ix wy wi lm qq dz ko qe ff pp qt eu wd yx ec p3 rt ty ik p6 pg i6 e3 sa fd dr gb jl as hz qo j9 j0 qs qd wf p7 br wd x5 hh t2 wl el rf tg ar rj tk em ud pn rw av iq nl qv x8 ov wq wb ec vm y0 w2 ew 5k w6 fw a1 +\n a4 a5 z1 hr qk q3 mq zf qc wu q8 bd a3 xf es yn rc et d8 pr or yl fa se dv dn uy vz wu en mb qa tj uq i6 pl du jx f1 xs qs qd vm kd wh kh mv ed rp ra co tg oa u2 ie ha ir da pr cq uv oy qb qb eo ye rz rc ei o6 id if do yc +\n a3 qs w0 po gx xo nh uj e1 lz os wj uv ud tx rr gq ve ch cs xz +\n rs rd qs qd hw dh q1 ql dy mj zz ws vy pj ea mv yf om uf sg up ix pb ab ej tq fr tg i3 nq dn gc wx wc qr wr lv t0 cm wy wu ko qe qr ze ug oa ed ym p5 os uq i5 tp pg s1 ok tb fb vx ns p1 wa qs ka qd lx ps sf zy kj pl ro rs rd wz tf ev gp e8 u3 ir od f5 dh qj cw qk h6 ql ad qb fj tl al zs h2 rl eq rx er w5 eu yz id pu hc te +\n pa pw q0 j4 4f vq iv yu ry fa e4 kw xm wj t3 ff ye w1 oj rv ul ep +\n mw di ec wt rx ko i4 qo l3 iq iw py yl +\n dx uv yv qa a3 ij ps qh cg qc 2n mc ut eq rz ea kc pz sj dl in db fk su qm qe m2 we 1q ke bn xy wb yq qq vr qw xc gf tn re oo qo p8 iv e2 tc e3 e4 fv ff pl sd qy qi si pm ws aa zw bu hu fn yj pv hs gh o2 dy ln v5 qv zb tk bq 4p qj zz wv 8n h1 y9 wm yw og mf u7 tq ov sp +\n iy wt gx nd t5 r0 yl tg dc qc th wt ld nd zn tc ke qu qo qp tk fa hh gn qp 5d qd ar rg oz fh at ag 2a kd nx w2 w5 +\n il wp ee ym tu ef dl el qb cl qn ob qe qr m6 mf xq i2 ud fn pc gw m9 l7 fs eh gi e7 fk ys pe ok 30 mf o8 uc +\n db k5 a7 je kj q3 we wt q6 ie ck kg kn gr lf pj io us id in aq jo qx su hd qm li qq jm we lc wc ld d8 lb xj em rn j4 tq oo eg fl sm he ue so hg ok dt qt px j7 qi nz l9 lj x8 wj na wk ez ex rg e7 u5 h4 kn ad cu oa qd do q4 eq w3 yy sy su r1 ri if yc uc +\n fr ij ft db dn gp qh ph ga gg kl ws wt ab q8 lk wp mi w9 tj pk yf ew us yz id gd y7 dc qx hp qv gl jn q0 d4 qw re qe cn cq pt wu lm dk cz yy qr rq te qi rr ea ex ye dq ok qt sg qa nk wh kt bt bd lh wf yb hu mw el rd rg sb em on qg wq oj zx wv n4 bo qf bf re wb ev yq cl yu w5 ad ag id a1 gc +\n qd ga dt ej kn r5 ax sg ix av am pu g5 ez fe qm nu ii zt wr vm qt jd im rb ml yx yv ru hr gv ad dw x4 ub hx wz rd ol oo rg yf f6 ii uk dl wl yw yu ie id +\n yv ga z3 kk pp nq le lr bp qc t1 c2 hc vt lw jl w9 ur r3 ys iu es rc ud yj r9 pb ot ta sk gj jm gx xg sf lc qr ht ve sl g7 qy nw vw fo ta tb oq fn qu hc qp op nz ow wk zo zq yg wg ke yt kr yy sb tk rk tz iu o1 rr pr qh dl dz p0 n2 ci cd vn ms aa yh ry w6 af du gc +\n q1 q2 mw bz k6 xf ec r4 rx yg ed d8 pv is sj qc q9 zw vf gc cv d0 xx rn ex uj ij ts ff ge i8 zg 4m x5 vh oy yy y5 wc tg at fk ob fv f9 ql bo k4 zn be ww ea ry tv w4 ru ov +\n tu g2 tq od pk tm fi y1 uf ku wn ew +\n hn rd um qg qh ph aa zn bc gv w8 rj ea es ui r7 r8 ey fw gh jf qn nu cc la 3u bx ve po et ei eo ea qp ul i7 uu fb dt pz qt m0 zf l8 kl t1 ej wj oy rf th rk gs sm em ap hg o2 ub wx ka hd br q2 hg y8 2e eq tb an oc it ep +\n tt um gi qh lp kl lw q4 q6 ro b1 if y6 qc th g0 q9 qm j2 we xt xi nd is ng bc ku yw sm ye dw e2 f1 lg qo wp zs gy l4 ul lv w9 br xl ql vf as yg y3 t5 wc ec iy hf ii f6 re hk qz jp oo qx xv v0 f2 vx cd vb yq ew zu yx +\n lo dt mt z3 rg av us pa xq wq qe qt yx y9 ev ry tk hu oe oi r1 x7 wk wz td jy ww qc 15 ba hd mo 72 +\n rs wi vt rh we jl ur tz tw ht y8 fh i3 qb qm b3 qy ep op yn tu ay hw fd ug qp qd x7 rs yy td u1 t9 sm uh dz ql 4t rw kn wn rc eo +\n a4 d3 kk q5 q6 wf wg m4 2b vt w7 ur uo rw pc g2 sl if y8 fj va rr ld wn xo qw rn ml la qu ep re rr qo pd eg og e1 i8 ui qt px i4 jc gq oe jj ws ks qd ul zh sm ql tf go e8 os tk rk ay us u6 dw dh pr qh qj oy lm jo cf ff wm br k1 en og aa rb yj o4 te +\n gb dd rd qd a6 qj wt jx z7 xi q7 kv mv uy pk or yk ek el y5 ez aq dx qx th sy jn pe vl fp xz m8 ng jh kq qr la ei ft p9 oh hj tn ho ud xs wa jq vn il zg p7 fp ic qk wd bu e7 go hd sq ug hh ip sl ch qc px wb hs rq qh bk rl ef yw dj yt u9 st yi uz uc a1 +\n al tt pq um uq un z6 wa vu w8 ed sj r0 tq pu dz qx js 2j na ip vz lm qq qe yj ud ei wf qi te p1 tu il tk iv dy i0 xg sf ix gp fk ai qk lm ql ch fg qv vg yw rl yy rv rm pu uc +\n rd ik qd jd ph gs k0 q3 qz ia q6 af q7 6w o8 tg gi sj ou aq po ja qn q0 qq gc nh xt wr fs m8 qw aq wp ho qu rm uh tr qp tj ay fi ao i8 aa i9 tv gv qu wo lj vv wa jm qa qd uk nl g0 qd dn gw ic kj nn wf wg dy ej rp y3 rs yy e6 wc oz fh eb e0 of hd yf uf ab gw qc ww yc cd ji y7 n0 wn cg u0 rn yp ie a1 dp o8 +\n ih h9 qd xy yl ez g9 lt qm on vg rz dx qa kt p1 ex yx od uz e3 in sd oi qa cq dr me e8 ua ya dk wx bw 4p vx tn o7 pu +\n ij rf fu jt gs ld wu q7 wo 2u bd k8 rg ws gi oe yl if sq hi dn jn qw bb cb wt lm sq vr qe wd qi qo tk uc hp i0 pa w6 fo v4 1m x3 t7 u5 sq ai hg ap hm ju fl tz wv w4 ry tn yl fm gl ox +\n ql db ch wu rl ih qc 25 pb qq ty yw fp ao qy sp p1 qa rf iu rw qg uk gq km dz wv at qb jo eq ur rb ad +\n ra fy gm iz qk qz lf bp kc is nr ws mb es tl d6 up pe ey sj fq ek iv pn sx ly qb jd jn q0 lp m2 xl fs xx rs b8 hu rn ey qo yn vr yq ti ai e1 so ts jz du do oi sa i0 oq ow 3r 1a wg qg r4 yv ty r8 wk wl s7 u4 of e0 gd pm yf h1 qg n1 lt sv qb eu wi mt ez w2 yk su dp +\n rd qf dz aa bo pd pm qw rn tf ah wu +\n dv jd he jt ao ql zg eq pz oe dj fw sc fj nt io fi lr xu ns mx qe qt ei rq qy yw em e1 i8 sp in jv wo ci fa x6 fn ej wv oi um yi oc au yf mt te az yv yi ad yo yz +\n uv hv ty qd nv jh qj q1 ql we fv vj q7 gw fe wl vu w8 vp 6k yd r7 yj ia ey ot g6 dx tf im hu ae qx fh g9 lt fk hs su ov lo m1 cn t9 wi ki qq qw xx aw nw es yb vw yn ry pd ix em so ut oj du f2 lj qp jm w5 xh ny wg 13 wc qc ek el sx oo th uo yo at pv hn uh hj qj zk ql lw zx qv cc wv en yr w3 yy st uy iq ox an ah +\n rs pa df il iz qm k9 bu jz bi ji du lo ts yy xf cv gu mc ii rc up d8 ey pv av to yz y5 fd qx sc qv jv qr xt bk m6 ot md qq qt rq ex p2 yn sb xc fp pj qt ce wp i8 j0 wa qd gn ps qf be qt wh ky l9 za wg rp wn fh rh em vn dh vw ng wz k2 h8 f1 nz zh yz q5 zy e1 yh ad tw ep te +\n db wr a1 pk ew uu r7 d0 pn fe g8 la qq b0 ef os oh pk fm wa wk yi ev ua sq wu n5 tw xc er +\n fr yb qa hm d2 q2 o1 oj ox dm oc km kj r5 px rb et r9 y7 vs pj q0 4s lm gs qe eu ep ti tl of jq od pf nr nb ea ej yy rh u2 iu qh dk zl qv xe 2k vc vb zb xn yg gk ox tw +\n hb dc rd fu gu zd js wu xa c5 a5 w9 vo r5 d0 g3 oy ib i3 ha jm nu rr wy m8 b9 ws qu ru eg uz hw eh hg sp sf do jb zp dp nz wj wv fg ae ah ob hd dd gh dz qz xc s5 vi je n4 re bh ma wm as st tn yl +\n wi w7 om ug qa x4 yn r7 gi re n3 n7 +\n ij pa qd qg uw qm d4 z4 q8 t3 mu yp uf ia pm ez ih qn jm nu kw qr j6 qw bb yu qs rw wf re qi ru jz tm gw lh ce xa wa xs bn nl ys t1 wk r9 gu oc u4 hd ku hp yg rv as yz ro dp +\n qa ss dc gu qk cs cv fv nm z7 lf z8 xs a3 rk r5 ys eg y1 po qv cl jf xq vh we wr qr b3 bv yr wf re qo sv tj ti eg dq ic fx jz du qp vb ws nl wd wj zq vg t2 zf wb tf yu ex yi yp tj en ua ud dr pe qk dl lq qz h7 ol v8 cy vi wv ck el gd q2 yw w1 ye xq w5 gk o6 ob +\n k5 hr jk ju k3 jq q6 zg wi id bb wa gb rf rq g1 et ot pn ht dc ww c7 we c8 cm xo mg w1 1l yx tr p2 oo lm ry ao e2 i9 e4 hi tn di lv cp ca 2u t2 no ub ex rk ys pw qg av py ql qo lb pn eo wb er tb yk ie id r2 tw o8 +\n ra qa qd ph jh d2 dx d4 2z jl q5 ld cm wu wi 2t wa dd lg ui to id in uq ww rr g2 wu rl qe 1l qi qo ec yn ed uw p8 ut sj ig p4 zh xm p8 vs vg x7 ot cu l6 sx gu yp t0 gs az pe nf wl qz nj lr cy wr qv tj s7 u2 ly be br ym w2 af ri it ob +\n pp uv nb bu kz wi ah z3 c6 rg la vi oe ia ot pm dv gk 2h xq kq xg bv qr b9 j2 ec od ay p8 qi wp zd ay kg ea mq 6b qc un fh tl u5 av ub ji zx k2 wc zy 1x kc ah rw vc wv yq zv e2 rp +\n a2 iy sa ft pp un qn qz ol lf mg wo fr vu ya rk w0 pj pl el dz i3 jd su ob c8 pb id b9 ep yn ru tk s3 sh sj xa l3 wa nj ke kr ic xl bd ej rg yo f3 al f5 sw re uh h2 av cq bo vk kf bd mu wq wm ew ue tv ol tb o3 ul ov +\n iy a5 gu q2 se ls dt zf o4 dm ez jj uu ik ue w0 ya ea on ui tu rv y1 et r9 tq y5 ht dc fg i2 vs q0 av iv ku in il en ri p7 uc e2 ut sp fv qt gn f2 wo qa op v7 ws l6 wh ys zq t2 wc y3 sx yi t9 t0 ys of rq ug o2 av kn h5 ju ji ko v0 nz wn kf te dw u8 yt fn r1 ie yc it +\n qj lw ji eq oe g7 jf jc yr qo v7 p7 wd ma xg wz qb u7 w3 +\n un ol eh g5 px b8 rr og gn mx yf wv sl on jo uz +\n qg qm q5 wy eg ri bm mz d5 rx pt ek fs pi td ez ho gh q0 ll pl kq wr d0 l1 qq ko er qt wf ei p2 ru uq ye tx s4 hc zd vn ps ix zo wk t4 y3 xh ez rf u3 up ys ou xx zv qa wb at rm eu qj wv za zs eq zy rv ry tn tq yc ob +\n ss qa pp rd jf a7 lp h8 um kc q7 wl rg r3 w0 wy tl a0 ih ly qm qq m1 xg qr up ja b8 yh dc lx rw ep ea ev ay ux to p7 tp tb i3 qu gq do gr za l8 rj og oy ub e5 ae tg t0 sq tx hj ad gs it vc bh yb eb w2 yg u9 w5 fn iw si di ah hc +\n ub o0 ik ps qd q1 ga lp cf kl m3 z7 q8 ue ee ud ix g5 ib gd aq fh th pa qc pg ue ur xw ww qr vj m5 jd ng in tx ff xc er qs eo qi p2 ky pd eg e1 yr ut ib oj tb hi hk ho gm qu qi hc ou gn wg sn wh ix wj wj wg ot ra wl un e5 rg s7 t0 oc sm tz hf fx pw x0 wz th qv 1z zt n4 qb cl wn xq xr y8 rt y9 rz tb iw vb +\n qn lq bu eg iw wi 2u 3q t6 k0 yd sd ed rb eh ek yz if pu y6 in fr qc qm ob il ma b4 en wu dk nh b8 qe bb mj ws qt ho yl ug qi ea tw uh p5 eg tl yr i9 pl lh ce i7 wp qa xs dn 7p kr p7 eo vs mb pk ni yh ef rp wj ej y2 iq y6 u5 em e0 ii md jy lw nj fh bq pc xm km q2 wv k1 rx u7 ut et gj tb iw gx fw yx +\n qa pw k6 qn qg qh as u0 dy q7 wp hv 4z 4c w0 d7 et aw wr bl mx md j6 an wi qt lc yx ec tj ri fx ht in gm ua qo qa ik ys eq n7 wh rs wz wx e7 eb ak gg ip sj py ka rl su ag +\n gb uz q2 qz wr q4 z7 ia ad je am my vi zc mx ym r7 yk ua pt g6 hy y7 sx ih qx pa hp jd sy gk nh no qq yg rc 3s qy ep p2 yb oa tr eb p5 en ic yr dw tc in hk qt zp i8 lz ks ci lg x3 wd xa x5 zf yt y5 op u1 oa iw fh oc rk ay pb pw uh qg zj qh h5 nf cd nv qx kp qs qb 6q cl kh xe u7 ew tv sr as rt o4 ey tn is +\n hv qj bo ru z9 t3 lj q9 rg vi rj sd r8 g2 sj yl aq fe po pa qv jf dm qq re we la wt wu qq vt gj ei yz rr xk uk pf so pk im zu ua sg j8 sk zd sd xz zw kl wk ol um yi rh sv u5 pb tz dl oi wz h7 s8 qf wn cx f4 mo wb ed oh ee er ry eu ei oc fw +\n hn a7 cv q6 cj q8 fs jv rl qq qi od dt l5 co qr zq ex u2 ah on pr wx kp wb yh gx +\n gv qg je zg jc q8 fr r6 yn ii g1 pe sj ta el jo sr jv ni jj zr bj ns qr qi ur hz vu wh cs ep s3 hu ez rh u2 t0 dw uj oi wx n5 18 bf wb yq oh ov +\n gb dc um jr mn we bl t6 vi pj c4 d7 rb ia yz tf qn dm ke xb ft au ix tv xd qq xg rx x6 vg r8 wz op h3 qj qx lr xv qc kc wp lq ea rn rm ri eo yx +\n ra gt qs dv ik gn co qg qm qj cb qz z6 wt ji q6 dy qc b4 ws ds vu cf on yg d8 eh py hu tg qc hp qn d3 wq c9 pv pr or qq ml eo ug tw es il os fi uw to em ic oj ho px wo qp m0 qa 1o ks 7o cp wh wk wg x5 ee yn bi ef wj ns r0 ez um u1 iw eb ir fk ov s0 fl hn h1 pr x0 ux cd wz aq jp im k4 qv bp wm n0 vm u7 w4 gj tm uz te a1 +\n gv il ps db he nb wr ql kc zh tf mp lw ab us pn a0 tg pa th ps hf wc 1a yw l1 fs eq wp qr rw yv tr eh so i0 qf wf l7 wg na ou ah ay f4 io ip f8 cd h7 nj rn wb qb qn wp oj w3 w6 di id pu eo +\n hm fu pd qk bi wf q6 wu b2 q7 q8 oc lj c3 o7 6s a1 jh rg rj 2s z7 ya id ez fr gh vl cl zq hd jh xh ru c0 bz wu dl qw km kp b9 rn eu yc yc p4 ru tk ux fo ue p9 iv tv s5 do l4 cu rg w6 os fi 4b uz l7 ld l8 fx jb ee wx rp ek tg e8 uf de qh hz h4 qj gq nb wx qc sv go wm zi zo tc 3k ez ec rz ye oh ck w2 sy ia gk rm ei si dp +\n gi go z5 qz wj mg kl yh g5 y6 g9 xt p6 eh ap sa qu dw j8 ql yg aw t7 ir zj v5 v7 ba tw yq cz gc +\n ps qn z3 sw gs q4 ie gx ye wz r3 us ef d9 pb y6 tg y8 qb gc ww az c8 cb lv wy a9 qq qw l2 c8 qu uf yx qo ic de ut e4 uu tb fn oe dp wa uj bq sg mx lv v3 ya xk wd by n7 ra cp gu va yo u2 sv rk ir ya hf kc kp bo qb gp qb yc ku q3 dj o3 ey ad si o7 tw ge uc +\n dx yv ij pw a8 qm ph k9 dz q1 q3 cn wo wp my el bb uo on eh id yz am fe hy sw ha m8 vg wt vl wm qq w3 ls gj yx eo ef en ta e3 i3 zu hl m0 wd co zy l9 nn ea yj e5 rg gi fg gp u4 ir tl tz pm dd kc p9 zx sx qc qv kf ln on qm lw vn vm ew yg se as is di ro gc +\n al tt gu qf qj xo q8 c4 ws e5 ur vp ea rz g3 fw sx th db kq wt sv tb ad hv 1u gt ss xk wj qj pk rp e7 ha fk f6 dr rr hk dk nf qo lr ka ie fk cz yz q3 ym ks gl +\n gb q1 qk we q3 q4 t1 ox di ny wa ws gi ea rx yg r6 io ow y1 d8 ey ab g3 is ek pu ez dx qx th i3 jv fk io xh wt oe kr nd md pb vz wi ro se b9 tr yb p4 i5 p7 ux fp p8 sp in ok hj qy hz wa qq zd qd 3t wj aa dy 5u el yi uo go t0 u5 tl dq gd rw uf gg kb ux dj qj go wb zm lu tx vc es ev ry zt w2 tp w5 tn o6 +\n ra ps hm qf qg 4q we ql q4 z6 d1 wp vt xs tg 2s e7 r3 ys oq ef c4 av dj pn aw sr th hf gx uy wr ac zv m6 wn ko c5 qt qy yl yc uh od ri uq fz dq i7 tx fc aa uu qt oe i5 ge ce wa gb vn xg wh og ya xk fs ea yf zw wh ub 8x th iw rj ah ya e9 tl yd tx yf ii fc kx hl zj or qj mh ww kf zm lb ob qn wp ww wn ym u7 rv ie pu +\n uj by wo ml dl qx m3 8i 2y r1 u4 hj h6 qa xv rn rm +\n qa gm qh ql u9 ls e3 yk fa ts wr vj ac en id ud ke ye i7 fn tn f1 ks at me l8 kl hk lx rp ek l6 ek oi e6 wc u4 2h pn 9y zq qk ec cf yq oj vz tb o4 iw ox gx te +\n gt ub hn qd qf hq dh q1 lp qk by ql lq we wr sy wy lh z0 ge k9 w8 th vp pz yg ti fo tp r0 g4 yz ig sx im i1 jv qn q0 wq nu 5t pw wm id qe gg qt xg wh en uc tz pj e4 tv i0 ff qt gm dp jb qp cr gr qa nk ws os wf ne wd mm wf t1 vu wz t8 e7 t0 od hs dq df av km v5 kl we fg cx al ax yq y9 rx yh ul hc +\n we cf q4 cj bf ws ww yd tk ef ek y8 qv fk wt ko qe ep rt ik ut op mr j0 ej t3 s8 ir pt qk km ww cg wc gi lu n6 yr rc oc +\n ak ft gy rd hn a6 uq q2 q4 lr ia eg d1 eb on sj dj pn pp qv i4 hs gx ww xj m8 ko im rt fi tc uy tb pl qy pc uf kf kt mv l0 qj x7 oi um tf ap uk wl ql zb vj wv tk re y7 de q4 rc ad rm ul is fq yx r2 +\n dx gb he dl k9 z3 qk lf ad ch js o5 vq zl rj wr th r4 tu uo r8 fp ic g4 fs g6 im fr wq bg no wt dg ru ln rp wi yd qq xz ew i1 kq qt rq wg sb pj hk qu vx oi jm pa vi x5 wf ni ro ot oy di un y6 yo rh sb us tz ac f8 av ve h5 ji mj n2 ci rm yx ep rt 5f yq u9 rb hx aj +\n ih a3 pi mt do w7 zc nh qe wv rs xc qr ts ut pj im hp xa lv x3 ph tt sc od rr qh km oc rq xl vv jp ef st tw +\n ft ik a7 lp jz jx k4 hz wo bv q9 6t ur rl qx qv js dm fw wd re ea fd hu jc qu zo p3 lx pf wk vf fj 2o wx sb gs it ol yp di eo ro +\n tr ih yv h9 k5 qj qk nb wy gk q8 c6 mj a5 yi ur rl uy eq up yj r8 xs sh a0 ez oi y8 ly lp lx fu il ke zy cj sk xq 7u ey p2 uh yv qp rt y9 eg pf so ph tx tc uy e4 tn j0 gy ik vm ul mt nm mm x6 wj rp eh sb u4 ov of tc jt pt qj jy k1 s5 qs 7z do zi cx wq wb ma wm uw sr w5 o3 o5 su r1 yx fe +\n h9 gm cp z2 fb zd gk ve o7 mt bc wp bd rg w8 rk kx mv uu rb or yk eh r0 y5 ht pu tf se ar fj hp su m2 cb c9 c0 b3 ns qq qw rv gg ij y9 oa od of pg i7 hk do pm 2n sj wa vm zw vg yy om qx nj v9 f3 ee w5 w6 iw sp ep +\n da jq iz z1 ls z5 cg nt zk 1i gt w7 yi r3 xi yn pc fa ta ez in i2 qc uw si qw d5 kw il b4 fa ib 6c ud rq yl wg tr qp p4 ry sm ut s5 hi qi do j7 jn j0 qs iz p7 wg aq ex go ax ku nc h8 n3 v0 oc ah wm li zp rl h5 is eu o6 +\n gr sa a4 ik dm gp q1 wy m5 fw a2 t6 rj mx e9 et ej q0 ot wu em fa mj qe yg gh j2 te tj p5 eg tk em ao i7 di lh ce m9 wa wf ys eq l1 t3 ej el tf t9 rk u4 ay rw gg dr hj ac qg zk h6 dz ok zy kc mr fz iu hk yj oz ey ag id r2 ov +\n ds fu ps vo qf qn pf a8 ph q4 cb le cn h0 jg gy b9 rk r3 pj yd oe ht pu ig ez hu q0 qm nu ww qw ow xh b4 is a0 qq hu bb cn xh oo qo y0 fz ue e2 yr fa pj in sa hj ui sp nj zg wj ge wk xg ra ex vs oz eb pv tl iu x0 ln cq xx iq s7 wv qs zn tl wn lr yr r2 +\n az qf fi qn u5 we jq zh wh c4 sd is y5 po oq ki sz qe rm qy yv p4 ye tb ho 1u gq r3 pl td ov u4 hg ax zj wz wb vl vv se 5k eo +\n tt gi pd jk lq q6 wi gx mj ut ax av g7 qv zm lo 5y dh cw xo ve vy xg yv iv i0 qq xg jv l2 yi sc ga pv pn iu ug gy k3 cl oj tv yl di +\n qk se pd gt rz uu d6 io d7 tq gf em ym tu ib oe v3 si wa nm wf qf wg rk kz yd hl wx cy bp mx et +\n uv yb dd k9 ph q4 me o6 nr xa mu ld r5 rb g2 or fe pa fj hp db lu qn nr j2 bk kt xl rn wf qp tl uc dq i7 tx fv ar sf xm mx x1 zw yh lz mr t6 l9 s8 ah u6 x7 yw ol tq eo gc pi +\n ia ys jh wy sb i0 cp u3 ql kl kh +\n po al qg qm d2 gs q2 ap qz q4 q7 kv ah o8 rs 2o ex zx qw z5 r4 r8 y1 is ts y8 qc dm ll we wr sg lb jx wu jv qe ee qt qy es ed ym hw to tx hr s2 oh dt dy af di do qo oo qa w5 uz wh kh x1 t1 hk no r7 rp na sl ej op ev tj eb sb ya pb u5 tx ds o1 hz v6 lw jp k4 wv do wn aj bc wn yw to w4 as ey yk is ig rp o8 +\n rs ty q1 wt wy xp e3 wa yd d7 ht ts sz fk su kw xg bw cw qw oo fu od ix sd zu jn qd ci fi xh mo cp ev th ua e0 em kc lm cu u3 n8 xr yq ti yj fm yx tw +\n dx z2 ga kb yo sf sk fd gf i2 vs qw vj vw qe eu mz tu sp xs qs es t0 eb ak uh hl n1 v9 wv kd o8 rp +\n ds qn qj qz cb kz bo wi o6 z9 fq wq ml cv cb lf eq r6 r8 ic y4 am sz sx po jp g8 ze we wu en ew qw 3q lz kw tt ty ti e1 fx ut tc uu s6 ow gm sh qp vn l4 uj op xn wh qk wz rc wh uv um ar e7 uf az uh py h5 lq vt nz lu li lm dd rl er rt yu o4 eu yz if +\n iz ld me z1 y2 dj ar qb b4 l1 mz ij ry to ad xs sd wf eo hj wl ex ie u5 pr zj gt oi wc kg my ex zt ks yg eu aj +\n gr iy ft pq um qj dz wt gj cn ru kx q8 ws ue rk eb ee fo jb jf la ji ke qq qi qw rq yb qp il eb y0 iv ff zp l3 xm fi x4 r5 xd r0 ol wc t8 ae iw ox fk of pb qj ku xc ct wc ie xn zi wm rz w2 tb u0 su pi +\n a3 ss je un zf vq zg wo mx d7 pm gd vn eu yk tq ik fu ai qt qf j0 to yy at ii qk wz lw n7 ly +\n ub dz rv qt rm wg ea pc j9 qa mr h8 +\n a4 wp td ur px qq ki yx go wc tm an +\n po gn rf a5 uw qn q1 nn we is z8 wj ca t5 ij eb tz ef pr ix g3 ek ta a0 y6 sq pa wq cx kq qw we rt c0 mz pv py wi cw mj qt qu 0e oa tj ux pf to hr ao tx yr ts fd fv s5 ui qu j7 gw ug ss cy ks qf xm fk wg vp kt mv qj mn lk vh yt ol rf th os e8 tj ua rk on pq dg kv km wq kp ad bp os bw pb qh wp zs q6 u0 gj yu o5 if a1 +\n a6 he pu vd cd q4 jz z6 qc jc bz eh wi b1 ed ym eg fo us ib td y8 gj zm pk lc qr wu mh qw sw fi ue j0 xm kz y2 ev aj df h3 qk qc tx rr rl rc ut ad so ro tw +\n a2 pa we kk eg q7 lh zj wp 4z gi yd yg rc io ix r9 jb xe rr iz jd ij tz p9 qi l4 pa g9 s4 vi tj pb hd f4 qh qk lq qs hn ro +\n gn k9 qz aw wu ki yf e2 pk v8 xk wg 5y t3 sl u4 ya gd hn ql zr oj ig +\n fr qn qh ph k0 q2 nq wi zz rh rx ee ef uo d7 ix el fh qv dm vg px wi m8 qq gh ud qy ec fu yw uw sa tb lg us sk wf 5h qf sh vp wk qk zw qz wg aq of ys ak al f5 re f8 pr ku qx wc u1 lr qs wb f4 cw k2 ka hk mf yr w3 ro ir +\n gr qh ql wh kv e4 r4 oy lu qw pb et uj tb tn xs kr dt td t8 e8 uc xn eq yi af +\n q5 dt ed y1 am qv ut gx m7 yt rr yq yr dy sh mt wd wm th bv ym +\n tr qs ca lp uv q3 wu o5 c1 rx om ee er ta ou i1 jb rt ry os ti fc ss px jn gy jz vp ea tg ay rq u6 al de qc zt wn ez rz eq aa rm ox +\n uv ds h9 fy rf jq he qh h8 d4 wr wf du ck wi km yp ut rv io g1 rb av y4 tw a0 hy sz qx gh ha q9 qw ze 1a bz bx bv qw po ee wa qi xk ri i6 ic he tm hl sj jb qp wp jk qr kf sm l8 be x3 qu ql t1 x6 yy fg rj ua ug qg kv k1 wl v7 xx bj ae wc n3 zy tl tz zk wq re n0 yw oh yr oz eu fm do ux uc +\n hb pa h0 pg q3 mw q6 mg ls lh am sc gz al j2 wt t9 lm qe j2 rm re rr ry fl yw ux i0 2e eo bt vh ra ys sm pb on tx re ff wn wv tu rt ox ul ge +\n al fw zb p6 hi qy ay ou rg sx ag rz uy +\n bx wi kv t5 3w e7 sh ht ff nu la xo qi s3 uy jb 1o vm vi l6 be x3 ny pk aw u1 rk fx km qc be rw yn ey eo ro +\n dn q3 jf w0 e0 lh rv zv js j2 xg ld hr qe mk s3 dr kw kc dh h2 ql cg zv n3 ym yt aa as +\n ft ty qh pi d3 qz ip wu wi q8 wj a1 mg mj ut wt r3 om ua y3 ou fd dc zw lp xe cn dh ng qe kp qt mz xy ef ay od tz p8 i0 hu hz qo kw jw qf kf 3y v3 qj w0 ib ew t4 fg oc e9 ua ov hs u6 f9 h6 vj qv li wq iu yv xv rc w6 rm r2 +\n d2 d4 av jc si rs ut 5q pa mm s4 e5 tc km +\n qa uk uw qh vd d3 q4 xo wo c3 wl wa w7 w9 mc r4 y2 fp r0 tw fr g8 ae qn lp sd bk en vr gd hu j1 xv xg rw ep wh ed fu ul eb fl fz i7 ht jx ns v3 ll zs j0 op xf qf l6 l7 sn wk zw wg ej ti wb wz t6 oz rh rj uf je av dj h6 ql wl oi im v8 zr qv wn ku wb bj ef o4 yl r1 ei so if uc +\n k7 qg q5 kx oz mu wl ws rh b2 rk yh qn qe 6o 1y mj ei pf ye e1 dw hj hx do qo gc rh v2 zw x5 t1 t3 yu th e9 em au qh f0 qk km ql kp wc 5p vx bg ea ev wn wm w2 rx o3 yk ru +\n a2 gr qa az dd gm d1 k9 hr we bz lg mg ny wp xd mp yo pj uy xs ua pt g4 tw ez jv q9 qn wr nd md nf qq ng pi bb j2 eu yl ij ty sb os eh hw i6 hg m9 nj wa qs w5 qf nz zh hw wh be zo fs rz me yk y3 ub t7 t8 u2 u3 en ha fl yd hf qh qk wc 1x ze w1 oj ee w3 ey du uz id ah pi +\n o0 hn qz q5 du 2b bn a4 ex rj y1 dj yz y5 ig tf th js qv 5e gc j3 ls d8 yw bc cz tx mb wf ij ty ai as hi lh l3 qd n1 7o wf wh qh wg ot ra l6 el e5 s8 dg vm 3f 7o wn yw gj tb et +\n fu a5 cp ch hx hc rd eh tg g4 li sw sf il eg eb zj 2o cg ew uc +\n qs uc rp ml eb yd if pa c7 oq vk wu ot yq rl uz tv gb zu vm w0 sc tf ud qk wm ko yy er tw +\n ak tt ub pa pq il jq q1 hr k0 uv ql q3 kk zs q5 z8 is lh q8 w7 qw es ii av yz dl ht td g6 vs jm zr px bj no g2 g7 la c7 xt mz yx tt ym os to s1 ur ta s3 gv pl qy pc qi sh jv j8 gr l3 bi oa wd fy v1 s1 zp hg 5e t1 rp wj ms wl t5 el wm at fl e0 sq h3 dl qz ka ox tj qb wb wq re xr rx em ee yu ri do uc a1 rp +\n uv rs un qs um il ul q2 jy kl wo a1 rj tj pk ys r5 yn uo oe y4 ou y5 ar zb g0 qn gx zt lb 2v rm qy nw yz lm eg og i7 ht ss qy qi ge wf bw lv lb wh cs wk hf 7g yb zw hk ns ol rh th yo f4 rq dt uj qo fd wx nk rv ka fl mu rr q3 w2 oj ee rt w6 ru ul +\n qs hq qf qn d1 k0 q2 kk o5 na si bv mx e9 tz d8 tq dl ez qv jf zw ww wu xo b8 w3 i2 te p3 ry iz s1 ut as s5 hk wo wa l6 wh bq xk wj wd ra gu yi u1 t0 ak ai tc ax ip uj nf zb wv bd wo fz qm qj pe md ew rv gj ol yk tn iq yl is si ie r2 +\n d3 ni wr ws li mj ds sh sl qx vs rp ft ik e1 sd af ho xn wg zh 6b rp eb f3 u5 uf df py k1 wz vk vx k2 dg wm er rv rb +\n gv iz qz wo o7 k0 oq ti r9 us ib ps g0 jm jb tq ue iv pj sa cr kh t1 ot wc at e9 ys o2 ab qj ww za rn yi +\n ty qn qh nt ql la q3 kl wt q5 mp mg o9 ls lh g2 id ez sw hu qb cx nu pl kw wt vz v2 1t wi mh qr eu rm qs xb ei ij uj yb sn ai iv pj oj de hy gv ka lz pa nx wg wj kj cw zp wk eq wj t5 ns rf e6 rh ev t9 eb ir e0 sm gs gd ds f5 dd de fc f8 x0 lm qz wz xc wc kx cu wv ks lv kv wn pv ei wm ju ww yv zy yt e2 rb w6 oc o6 tq ig +\n q2 o2 gj q6 zh mg li mo vo ch tl ax ip ho wt ln ro wo qr tr tt os fo e1 de hg gb sk w5 fp kg mm l6 yi u3 fl hs u6 fx re rr dl wb jr el rw pm rt to rx w4 gx +\n yv a3 qa uz k9 q2 o2 bp ny zl mj vo tk rx ui g5 pu qx nr xt ls lm rv qs yv ik fz tv wp nk gn qh qi yf ek e5 pb au tc ac kc br qz 4t qc mx ly wm kb ez w2 u8 ei o8 +\n rf vo q1 o2 wt q5 oc 5l a2 es oe sc cx wq qw ky em tx rm p2 qo ft ed uq fs i9 ok lz v3 au xj v4 wf l3 eg ej ex wl rv qv ak mi hm cj yr w4 si +\n a2 tr qa fy qd qh oh kk lq dy bz oc jf wa k0 ip pm po qx wq cx we wr bj j5 yq qe gg rq rr oo ru od ix qt af or sj qo jn gr sk wd nc xo xl wk hh yf eh ek aq ex ar en tl ys rq pm ug ql qz wb wn yw og xw an if it +\n ak kk wu ig df w0 rb y4 fr gg i2 qb qw yf j1 ij ue s2 qt ad i5 yp ai l9 wk km ql zn yb ee rb ir te +\n hb q2 ld wt q7 qm km ws w7 vi iu yf rc g1 pr ot a9 pn dk ib qx hi qc jd jg hd q0 lo jj cn wb mz ec qp uj y9 tu yq au tp hg pl jx vx j7 wd 3y ca au rq kv qg dh k2 ok cf qa wv bp dw iu de k2 rt hj wm rc er o3 ey fn si if so +\n hq q1 qj d3 ws as ld mu rj ut d8 ey ou ib ez gf y7 qx qn vz qm vd zw ww d8 xu v1 av b6 mg gs bb g8 rm qy yv rr ry oa tb dt jb qa j0 qs l5 nz qg wj t4 td t6 eb ua s0 pn ii ac x9 qj k4 wc v9 s7 cj zy wo 10 hn yq vz u0 fm uz ux +\n ra pp qd d2 vg wj qn rh we ht st jm bv wu wi qy y9 de gw wa sb uz r1 qu pz ot td rg go e8 sn iy zr wc s0 ww ea pw ac w1 h4 w6 rp +\n fr uv pa jt qk q4 ls wu wi mt xa vu tk ed rb pe fp am sr hp qv m1 gc en yw qq qt ud ey eo p3 tj tu en ix ux ye tp ic s3 ad hz qi uf qa kr wh vd lk yn 5t u1 t0 od rr x9 f0 zj kn nk wp zs se rv ei pi +\n yb dc qs py qk nb jj ql q5 m3 mg zz e5 i1 zr lc zx xu vq hr xp by ei yx gl qi qp ij eg ai ph ap tn dy zp qp bp kf j5 ib vd eg el yy td yo ie ag em fc kx zx h8 wv sv q1 te wv vm yq ol if a1 +\n ak rd rf qg lo nq xy z6 q6 mw c1 cu z8 q7 vw wp a2 zz w8 yo uu ee yn r8 av yz y6 pp uq dv i3 db jv q9 2l xg rp ib lj sq tx tc mj mk qr rw te p3 ik eg pj e3 i9 im tb tn fm na j7 lj wa ct rg v4 he x3 kl bi r7 wj y1 l6 wk el 9f t6 gu tj od e9 tz re uh o2 zk ki cf lw jp sc s6 qs qb yn yw ms md w3 rv as yi ox du yz ir yc dp hc +\n yv gy ik k5 db gm ux qj gc w8 ea g6 dx po jb 5t pv wi rz qp jv v1 ea en al ii dt qj py w4 if ux +\n iy pd yg qq p4 in qa y1 yy ta fb zk s6 lu +\n ql ws rv yj jk ke lm ff lb fx s4 av uv wl n1 rv dp +\n qh d3 rs ih rc aq we 7y ud t3 h2 zt cu oc +\n fr hn k6 je q3 k4 tm zh lj aj li a4 t7 w7 kx ut pl rc ih th hp wq pl ls ma oe lf wu l1 ve lp qt qy fi ti he oh hi ow tm cu p7 nr va r3 tt wk wc s8 s0 hs al o2 hk x0 qj lm v5 wl qz 7u iw os lu ah wm hk e1 o4 rm fq ro so +\n gr sa rd um pf ca ga ql qz wt ld z6 vw kv my xt cn wr eq tk rw fe qx qc qr qr rk qa qi ex p3 p5 dq ff pc sh cy oq v4 wg s7 yo ya od rq dt un bw zm da bg q5 ru ah +\n iy qd k6 dm oj qz zd vr w0 r7 d8 et y1 eg yj gz qq p3 il i8 ge wp sx s1 wj t4 lm jo qp pw xc vm sr uz ig +\n qf u8 iq rg rk g4 im ih oq fp a0 ib tc uj tn nc kz ll u1 un qv ck lv vv +\n a4 df um jg z2 lq wr tn xu id wo ez rk rz ew d5 ti ix to r0 sk fa fe fr hp jk wr v1 ms wu jm rc qt tr ex uk vr to tz ut hl sg hb qd xn rj jc 6x mo wz rp ek y4 oi oo ae sc e9 od pn hg wz js qv ln ju rx yg as rn gk o7 so it +\n dd qs qd py k9 lw wt db gk zf nw wh t2 nf zx w8 rj ue w0 tl ew r6 ui ef g1 or ej pn an tq ou ff qv gj jv q0 kq 2l uo oe ku wi w1 tx qe rv 1l ws eu lv p4 ru fo tz ph ib fv uu i3 qu oe pc gw wp sx zd kw w6 bo w9 cs cw my qz zf rg fh e8 ay yd fz rw fc ng qz cg wx qp oz qv ly ha cx al iu rt mp e1 ee w4 tn ul ru o6 ag aj +\n qa kv e5 bm yj j4 m5 rj qe ri ht oi qf qe t6 e5 aw t8 wc dw un yb +\n iy jg jj d4 ju ol wy bs wk wq t8 a9 y4 ta dx jp qc q9 su si ut q0 m8 qq 4a zy qq zq sw po qe qt la sn p6 ht oj hy hh qi gc bn w7 au ya kz na oa ox ov je fb or wl qx ze cg we fk tz tv cg uq w6 +\n dx sa qa qs db go lo z3 lf ox jc wj 93 tj tk yf ii ef fo ua sk g5 fs el oi fr sx fg se q9 xq qw j3 m6 4h qq l2 eu rq qu qi hs uh p6 ix fx qa i0 wf ke bq ne wh xl ms un ex sx yi ua pb s0 rq ak ao fc pr qj cw wq vy wv u2 3h wq re yw eb gl eu +\n hv gv il jd go qh d3 we q4 q5 ej lk my gv a2 ds ex e7 rk yf fq pu ff qx ho js gx j1 qe kw gm ja ns wy ln d0 cz xt te xu tt sb em ix ic p0 i8 im ui di gt ws os r1 qy pz l6 e5 e6 op sb pv sn ii rr v6 ql le zy pv mt da yq ol w6 yz ag it +\n ds gy dg jf qg uw qj uv q5 q8 q8 q0 qm e5 rk yd tz pv if qn ju cv xy ki qw mj ls yv ru of tz so yr oq qi m9 sc kw qf zh jx wh kg l0 t1 pz un fj os ha sn f3 e0 om ab cw ct nj zy wn fl ww vn fn tn ie ov +\n co qh jr jj cb bi wt q6 ra qm zx ur r5 an fw tg jm re j5 vl em sl xz qe wa 45 nq ex yb ed ef ph e4 tb s6 qy lz cu gm pd gq mc ca 85 yf wf hu sb eb fk fv dt cq lq qz ww wv xr n0 eq ok er et iw r2 o7 fe it +\n ra dx og wd wt o9 i4 it pk qo ic dt hj jl oq sf lz wd ca hi fg f5 ap x9 gq nd iy q6 ep +\n o9 gb a5 z5 q6 wu w0 tl r9 dj if ts ig it zq ll qw qy ep ed ry p5 ut hh dr i0 hl qp qa zs wd ya ot xk s7 e9 om io dl ki k2 wv q1 5g er rb rm +\n qs w0 om ed tk ta th gf ii av og 6o ee o8 +\n po ty rf qf he qc hz bv c5 mi rh ew tu ef sh ix r0 d0 pb tq fw ig g8 fh i2 uw hf qw qr sf cn wi fh qt hp nq yv fy tj od ux ut fb hu tn qt oi qs oa xm dm fa nm qx yy oo ec ev ox sb ya rk ys ud jy dz zv qc zb qb 17 tb lt yt u9 w4 rb st et ry yl o5 di ux +\n gb gt az uk gm qh d3 bt qz wd ld o3 bl cm q7 ck k7 we b2 yd ua ew tl rq yg us tq js fk jb gz jn jg qq in qr rq qy 3h c0 qp p3 yn ef sb ym jl sf sh hv qd p4 fj od ix kz ni wj wz tg t0 tj e0 sm om kx ku cw nb zc aw cy qv bq kg wq pn zz wv cd wn yr se o6 pu eo gc +\n gy rf qf k6 qh qj cd q3 kk cj fw b4 fr mj w7 bm wr ya z7 wt w0 r8 ip ti is pn am y5 qb hs jf qw uu wr np qt wi 1t bx qq qw aw er cv qy rw eo oa iz fp iv qi jm nk kr qf xm eo nr w0 qj bi t3 uv wk ek wn ex e5 rf rh ga it f5 pm hm f8 qj gy jp le wc qc lt s9 zu lb q1 ju w1 uw w3 oj tn tq ir r2 te +\n ak gn pw a5 qh k9 qk nb 2l qz wr kv mt gt w7 zx ii oe ug ix sz qx qc ar sr zb su vg qe np yg qt yj sv uk pd uq pf of eh jb sk gy ws ke kd be og kh x6 me wz e6 yo iw ah rw pm rr qg pt lm ql qz wz qs ly wb wn q3 ry rx gj ia o5 ge +\n gy qm d3 q3 ia c1 ta ex e5 e8 eg sy cl jf qe nj nh m9 qa w6 ek iw kv qg ab n4 w5 iq do +\n uv gv qa un az jd qm eg iw nr q8 zj ny c5 vu rl rx yn et ia ua is ot pt hu im gj qv vv xe xu 1g wo vt qt st qy rw qi wh ft es uk hw to p8 fn f1 hp qu sk p2 l4 zf qf g0 fi l7 be ky iv mn xp nn dt 6b ro kw uv ra tp e6 sv s8 sn tl fz iy qh hz ve v8 h8 th wc wy qb xm s9 hs wq zs yq tu en zt w4 dp yc +\n sa ak gi hw qm gp pp qz fm id lh 6w 9h xr w7 ui ow rb oe ia us fq g5 y5 ig oi y6 im gk ze qe gn 3o ye xz jh qe db qi p1 ep re op te y9 os pj e3 p0 zp qa ih l4 cu zg wg sn rh lf fz ic kh ni wh vh wx th ag u3 f6 uj jy k3 2a wc kv lu wo hb eq w1 rb xw yo ei o7 gx +\n hw wd r0 g4 sz b7 pi sn tc in qt zs rg eu +\n iy hv hb hq qf z3 q2 xy ia tm zf jw wq a3 rk w0 d6 eg et is id po tg gh ob jj wr np no wt ja wy xl l2 yr bt bb tc cx qr rn qt lc rw sy ex y0 ru od to tz og ye hr pj de tv e4 qt ad oo qa jq fj l7 fo wh nt pl ro wl vp yy tf va e6 fg th ar s7 os at s8 re df pe hj f0 qx qc x7 lu nc zo tx bf ww pq cg w1 rx id pu it fe +\n qf fi ld 4o ge da t5 zz mo zx vi ui w9 pj rl rz r4 uy r5 sf av ot fq tw sc zv g9 qv i4 ut iy m1 wy xo b0 ud cb qy rq ug wg sn fo ix uc aa i9 ss sd di sh j8 qp xa ep w0 7h wl t7 iw tj ya hs e0 fz hd u6 hh dr dh uk qj qk wx ol xb qv wb s8 15 wy zm jr nx it eo fx ww yv zy to ee yu yi iq ey iw rm uz yz ob +\n po ra ik qd qf je jr lp wr ji ne wu 2b nt wa e7 rx xo ia yl ta ig ff hp gk jf q9 vd si gc qe rk wu by yg rq sb os fu eh em ux ic ao pj hy im du qy cr 2e l5 qw v1 lf mv wk rx dy rp ra rg gi eb hs au ap bo oa sn zi f6 h1 zt ey yz do +\n lj vu y2 if qr wr ta so kg 3k ol u1 f5 +\n yb cv mq lf zz ue ui dx qe tv qu ex tz hh tb dy ds wi rb +\n hb gt qa h9 rf qf qg k9 q1 lo q3 ql z8 gl zg q8 1t wo vr rg ez ws mo w9 yo r3 yd e9 ea sf a0 im tg y8 ar qb ni wr qr wv m4 ix d9 nz yq fa if yr bt qr mz qi ea rr xx at ic pk qi za hv kq w7 co xj wd x4 zs wh y3 rf ec u2 e9 ah s0 uh io un h8 iq zb bs nr be zo fz vb wm pr yw md rc ur er ia yl ox ei ux eo tw o8 +\n qs rd rh yf px ow d8 tq ig ih cl qr yw qq in qy wc ek rh ya qg cd x9 qm lq to o3 ul a1 +\n a2 cp as gk kc 4u zj z2 t5 zz rb eh sh sx fg fh g9 hp vd gx oq cv pe wv b8 qe cc nw tr il tl e3 qu l4 mt wk wh aq td e9 gf lm qz bu jq my wp vb dg y0 ye yq w6 r1 +\n ij az qn ph qv bv bf mz iu is y8 ar fh q9 hd qq ji sf ld up qo p2 at sp in qi nk l5 e0 rw px 5o ew oc te +\n qd jr pa q5 w9 hw hu y8 dn qn zw wr ma ei xl dq i7 i9 vb sx wf wh na wl um e7 s0 h2 nh nk fj yl wn iu u7 as ad ey so uc +\n la up ic g5 ay ic x8 u2 ar eb wb yr aj +\n po da rd un qg uw lq m2 4r wg q8 z9 t3 zc d9 ae st q0 li qw wt kr qu ry en sm qf kf kh ny yt gi rh u5 em tc kv h8 qx lr jq ef +\n a2 dh qh q1 h8 qz z6 kx z8 bv 3q df pk tl d8 tq tf g8 zb qw 5p zm qe cv yb ec uz iv e2 gq wp uh kq ws lc wk x3 t8 rj fc io je dk lr lt wv wt bw be eo q4 ye yy rv ok yo yp ir ig +\n rs ij ty ps ul wr bh kb rs z4 z8 er px uo up y1 rb fo jo gg dv ph q0 jn xw ww d8 rp yd yf tx b0 op yn of jl tm px fm jc zf qd pk wh rp uv tp t9 ir yf ug qg v5 ku qz fd k4 cu mw zn iu bg lq ly rv su +\n ik dm cm or tw pu lp eh qd kk j0 em ng tw +\n ra ds qk cg q7 k6 4p t6 yu lq go yd eq r8 fw am dm xy cm v1 cz eo qi ij yn eg hq tc sj qa i0 oa l6 p6 wj vd wf mr yt ex e6 yo t9 ev s8 en rr bq kg hb lm re bj ms w1 et du +\n o9 gy bl wz t8 hq iu ix av y5 y8 jn j1 np xt t9 vw qq 43 xv 9w yi ft es hy op lg vs hg wd ef wx ou ox sw dr ze xr st fm ah +\n a3 wr fb jc c2 w8 rx fe q9 hd xq qq wi te y9 e1 qt qi qs nl ca bh u2 md tv hx +\n ra jh q3 aa t3 1o eq lh rv fo us pt dj pm pi qn zr bj xj cm ix a0 ra hi eu nw yc p3 ru ri ue e2 jl hi wo g9 xn qh wl wx go yp rr dj nd ch u3 fj bd jy vn w1 ia ox tm uz +\n ma y5 bl qi g7 ri fl ap 7a yo ko rp +\n um dh pg wq r5 sf ia ta an hs ne q9 wt sh rk yi ym of tb oq do hv wj ic oi sc pe sc wq wb wm tq +\n hq qm gg q4 xu k4 k7 uo wt kb et fo ey aw g0 xi am in qy eo qi eb ay ue og nt kl wx s9 df qg f9 v6 rv sv pc tl my bj wb eq h4 o3 ri +\n tt uq qh nb qz wt jx ya on om io ow ha qp e2 fd e4 hp hx p2 vm xg xn ra l8 iu yf jr qh k4 1l oa tk zp yw rz sy ul yx eo ep +\n ij yb qs fi ul qk by ql jl wr bi q5 bl tm q7 xp k7 vy gi tj rl rx yf ym tu er r8 pe ip ej y4 fd jn gx zt vj xt xh rj kt cm ri nh zq pp eu rw to pg e1 ue dw e2 so tb gm qi jb nk gy pa v1 xj fl kh 3k kl ed wx wc ek yy ez wc iq yo u4 it tz ak hn f8 h2 hl uv wz h8 gi nk ch zt wt bw kn yq e1 tv zp ag it +\n qs rf jq go qh a8 jj xt le wu qq yd d6 d0 ff qc su c7 lc wp ty y0 tu ti pf ta aa ug vb rf vi rx no un yu e5 7r up rj ag ha hs fc wz bo qv bp tv ki er +\n yb qa rd lo ok q6 o6 ba r6 ow or yl am aq gd dc ho cx c0 wu g4 ib c5 ep re qo ed yw iv ta hy jc pn xs oq xn bo zg ps kr iz yp wh wj xl xo zq me na ek wl wx wc rg uo ir tk aj da rw hm io uj fb jt qj dk nh zx jp qx wc zr zy zu nc xe ww wv vn h2 q6 en ew ad yl af eo if r2 +\n yb o0 dn z1 q1 sw qk po xt wr ls z8 ox wu jd ro q8 lh mh wa rg ea c3 pz tu g2 is a9 pn tw po qc sa jj vh ax xh kt wy jv mg nh kp b9 qi od ht e4 uu ij qf sf nc wk ap wd qz rd yi s7 tk pb it f7 o2 f9 kv qh h4 ln wz gi qd zn xm sn 39 yn rz u7 yr yj is ie ag ir tw +\n po dx uv pq jd dm d2 hr cs gs d3 q4 wr np ab di mh vt w7 w0 on tl ia ta aq dz y7 i1 qc pg q0 wq j2 c7 la cb il wr lv na ru 4g vz nf bc sl qq qp qt ud rq wg ex uw he tz ye p9 ui ou vu at ix w0 vf bi ed yh wh ra y6 wc u1 t8 fj ov iy tz kx h1 hj jy qj h6 ng jo wz cj ie mt rq te n9 mp ma q5 8w rb o7 sp ob +\n po ra dg ca qj q2 is kn rd ws lq tu ym yl y5 tg pp qw we cn a7 1t jd m7 wo yr sz qa hp ei qy ec p4 hw p7 to au iv ht qt qy qo l4 lz xm wd yf wg ez s7 en f3 tx yf rr f8 cw ji qv yz ry ew w2 oj w4 w5 st rn oz ri o6 dp aj +\n gm jg ju q5 np lf q7 xo 1y qn k0 jo pp qx th q9 4f or ro pu bv eu nw uq ao dy jb j9 gr rd nz wj wj r9 co ta rk od dd gg hm df pr km ng oj qc sb qd wb tz cq ex wb vb ty eq tv iw +\n fu uq co qk jl cg ld lg wo vr gc bd rj r3 yd rz iu ew d6 io to sh y7 jp db dn qn qm si xg qr ls jo lr wy rk wn m7 qu bb es op qp ru en ta e3 in hy dy hl vc gc gt jw ke 2t wh rk lj hg oy e6 yo ev em fz rw pq re dg qk ku oi qz k4 qv li rq n8 ec 4d yb wb e1 iw id o6 ir do ux pi ep +\n a2 wu jd ef dc mn 5e qp pl xd ag ay +\n yv o9 al a5 uq qg jw pi z2 jt cd q5 3m zl ez vu rg jl rz yf ix sj fp d0 tq ff ha hs zw om ni m0 xg c8 a7 ki qw cc ei xg j3 tt tu il p6 ix tp tx ib sp hg p0 fc pj su qu jv sj lk qp ws qs gm 1x mx lv wj qu l1 dt wh wv un aq fg rg e6 uo ar ie up it sw tx f6 o2 h3 qc qa ho vj u3 kd zy n6 my ww vc lr em w2 se rt o4 yc a1 te +\n qs dv pa ty iz uw qh jj z3 tn jc eg e4 qq w7 ut r3 uu kb up g1 fo iv if fd gd sc qm qe xg ia wb he ky hu tv rw qu rr es p3 ue s2 as i0 dt qt hz jm j0 gy ci fi hw nv ea kk vf rx 68 ti rp wl oi vp at om io uk pt qh qj dl cf lr cx wq ku ki w2 yh af ul sp yc it +\n ub yb dc ty gm dm go nv we ql by la o1 ju o3 jx fm aj wa rg e4 vi a6 r4 xo tz oe ip pv dk tq a0 tf fg tg i4 pz sd ry ky mg hy g7 eu qy yi rw qp eg yw hw sm uc i7 dw fx s3 sf zo m9 xs vn rf ci nz kr qt 9y pj lk ee pz ef rk e0 fx uf az fc qg jr oy lq cg qp um ad wc zn bw n6 my xr mp tu en o3 iq ir ro +\n da a3 d1 jr dz ca ql nu q3 cf o6 nr mt lk yr rs lp w7 a5 pj ys ym r8 ey to fs dz im ih sw qx qv zn gl j1 xe lc zc vw 6a mh b9 qt rm re oo qp p4 tk ix p7 og tz yr sp aa hk ih lx qd mx 4n kk vf el oo td ae yo fj uf pr hl qj qk wr qc qv kf yz my wq hn zs dr ee u8 rv et ru ie ag tw +\n gt ph z0 zl mu ui av zm om ui vh qr he qr es fl ws w6 nc ra rk kp ol wm yu it +\n dd df jq jd ux ql el 3r ya uu iu ee eh g3 sj us ib pp qc jv hd bh zt uo d8 b3 xu bc rq te uh ex tt eb il qu pc ge sj qp ih xf 3r gr yh qx tu wl wn sz up ay it ab jt qz v7 wn li za 6o w3 fn yk eu ie gz ro +\n yv o9 qf eg eh mh jh rh r3 rv ix y3 a0 sr qc qq qr wr qe bx ki m8 mk qi lm uk eb ai ur e2 xd nc ca eo mb ed uv rs up ya of hn lw wz qz et qh wm zr rc o3 r2 +\n ss qg qj ph qk q2 cs z4 bi qc cj q8 qn w7 rj ys ea r4 uy om rc ii fp sj ej yz el qx qv zn gk q9 hs m2 ii d7 nk c8 j4 qq dl gg pp ei qo yc od fo eh fp ta hy ok tv uu us dp qf sb zg ks sg n3 wh x2 nr cs wk kh wk wf ew 7h 7k oy t6 gi rg yp s9 ya e9 pb tc dt dh hk h2 pt qh h7 wz n1 qv kd pm cc xr kp yk tm ge +\n gr qa ft tt gn qs pw pu ca ph ls cg cn zf bz q7 z0 c3 qn gv w7 rg ut e8 ii er ip sg y3 oy ek ht gd qx g0 qv db su jn qq lz uu jo ru an wi kn sq nh qr qy yx eo qi xz y9 ru pd au p7 dq he ut ok fd jz ui hc j9 l3 hb xd jq gy kh wf xs sl rs aq ez y4 ts um yi e0 gh dk py v5 qk ql ko jq wc nk v0 wb qv br iu wm 6p sr gk yp pu +\n o0 pa pf z3 jt jy z7 cm ne w8 yz fd fg zn qq ll vg wr wb ia xx yj ty eh e1 so ts tc s4 i0 tn wo wp wa op va wk x3 vg qx rs sn au f3 tz sq hn rr o2 fv un k2 vj ey dj +\n iy ra ij ty a4 un rf qg dm jr kj uv we cv gk wy z8 oc wp mo jl mz ev ch rv tu ax y2 g3 oy y6 im uq qv hp qb hd iy lp nk w2 bb ho ep tr os en sm p8 p9 hy ss ui gm qi oo vn ae qd w6 ps dn wd wg ro mr yt ol oz rg s7 u5 tl yd rr ax f0 cq ku qx ze n4 wn kt ca jy bg yc zs yw rz w1 eu rm r1 +\n hv fu ca q8 mt la r3 pl yh to sy yh tv x4 tg yp ov wn ze sp +\n o9 qa az gm qd pw hq pd ga qj cd q3 jk pd du c2 zk xf t8 eq om es rc ua y3 pu ig qx se qv db st qn ii lx qe wt xk nx ku br qe qr qt rm eu xf xb rn qu qi ep qo rr ex xk p5 ym fi uq to ux ix ai hj gn zi oq qf kd wf xn kr w8 rl kk mq rp rf u1 s7 oa fh e7 yp e0 pr ql sx ck ag kg kt mp eb rl em ee w6 du rm yz if ep +\n qs pi am 6a ut r4 ii sd ua ib y6 pa kt pb wm qq dz qt qp y0 he p8 ue tb qu or qo wh 40 8j t4 sl rf iu gh hh qc iq bf rl wm mf oh ew is dp +\n da ps a7 jr z4 q3 bu xt ip jx q6 np z7 bp lg bz ye wo ig bb ww rf om uu ef r8 ey pt ta pn y7 gg th dn pg qb ri qq 42 qw zw b9 b0 xb qt qy yl wh xk ft at yw i7 sp de pz fn qy si m0 ik wf sg cq ql hk er eg lc ek na wc iw ir rk ua e0 ak iu sw ap uj av ab hl uv zc qa wc jw vj qv vk ay kg xw on rw 1b wn rl eb vm eq h4 yt oz eu uz +\n a2 qa rd cp qh ub vg ws u0 4g bp da yo ev kz eq uu ee ef yk pr sj sk fe oi lt uy j2 gn io vk ns 27 ln wu ve yr l2 qu qi ry il ul tj eg ux i5 yr tx ph oj gq or zp wa qs gy iz v0 qt wj ic ca lh yb np ej sl td l8 yi iw s8 e8 ys yd sq al dt pt tg te yb eu tq r1 ir fe +\n tr h9 go qj b1 wu q7 zh el tg mb ys ed ii er r8 xs pe r0 sw db ov m7 d3 re no nu zr pq ji wr lc or qw ee yy qr rn rm re qi te ea qo yb yn y0 uz uq iz tl yr i0 fm wp qs qd he wk kl ew as hl ez oo ox ie s0 f4 dl wq wl ww lr qc qv vk mt my kn ep em yt sy am so rp sp +\n ak ft qg bg ji q6 bk xi tf mo ur pj yk ua qv wq gc qe ke ef eb tk uq i6 oh iv gb qs rx el yo rr pe wz wx ho xq tc mo yk du r1 tq oc hc te +\n ra ub qj jh jt dx ql q6 da tf r3 ew iu sg tp yl el gc 6n tt ry pd ye ff lz kt yp fl yf dl rn +\n o9 hb h9 qd dh qg q1 qj jy se q5 wt nr qv ge c5 el 6y uo rv ax pe et r0 fe y6 dx qx ha qq lo we zy v1 wy dl vr wa qr rm qi qp yn tz pg ph de p0 do qp wp wf bw xh ky xz wh hl to ek rd sv rj rq re h1 qg qh kl f1 zm 18 ez xe vm en 5j o3 rn fw fe it +\n db c2 bb o0 w8 kl kc y4 qx zm pk cw id ve mh lp rq jb fl x1 qi wd lx f3 cy bq dd ye fn ig diff --git a/contrib/tsearch2/dict.c b/contrib/tsearch2/dict.c new file mode 100644 index 0000000..9ceb78f --- /dev/null +++ b/contrib/tsearch2/dict.c @@ -0,0 +1,303 @@ +/* + * interface functions to dictionary + * Teodor Sigaev + */ +#include +#include +#include +#include + +#include "postgres.h" +#include "fmgr.h" +#include "utils/array.h" +#include "catalog/pg_type.h" +#include "executor/spi.h" + +#include "dict.h" +#include "common.h" +#include "snmap.h" + +/*********top interface**********/ + +static void *plan_getdict = NULL; + +void +init_dict(Oid id, DictInfo * dict) +{ + Oid arg[1] = {OIDOID}; + bool isnull; + Datum pars[1] = {ObjectIdGetDatum(id)}; + int stat; + + memset(dict, 0, sizeof(DictInfo)); + SPI_connect(); + if (!plan_getdict) + { + plan_getdict = SPI_saveplan(SPI_prepare("select dict_init, dict_initoption, dict_lexize from pg_ts_dict where oid = $1", 1, arg)); + if (!plan_getdict) + ts_error(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_getdict, pars, " ", 1); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + { + Datum opt; + Oid oid = InvalidOid; + + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + if (!(isnull || oid == InvalidOid)) + { + opt = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &isnull); + dict->dictionary = (void *) DatumGetPointer(OidFunctionCall1(oid, opt)); + } + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, &isnull)); + if (isnull || oid == InvalidOid) + ts_error(ERROR, "Null dict_lexize for dictonary %d", id); + fmgr_info_cxt(oid, &(dict->lexize_info), TopMemoryContext); + dict->dict_id = id; + } + else + ts_error(ERROR, "No dictionary with id %d", id); + SPI_finish(); +} + +typedef struct +{ + DictInfo *last_dict; + int len; + int reallen; + DictInfo *list; + SNMap name2id_map; +} DictList; + +static DictList DList = {NULL, 0, 0, NULL, {0, 0, NULL}}; + +void +reset_dict(void) +{ + freeSNMap(&(DList.name2id_map)); + /* XXX need to free DList.list[*].dictionary */ + if (DList.list) + free(DList.list); + memset(&DList, 0, sizeof(DictList)); +} + + +static int +comparedict(const void *a, const void *b) +{ + return ((DictInfo *) a)->dict_id - ((DictInfo *) b)->dict_id; +} + +DictInfo * +finddict(Oid id) +{ + /* last used dict */ + if (DList.last_dict && DList.last_dict->dict_id == id) + return DList.last_dict; + + + /* already used dict */ + if (DList.len != 0) + { + DictInfo key; + + key.dict_id = id; + DList.last_dict = bsearch(&key, DList.list, DList.len, sizeof(DictInfo), comparedict); + if (DList.last_dict != NULL) + return DList.last_dict; + } + + /* last chance */ + if (DList.len == DList.reallen) + { + DictInfo *tmp; + int reallen = (DList.reallen) ? 2 * DList.reallen : 16; + + tmp = (DictInfo *) realloc(DList.list, sizeof(DictInfo) * reallen); + if (!tmp) + ts_error(ERROR, "No memory"); + DList.reallen = reallen; + DList.list = tmp; + } + DList.last_dict = &(DList.list[DList.len]); + init_dict(id, DList.last_dict); + + DList.len++; + qsort(DList.list, DList.len, sizeof(DictInfo), comparedict); + return finddict(id); /* qsort changed order!! */ ; +} + +static void *plan_name2id = NULL; + +Oid +name2id_dict(text *name) +{ + Oid arg[1] = {TEXTOID}; + bool isnull; + Datum pars[1] = {PointerGetDatum(name)}; + int stat; + Oid id = findSNMap_t(&(DList.name2id_map), name); + + if (id) + return id; + + SPI_connect(); + if (!plan_name2id) + { + plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_dict where dict_name = $1", 1, arg)); + if (!plan_name2id) + ts_error(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_name2id, pars, " ", 1); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + else + ts_error(ERROR, "No dictionary with name '%s'", text2char(name)); + SPI_finish(); + addSNMap_t(&(DList.name2id_map), name, id); + return id; +} + + +/******sql-level interface******/ +PG_FUNCTION_INFO_V1(lexize); +Datum lexize(PG_FUNCTION_ARGS); + +Datum +lexize(PG_FUNCTION_ARGS) +{ + text *in = PG_GETARG_TEXT_P(1); + DictInfo *dict = finddict(PG_GETARG_OID(0)); + char **res, + **ptr; + Datum *da; + ArrayType *a; + + + ptr = res = (char **) DatumGetPointer( + FunctionCall3(&(dict->lexize_info), + PointerGetDatum(dict->dictionary), + PointerGetDatum(VARDATA(in)), + Int32GetDatum(VARSIZE(in) - VARHDRSZ) + ) + ); + PG_FREE_IF_COPY(in, 1); + if (!res) + { + if (PG_NARGS() > 2) + PG_RETURN_POINTER(NULL); + else + PG_RETURN_NULL(); + } + + while (*ptr) + ptr++; + da = (Datum *) palloc(sizeof(Datum) * (ptr - res + 1)); + ptr = res; + while (*ptr) + { + da[ptr - res] = PointerGetDatum(char2text(*ptr)); + ptr++; + } + + a = construct_array( + da, + ptr - res, + TEXTOID, + -1, + false, + 'i' + ); + + ptr = res; + while (*ptr) + { + pfree(DatumGetPointer(da[ptr - res])); + pfree(*ptr); + ptr++; + } + pfree(res); + pfree(da); + + PG_RETURN_POINTER(a); +} + +PG_FUNCTION_INFO_V1(lexize_byname); +Datum lexize_byname(PG_FUNCTION_ARGS); +Datum +lexize_byname(PG_FUNCTION_ARGS) +{ + text *dictname = PG_GETARG_TEXT_P(0); + Datum res; + + strdup("simple"); + res = DirectFunctionCall3( + lexize, + ObjectIdGetDatum(name2id_dict(dictname)), + PG_GETARG_DATUM(1), + (Datum) 0 + ); + PG_FREE_IF_COPY(dictname, 0); + if (res) + PG_RETURN_DATUM(res); + else + PG_RETURN_NULL(); +} + +static Oid currect_dictionary_id = 0; + +PG_FUNCTION_INFO_V1(set_curdict); +Datum set_curdict(PG_FUNCTION_ARGS); +Datum +set_curdict(PG_FUNCTION_ARGS) +{ + finddict(PG_GETARG_OID(0)); + currect_dictionary_id = PG_GETARG_OID(0); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(set_curdict_byname); +Datum set_curdict_byname(PG_FUNCTION_ARGS); +Datum +set_curdict_byname(PG_FUNCTION_ARGS) +{ + text *dictname = PG_GETARG_TEXT_P(0); + + DirectFunctionCall1( + set_curdict, + ObjectIdGetDatum(name2id_dict(dictname)) + ); + PG_FREE_IF_COPY(dictname, 0); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(lexize_bycurrent); +Datum lexize_bycurrent(PG_FUNCTION_ARGS); +Datum +lexize_bycurrent(PG_FUNCTION_ARGS) +{ + Datum res; + + if (currect_dictionary_id == 0) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("no currect dictionary"), + errhint("Execute select set_curdict()."))); + + res = DirectFunctionCall3( + lexize, + ObjectIdGetDatum(currect_dictionary_id), + PG_GETARG_DATUM(0), + (Datum) 0 + ); + if (res) + PG_RETURN_DATUM(res); + else + PG_RETURN_NULL(); +} diff --git a/contrib/tsearch2/dict.h b/contrib/tsearch2/dict.h new file mode 100644 index 0000000..86ea422 --- /dev/null +++ b/contrib/tsearch2/dict.h @@ -0,0 +1,41 @@ +#ifndef __DICT_H__ +#define __DICT_H__ +#include "postgres.h" +#include "fmgr.h" + +typedef struct +{ + int len; + char **stop; + char *(*wordop) (char *); +} StopList; + +void sortstoplist(StopList * s); +void freestoplist(StopList * s); +void readstoplist(text *in, StopList * s); +bool searchstoplist(StopList * s, char *key); +char *lowerstr(char *str); + +typedef struct +{ + Oid dict_id; + FmgrInfo lexize_info; + void *dictionary; +} DictInfo; + +void init_dict(Oid id, DictInfo * dict); +DictInfo *finddict(Oid id); +Oid name2id_dict(text *name); +void reset_dict(void); + + +/* simple parser of cfg string */ +typedef struct +{ + char *key; + char *value; +} Map; + +void parse_cfgdict(text *in, Map ** m); + +#endif diff --git a/contrib/tsearch2/dict_ex.c b/contrib/tsearch2/dict_ex.c new file mode 100644 index 0000000..a8fb204 --- /dev/null +++ b/contrib/tsearch2/dict_ex.c @@ -0,0 +1,69 @@ +/* + * example of dictionary + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" + +typedef struct +{ + StopList stoplist; +} DictExample; + + +PG_FUNCTION_INFO_V1(dex_init); +Datum dex_init(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(dex_lexize); +Datum dex_lexize(PG_FUNCTION_ARGS); + +Datum +dex_init(PG_FUNCTION_ARGS) +{ + DictExample *d = (DictExample *) malloc(sizeof(DictExample)); + + if (!d) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(d, 0, sizeof(DictExample)); + + d->stoplist.wordop = lowerstr; + + if (!PG_ARGISNULL(0) && PG_GETARG_POINTER(0) != NULL) + { + text *in = PG_GETARG_TEXT_P(0); + + readstoplist(in, &(d->stoplist)); + sortstoplist(&(d->stoplist)); + PG_FREE_IF_COPY(in, 0); + } + + PG_RETURN_POINTER(d); +} + +Datum +dex_lexize(PG_FUNCTION_ARGS) +{ + DictExample *d = (DictExample *) PG_GETARG_POINTER(0); + char *in = (char *) PG_GETARG_POINTER(1); + char *txt = pnstrdup(in, PG_GETARG_INT32(2)); + char **res = palloc(sizeof(char *) * 2); + + if (*txt == '\0' || searchstoplist(&(d->stoplist), txt)) + { + pfree(txt); + res[0] = NULL; + } + else + res[0] = txt; + res[1] = NULL; + + PG_RETURN_POINTER(res); +} diff --git a/contrib/tsearch2/dict_ispell.c b/contrib/tsearch2/dict_ispell.c new file mode 100644 index 0000000..e3a100f --- /dev/null +++ b/contrib/tsearch2/dict_ispell.c @@ -0,0 +1,196 @@ +/* + * ISpell interface + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" +#include "ispell/spell.h" + +typedef struct +{ + StopList stoplist; + IspellDict obj; +} DictISpell; + +PG_FUNCTION_INFO_V1(spell_init); +Datum spell_init(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(spell_lexize); +Datum spell_lexize(PG_FUNCTION_ARGS); + +static void +freeDictISpell(DictISpell * d) +{ + FreeIspell(&(d->obj)); + freestoplist(&(d->stoplist)); + free(d); +} + +Datum +spell_init(PG_FUNCTION_ARGS) +{ + DictISpell *d; + Map *cfg, + *pcfg; + text *in; + bool affloaded = false, + dictloaded = false, + stoploaded = false; + + if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("ISpell confguration error"))); + + d = (DictISpell *) malloc(sizeof(DictISpell)); + if (!d) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(d, 0, sizeof(DictISpell)); + d->stoplist.wordop = lowerstr; + + in = PG_GETARG_TEXT_P(0); + parse_cfgdict(in, &cfg); + PG_FREE_IF_COPY(in, 0); + pcfg = cfg; + while (pcfg->key) + { + if (strcasecmp("DictFile", pcfg->key) == 0) + { + if (dictloaded) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("dictionary already loaded"))); + } + if (ImportDictionary(&(d->obj), pcfg->value)) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not load dictionary file \"%s\"", + pcfg->value))); + } + dictloaded = true; + } + else if (strcasecmp("AffFile", pcfg->key) == 0) + { + if (affloaded) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("affixes already loaded"))); + } + if (ImportAffixes(&(d->obj), pcfg->value)) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not load affix file \"%s\"", + pcfg->value))); + } + affloaded = true; + } + else if (strcasecmp("StopFile", pcfg->key) == 0) + { + text *tmp = char2text(pcfg->value); + + if (stoploaded) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("stop words already loaded"))); + } + readstoplist(tmp, &(d->stoplist)); + sortstoplist(&(d->stoplist)); + pfree(tmp); + stoploaded = true; + } + else + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized option: %s => %s", + pcfg->key, pcfg->value))); + } + pfree(pcfg->key); + pfree(pcfg->value); + pcfg++; + } + pfree(cfg); + + if (affloaded && dictloaded) + { + SortDictionary(&(d->obj)); + SortAffixes(&(d->obj)); + } + else if (!affloaded) + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("no affixes"))); + } + else + { + freeDictISpell(d); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("no dictionary"))); + } + + PG_RETURN_POINTER(d); +} + +Datum +spell_lexize(PG_FUNCTION_ARGS) +{ + DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0); + char *in = (char *) PG_GETARG_POINTER(1); + char *txt; + char **res; + char **ptr, + **cptr; + + if (!PG_GETARG_INT32(2)) + PG_RETURN_POINTER(NULL); + + res = palloc(sizeof(char *) * 2); + txt = pnstrdup(in, PG_GETARG_INT32(2)); + res = NormalizeWord(&(d->obj), txt); + pfree(txt); + + if (res == NULL) + PG_RETURN_POINTER(NULL); + + ptr = cptr = res; + while (*ptr) + { + if (searchstoplist(&(d->stoplist), *ptr)) + { + pfree(*ptr); + *ptr = NULL; + ptr++; + } + else + { + *cptr = *ptr; + cptr++; + ptr++; + } + } + *cptr = NULL; + + PG_RETURN_POINTER(res); +} diff --git a/contrib/tsearch2/dict_snowball.c b/contrib/tsearch2/dict_snowball.c new file mode 100644 index 0000000..51dba04 --- /dev/null +++ b/contrib/tsearch2/dict_snowball.c @@ -0,0 +1,131 @@ +/* + * example of Snowball dictionary + * http://snowball.tartarus.org/ + * Teodor Sigaev + */ +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" +#include "snowball/header.h" +#include "snowball/english_stem.h" +#include "snowball/russian_stem.h" + +typedef struct +{ + struct SN_env *z; + StopList stoplist; + int (*stem) (struct SN_env * z); +} DictSnowball; + + +PG_FUNCTION_INFO_V1(snb_en_init); +Datum snb_en_init(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(snb_ru_init); +Datum snb_ru_init(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(snb_lexize); +Datum snb_lexize(PG_FUNCTION_ARGS); + +Datum +snb_en_init(PG_FUNCTION_ARGS) +{ + DictSnowball *d = (DictSnowball *) malloc(sizeof(DictSnowball)); + + if (!d) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(d, 0, sizeof(DictSnowball)); + d->stoplist.wordop = lowerstr; + + if (!PG_ARGISNULL(0) && PG_GETARG_POINTER(0) != NULL) + { + text *in = PG_GETARG_TEXT_P(0); + + readstoplist(in, &(d->stoplist)); + sortstoplist(&(d->stoplist)); + PG_FREE_IF_COPY(in, 0); + } + + d->z = english_create_env(); + if (!d->z) + { + freestoplist(&(d->stoplist)); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + d->stem = english_stem; + + PG_RETURN_POINTER(d); +} + +Datum +snb_ru_init(PG_FUNCTION_ARGS) +{ + DictSnowball *d = (DictSnowball *) malloc(sizeof(DictSnowball)); + + if (!d) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(d, 0, sizeof(DictSnowball)); + d->stoplist.wordop = lowerstr; + + if (!PG_ARGISNULL(0) && PG_GETARG_POINTER(0) != NULL) + { + text *in = PG_GETARG_TEXT_P(0); + + readstoplist(in, &(d->stoplist)); + sortstoplist(&(d->stoplist)); + PG_FREE_IF_COPY(in, 0); + } + + d->z = russian_create_env(); + if (!d->z) + { + freestoplist(&(d->stoplist)); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + d->stem = russian_stem; + + PG_RETURN_POINTER(d); +} + +Datum +snb_lexize(PG_FUNCTION_ARGS) +{ + DictSnowball *d = (DictSnowball *) PG_GETARG_POINTER(0); + char *in = (char *) PG_GETARG_POINTER(1); + char *txt = pnstrdup(in, PG_GETARG_INT32(2)); + char **res = palloc(sizeof(char *) * 2); + + if (*txt == '\0' || searchstoplist(&(d->stoplist), txt)) + { + pfree(txt); + res[0] = NULL; + } + else + { + SN_set_current(d->z, strlen(txt), txt); + (d->stem) (d->z); + if (d->z->p && d->z->l) + { + txt = repalloc(txt, d->z->l + 1); + memcpy(txt, d->z->p, d->z->l); + txt[d->z->l] = '\0'; + } + res[0] = txt; + } + res[1] = NULL; + + + PG_RETURN_POINTER(res); +} diff --git a/contrib/tsearch2/dict_syn.c b/contrib/tsearch2/dict_syn.c new file mode 100644 index 0000000..8364223 --- /dev/null +++ b/contrib/tsearch2/dict_syn.c @@ -0,0 +1,185 @@ +/* + * ISpell interface + * Teodor Sigaev + */ +#include +#include +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" + +#define SYNBUFLEN 4096 +typedef struct +{ + char *in; + char *out; +} Syn; + +typedef struct +{ + int len; + Syn *syn; +} DictSyn; + +PG_FUNCTION_INFO_V1(syn_init); +Datum syn_init(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(syn_lexize); +Datum syn_lexize(PG_FUNCTION_ARGS); + +static char * +findwrd(char *in, char **end) +{ + char *start; + + *end = NULL; + while (*in && isspace(*in)) + in++; + + if (!in) + return NULL; + start = in; + + while (*in && !isspace(*in)) + in++; + + *end = in; + return start; +} + +static int +compareSyn(const void *a, const void *b) +{ + return strcmp(((Syn *) a)->in, ((Syn *) b)->in); +} + + +Datum +syn_init(PG_FUNCTION_ARGS) +{ + text *in; + DictSyn *d; + int cur = 0; + FILE *fin; + char *filename; + char buf[SYNBUFLEN]; + char *starti, + *starto, + *end = NULL; + int slen; + + if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("NULL config"))); + + in = PG_GETARG_TEXT_P(0); + if (VARSIZE(in) - VARHDRSZ == 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("VOID config"))); + + filename = text2char(in); + PG_FREE_IF_COPY(in, 0); + if ((fin = fopen(filename, "r")) == NULL) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", + filename))); + + d = (DictSyn *) malloc(sizeof(DictSyn)); + if (!d) + { + fclose(fin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + memset(d, 0, sizeof(DictSyn)); + + while (fgets(buf, SYNBUFLEN, fin)) + { + slen = strlen(buf) - 1; + buf[slen] = '\0'; + if (*buf == '\0') + continue; + if (cur == d->len) + { + d->len = (d->len) ? 2 * d->len : 16; + d->syn = (Syn *) realloc(d->syn, sizeof(Syn) * d->len); + if (!d->syn) + { + fclose(fin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + } + + starti = findwrd(buf, &end); + if (!starti) + continue; + *end = '\0'; + if (end >= buf + slen) + continue; + + starto = findwrd(end + 1, &end); + if (!starto) + continue; + *end = '\0'; + + d->syn[cur].in = strdup(lowerstr(starti)); + d->syn[cur].out = strdup(lowerstr(starto)); + if (!(d->syn[cur].in && d->syn[cur].out)) + { + fclose(fin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + + cur++; + } + + fclose(fin); + + d->len = cur; + if (cur > 1) + qsort(d->syn, d->len, sizeof(Syn), compareSyn); + + pfree(filename); + PG_RETURN_POINTER(d); +} + +Datum +syn_lexize(PG_FUNCTION_ARGS) +{ + DictSyn *d = (DictSyn *) PG_GETARG_POINTER(0); + char *in = (char *) PG_GETARG_POINTER(1); + Syn key, + *found; + char **res = NULL; + + if (!PG_GETARG_INT32(2)) + PG_RETURN_POINTER(NULL); + + key.out = NULL; + key.in = lowerstr(pnstrdup(in, PG_GETARG_INT32(2))); + + found = (Syn *) bsearch(&key, d->syn, d->len, sizeof(Syn), compareSyn); + pfree(key.in); + + if (!found) + PG_RETURN_POINTER(NULL); + + res = palloc(sizeof(char *) * 2); + + res[0] = pstrdup(found->out); + res[1] = NULL; + + PG_RETURN_POINTER(res); +} diff --git a/contrib/tsearch2/docs/tsearch2-guide.html b/contrib/tsearch2/docs/tsearch2-guide.html new file mode 100644 index 0000000..2529480 --- /dev/null +++ b/contrib/tsearch2/docs/tsearch2-guide.html @@ -0,0 +1,1057 @@ + + + + +tsearch2 guide + + +

The tsearch2 Guide

+ +

+Brandon Craig Rhodes
30 June 2003 +

+This Guide introduces the reader to the PostgreSQL tsearch2 module, +version 2. +More formal descriptions of the module's types and functions +are provided in the tsearch2 Reference, +which is a companion to this document. +You can retrieve a beta copy of the tsearch2 module from the +GiST for PostgreSQL +page — look under the section entitled Development History +for the current version. +

+First we will examine the tsvector and tsquery types +and how they are used to search documents; +next, we will use them to build a simple search engine in SQL; +and finally, we will study the internals of document conversion +and how you might tune the internals to accommodate various searching needs. +

+Once you have tsearch2 working with PostgreSQL, +you should be able to run the examples here exactly as they are typed. +

+


+

Table of Contents

+
+Vectors and Queries
+A Simple Search Engine
+Ranking and Position Weights
+Casting Vectors and Queries
+Parsing and Lexing
+
+ +
+ +

Vectors and Queries

+ +
+This section introduces +the two data types upon which tsearch2 search engines are based, +and illustrates their interaction using the simplest possible case. +The complex examples we present later on +are merely variations and elaborations of this basic mechanism. +
+

+The tsearch2 module allows you to index documents by the words they contain, +and then perform very efficient searches +for documents that contain a given combination of words. +Preparing your document index involves two steps: +

    +
  • Making a list of the words each document contains. + You must reduce each document to a tsvector + which lists each word that appears in the document. + This process offers many options, + because there is no requirement + that you must copy words into the vector + exactly as they appear in the document. + For example, + many developers omit frequent and content-free stop words + like the to reduce the size of their index; + others reduce different forms of the same word + (forked, forking, forks) + to a common form (fork) + to make search results independent of tense and case. + Because words are very often stored in a modified form, + we use the special term lexemes + for the word forms we actually store in the vector. +
  • Creating an index of the documents by lexeme. + This is managed automatically by tsearch2 + when you creat a gist() index + on the tsvector column of a table, + which implements a form of the Berkeley + Generalized Search Tree. +
+Once your documents are indexed, +performing a search involves: +
    +
  • Reducing the search terms to lexemes. + You must express each search you want to perform + as a tsquery specifying a boolean combination of lexemes. + Note that tsearch2 only finds exact matches + between the lexemes in your query and the ones in each vector — + even capitalization counts as a difference + (which is why all lexemes are usually kept lowercase). + So you must process search words the same way you processed document words; + if forking became fork in the document's tsvector, + then the search term forking must also become fork + or the search will not find the document. +
  • Retrieving the documents that match the query. + Running a SELECT ... WHERE + query @@ vector + on the table with the vector column + will return the documents that match your query. +
  • Presenting your results. + This final stage offers as many options + as turning documents into vectors. + You can order documents by how well they matched the search terms; + create a headline for each document + showing some of the phrases in which it uses the search terms; + and restrict the number of results retrieved. + You will of course want some way to identify each document, + so the user can ask for the full text of the ones he wants to read. +
+And beyond deciding upon rules for turning documents into vectors +and for presenting search results to users, +you have to decide where to perform these operations — +whether one database server +will parse documents, perform searches, and prepare search results, +or whether to spread the load of these operations across several machines. +These are complicated design issues +which we will explore later; +in this section and the next, +we will illustrate what can be accomplished +using a single database server. +

+The default tsearch2 configuration, +which we will learn more about later, +provides a good example of a process for reducing documents to vectors: + +

+=# SELECT set_curcfg('default')
+=# SELECT to_tsvector('The air smells of sea water.')
+             to_tsvector             
+-------------------------------------
+ 'air':2 'sea':5 'smell':3 'water':6
+(1 row)
+
+ +Note the complex relationship between this document and its vector. +The vector lists only words from the document — +spaces and punctuation have disappeared. +Common words like the and of have been eliminated. +The -s that makes smells a plural has been removed, +leaving a lexeme that represents the word in its simplest form. +And finally, +though the vector remembers the positions in which each word appeared, +it does not store the lexemes in that order. +

+Keeping word positions in your vectors is optional, by the way. +The positions are necessary for the tsearch2 ranking functions, +which you can use to prioritize documents +based on how often each document uses the search terms +and whether they appear in close proximity. +But if you do not perform ranking, +or use your own process that ignores the word positions stored in the vector, +then you can save space by stripping them from your vectors: + +

+=# SELECT strip(to_tsvector('The air smells of sea water.'))
+            strip            
+-----------------------------
+ 'air' 'sea' 'smell' 'water'
+(1 row)
+
+ +Now that we have a procedure for creating vectors, +we can build an indexed table of vectors very simply: + +
+=# CREATE TABLE vectors ( vector tsvector )
+=# CREATE INDEX vector_index ON vectors USING gist(vector)
+=# INSERT INTO vectors VALUES (to_tsvector('The path forks here'))
+=# INSERT INTO vectors VALUES (to_tsvector('A crawl leads west'))
+=# INSERT INTO vectors VALUES (to_tsvector('The left fork leads northeast'))
+=# SELECT * FROM vectors
+                  vector                  
+------------------------------------------
+ 'fork':3 'path':2
+ 'lead':3 'west':4 'crawl':2
+ 'fork':3 'lead':4 'left':2 'northeast':5
+(3 rows)
+
+ +Now we can search this collection of document vectors +using the @@ operator and a tsquery +that specifies the combination of lexemes we are looking for. +Note that while vectors simply list lexemes, +queries always combine them with the operators +‘&’ and, +‘|’ or, +and  ‘!’ not, +plus parentheses for grouping. +Some examples of the query syntax: + + + + + +
‘find documents with the word forks in them’
+
'forks' +
‘... with both forks and leads
+
'forks & leads' +
‘... with either forks or leads
+
'forks | leads' +
‘... with either forks or leads, + but without crawl
+
'(forks|leads) & !crawl' +
+The tsearch2 module +provides a to_tsquery() function for creating queries +that uses the same process as to_tsvector() uses +to reduce words to lexemes. +For instance, +it will remove the -s from the plurals in the last example above: + +
+=# SELECT to_tsquery('(leads|forks) & !crawl')
+           to_tsquery           
+--------------------------------
+ ( 'lead' | 'fork' ) & !'crawl'
+(1 row)
+
+ +Again, +this is critically important because the search operator @@ +only finds exact matches +between the words in a query and the words in a vector; +if the document vector lists the lexeme fork +but the query looks for the plural form forks, +the query would not match that document. +Thanks to the symmetry between our process +for producing vectors and queries, however, +the above searches return correct results: + +
+=# SELECT * FROM vectors WHERE vector @@ to_tsquery('(leads|forks) & !crawl')
+                  vector                  
+------------------------------------------
+ 'fork':3 'path':2
+ 'fork':3 'lead':4 'left':2 'northeast':5
+(2 rows)
+
+ +You may want to try the other queries shown above, +and perhaps invent some of your own. +

+You should not include stop words in a query, +since you cannot search for words you have discarded. +If you throw out the word the when building vectors, for example, +your index will obviously not know which documents included it. +The to_tsquery() function will automatically detect this +and give you an error to prevent this mistake: + +

+=# SELECT to_tsquery('the')
+NOTICE:  Query contains only stopword(s) or doesn't contain lexem(s), ignored
+ to_tsquery 
+------------
+ 
+(1 row)
+
+ +But if you every build vectors and queries using your own routines, +a possibility we will discuss later, +then you will need to enforce this rule yourself. + +
+Now that you understand how vectors and queries work together, +you are prepared to tackle many additional topics: +how to distribute searching across many servers; +how to customize the process +by which tsearch2 turns documents and queries into lexemes, +or use a process of your own; +and how to sort and display search results to your users. +But before discussing these detailed questions, +we will build a simple search engine +to see how easily its basic features work together. +
+ +

A Simple Search Engine

+ +
+In this section we build a simple search engine out of SQL functions +that use the vector and query types described in the previous section. +While this example is simpler +than a search engine that has to interface with the outside world, +it will illustrate the basic principles of building a search engine, +and better prepare you for developing your own. +
+Building a search engine involves only a few improvements +upon the rudimentary vector searches described in the last section. +
    +
  • Because the user wants to read documents, not vectors, + you must provide some way + for the full text of each document to be accessed — + either by storing the entire text of each document in the database, + or storing an identifier + like a URL, file name, or document routing number + that lets you fetch the document from other storage. +
  • You can make it easier for user interface code to refer to each document + by providing a unique identifier for each document, + perhaps with a SERIAL column. +
  • Search results should be ordered by relevance. + If you leave word positions in your vectors, + you can either have PostgreSQL ORDER your results + BY a ranking function, + or you can fetch the vectors yourself and perform your own sort. + If you choose to ignore word positions or strip them from your vectors, + you will have to determine relevance yourself, + using either the full text of the document + or other information about each document you may possess. +
  • For each document returned by a search, + you will usually want to display a summary called a headline + that shows short excerpts + illustrating how the document uses the query words. + Headlines are usually generated from the full text of the document, + not from position information in the tsvector, + since excerpts lacking stop words, punctuation, and suffixes + would not be comprehensible. + If you store the full text of each document in the database, + headlines can be generated very simply by a tsearch2 function. + If you store your documents elsewhere, + then you will either have to transmit each document to the database + every time you want to run the headline function on it, + or use your own headline code outside of the database. +
+

+We can easily construct a simple search engine +that accomplishes these goals. +First we build a table that, for each document, +stores a unique identifier, the full text of the document, +and its tsvector: + +

+=# CREATE TABLE docs ( id SERIAL, doc TEXT, vector tsvector )
+=# CREATE INDEX docs_index ON docs USING gist(vector);
+
+ +Note that although searches will still work +on tables where you have neglected +to create a gist() index over your vectors, +they will run much more slowly +since they will have to compare the query +against every document vector in the table. +

+Because the table we have created +stores each document in two different ways — +both as text and as a vector — +our INSERT statements must provide the document in both forms. +While more advanced PostgreSQL programmers +might accomplish this with a database trigger or rule, +for this simple example we will use a small SQL function: + +

+=# CREATE FUNCTION insdoc(text) RETURNS void LANGUAGE sql AS
+  'INSERT INTO docs (doc, vector) VALUES ($1, to_tsvector($1));'
+
+ +Now, by calling insdoc() several times, +we can populate our table with documents: + +
+=# SELECT insdoc('A low crawl over cobbles leads inward to the west.')
+=# SELECT insdoc('The canyon runs into a mass of boulders -- dead end.')
+=# SELECT insdoc('You are crawling over cobbles in a low passage.')
+=# SELECT insdoc('Cavernous passages lead east, north, and south.')
+=# SELECT insdoc('To the east a low wide crawl slants up.')
+=# SELECT insdoc('You are in the south side chamber.')
+=# SELECT insdoc('The passage here is blocked by a recent cave-in.')
+=# SELECT insdoc('You are in a splendid chamber thirty feet high.')
+
+ +Now we can build a search function. +Its SELECT statement is based upon +the same @@ operation illustrated in the previous section. +But instead of returning matching vectors, +we return for each document +its SERIAL identifier, so the user can retrieve it later; +a headline that illustrates its use of the search terms; +and a ranking with which we also order the results. +Our search operation can be coded as a single SELECT statement +returning its own kind of table row, +which we call a finddoc_t: + +
+=# CREATE TYPE finddoc_t AS (id INTEGER, headline TEXT, rank REAL)
+=# CREATE FUNCTION finddoc(text) RETURNS SETOF finddoc_t LANGUAGE sql AS '
+   SELECT id, headline(doc, q), rank(vector, q)
+     FROM docs, to_tsquery($1) AS q
+     WHERE vector @@ q ORDER BY rank(vector, q) DESC'
+
+ +This function is a rather satisfactory search engine. +Here is one example search, +after which the user fetches the top-ranking document itself; +with similar commands you can try queries of your own: + +
+=# SELECT * FROM finddoc('passage|crawl')
+ id |                       headline                        | rank 
+----+-------------------------------------------------------+------
+  3 | <b>crawling</b> over cobbles in a low <b>passage</b>. | 0.19
+  1 | <b>crawl</b> over cobbles leads inward to the west.   |  0.1
+  4 | <b>passages</b> lead east, north, and south.          |  0.1
+  5 | <b>crawl</b> slants up.                               |  0.1
+  7 | <b>passage</b> here is blocked by a recent  cave-in.  |  0.1
+(5 rows)
+=# SELECT doc FROM docs WHERE id = 3
+                       doc                       
+-------------------------------------------------
+ You are crawling over cobbles in a low passage.
+(1 row)
+
+ +While by default the headline() function +surrounds matching words with <b> and </b> +in order to distinguish them from the surrounding text, +you can provide options that change its behavior; +consult the tsearch2 Reference for more details about +Headline Functions. +

+Though a search may match hundreds or thousands of documents, +you will usually present only ten or twenty results to the user at a time. +This can be most easily accomplished +by limiting your query with a LIMIT +and an OFFSET clause — +to display results ten at a time, for example, +your would generate your first page of results +with LIMIT 10 OFFSET 0, +your second page +with LIMIT 10 OFFSET 10, +your third page +with LIMIT 10 OFFSET 20, +and so forth. +There are two problems with this approach, however. +

+The first problem is the strain of running the query over again +for every page of results the user views. +For small document collections or lightly loaded servers, +this may not be a problem; +but the impact can be high +when a search must repeatedly rank and sort +the same ten thousand results +on an already busy server. +So instead of selecting only one page of results, +you will probably use LIMIT and OFFSET +to return a few dozen or few hundred results, +which you can cache and display to the user one page at a time. +Whether a result cache rewards your effort +will depend principally on the behavior of your users — +how often they even view the second page of results, for instance. +

+The second issue solved by caching involves consistency. +If the database is changing while the user browses their results, +then documents might appear and disappear as they page through them. +In some cases the user might even miss a particular result — +perhaps the one they were looking for — +if, say, its rank improves from 31th to 30th +after they load results 21–30 but before they view results 31–40. +While many databases are static or infrequently updated, +and will not present this problem, +users searching very dymanic document collections +might benefit from the stable results that caches yield. + +

+Having seen the features of a search engine +implemented entirely within the database, +we will learn about some specific tsearch2 features. +First we will look in more detail at document ranking. +
+ +

Ranking and Position Weights

+ +
+When we built our simple search engine, +we used the rank() function to order our results. +Here we describe tsearch2 ranking in more detail. +
+ +There are two functions with which tsearch2 can rank search results. +They both use the lexeme positions listed in the tsvector, +so you cannot rank vectors +from which these have been removed with strip(). +The rank() function existed in older versions of OpenFTS, +and has the feature that you can assign different weights +to words from different sections of your document. +The rank_cd() uses a recent technique for weighting results +but does not allow different weight to be given +to different sections of your document. +

+Both ranking functions allow you to specify, +as an optional last argument, +whether you want their results normalized — +whether the rank returned should be adjusted for document length. +Specifying a last argument of 0 (zero) makes no adjustment; +1 (one) divides the document rank +by the logarithm of the document length; +and 2 divides it by the plain length. +In all of these examples we omit this optional argument, +which is the same as specifying zero — +we are making no adjustment for document length. +

+The rank_cd() function uses an experimental measurement +called cover density ranking that rewards documents +when they make frequent use of the search terms +that are close together in the document. +You can read about the algorithm in more detail +in Clarke et al., + “Relevance Ranking for One to Three Term Queries.” +An optional first argument allows you to tune their formula; +for details +see the section on ranking +in the Reference. +

+The rank() function offers more flexibility +because it pays attention to the weights +with which you have labelled lexeme positions. +Currently tsearch2 supports four different weight labels: +'D', the default weight; +and 'A', 'B', and 'C'. +All vectors created with to_tsvector() +assign the weight 'D' to each position, +which as the default is not displayed when you print a vector out. +

+If you want positions with weights other than 'D', +you have two options: +either you can author a vector directly through the ::tsvector +casting operation, +as described in the following section, +which lets you give each position whichever weight you want; +or you can pass a vector through the setweight() function +which sets all of its position weights to a single value. +An example of the latter: + + +

+=# SELECT vector FROM docs WHERE id = 3
+                 vector                 
+----------------------------------------
+ 'low':8 'cobbl':5 'crawl':3 'passag':9
+(1 row)
+=# SELECT setweight(vector, 'A') FROM docs WHERE id = 3
+                 setweight                  
+--------------------------------------------
+ 'low':8A 'cobbl':5A 'crawl':3A 'passag':9A
+(1 row)
+
+ + +Merely changing all of the weights in a vector is not very useful, +of course, +since this results still in all words having the same weight. +But if we parse different parts of a document separately, +giving each section its own weight, +and then concatenate the vectors of each part into a single vector, +the result can be very useful. +We can construct a simple example +in which document titles are given greater weight +that text in the body of the document: + + +
+=# CREATE TABLE tdocs ( id SERIAL, title TEXT, doc TEXT, vector tsvector )
+=# CREATE INDEX tdocs_index ON tdocs USING gist(vector);
+=# CREATE FUNCTION instdoc(text, text) RETURNS void LANGUAGE sql AS
+  'INSERT INTO tdocs (title, doc, vector)
+   VALUES ($1, $2, setweight(to_tsvector($1), ''A'') || to_tsvector($2));'
+
+ + +Now words from a document title will be weighted differently +than those in the main text +if we provide the title and body as separate arguments: + + +
+=# SELECT instdoc('Spendid Chamber',
+ 'The walls are frozen rivers of orange stone.')
+ instdoc 
+---------
+ 
+(1 row)
+=# SELECT vector FROM tdocs
+                                    vector                                    
+------------------------------------------------------------------------------
+ 'wall':4 'orang':9 'river':7 'stone':10 'frozen':6 'chamber':2A 'spendid':1A
+(1 row)
+
+ + +Note that although the necessity is unusual, +you can constrain search terms +to only match words from certain sections +by following them with a colon +and a list of the sections in which the word can occur; +by default this list is 'ABCD' +so that search terms match words from all sections. +For example, +here we search for a word both generally, +and then looking only for specific weights: + + +
+=# SELECT title, doc FROM tdocs WHERE vector @@ to_tsquery('spendid')
+      title      |                     doc                      
+-----------------+----------------------------------------------
+ Spendid Chamber | The walls are frozen rivers of orange stone.
+(1 row)
+=# SELECT title, doc FROM tdocs WHERE vector @@ to_tsquery('spendid:A')
+      title      |                     doc                      
+-----------------+----------------------------------------------
+ Spendid Chamber | The walls are frozen rivers of orange stone.
+(1 row)
+=# SELECT title, doc FROM tdocs WHERE vector @@ to_tsquery('spendid:D')
+ title | doc 
+-------+-----
+(0 rows)
+
+ + + + +
+Our examples so far use tsearch2 to parse our documents into vectors. +When your application needs absolute control over vector content, +you will want to use direct type casting, +which is described in the next section. +
+ +

Casting Vectors and Queries

+ +
+While tsearch2 has powerful and flexible ways +to process documents and turn them into document vectors, +you will sometimes want to parse documents on your own +and place the results directly in vectors. +Here we show you how. +
+ +In the preceding examples, +we used the to_tsvector() function +when we needed a document's text reduced to a document vector. +We saw that the function stripped whitespace and punctuation, +eliminated common words, +and altered suffixes to reduce words to a common form. +While these operations are often desirable, +and while in the sections below +we will gain precise control over this process, +there are occasions on which +you want to avoid the changes that to_tsvector() makes to text +and specify explicitly the words that you want in your vectors. +Or you may want to create queries directly +rather than through to_tsquery(). +

+For example, +you may have already developed your own routine +for reducing your documents to searchable lexemes, +and do not want your carefully generated terms altered +by passing them through to_tsvector(). +Or you might be developing and debugging parsing routines of your own +that you are not ready to load into the database. +In either case, +you will find that direct insertion is easily accomplished +if you simply follow some simple rules. +

+Vectors are created directly +when you cast a string of whitespace separated lexemes +to the tsvector type: + + +

+=# select 'the only exit is the way you came in'::tsvector
+                     tsvector                     
+--------------------------------------------------
+ 'in' 'is' 'the' 'way' 'you' 'came' 'exit' 'only'
+(1 row)
+
+ + +Notice that the conversion interpreted the string +simply as a list of lexemes to be included in the vector. +Their order was lost, +as was the number of times each lexeme appeared. +You must keep in mind that directly creating vectors with casting +is not an alternate means of parsing; +it is a way of directly entering lexemes into a vector without parsing. +

+Queries can also be created through casting, +if you separate lexemes with boolean operators +rather than with whitespace. +When creating your own vectors and queries, +remember that the search operator @@ +finds only exact matches between query lexemes and vector lexemes +— +if they are not exactly the same string, +they will not be considered a match. +

+To include lexeme positions in your vector, +write the positions exactly the way tsearch2 displays them +when it prints vectors: +by following each lexeme with a colon +and a comma-separated list of integer positions. +If you list a lexeme more than once, +then all the positions listed for it are combined into a single list. +For example, +here are two ways of writing the same vector, +depending on whether you mention ‘the’ twice +or combine its positions into a list yourself: + + +

+=# select 'the:1 only:2 exit:3 is:4 the:5 way:6 you:7 came:8 in:9'::tsvector
+                              tsvector                              
+--------------------------------------------------------------------
+ 'in':9 'is':4 'the':1,5 'way':6 'you':7 'came':8 'exit':3 'only':2
+(1 row)
+=# select 'the:1,5 only:2 exit:3 is:4 way:6 you:7 came:8 in:9'::tsvector
+                              tsvector                              
+--------------------------------------------------------------------
+ 'in':9 'is':4 'the':1,5 'way':6 'you':7 'came':8 'exit':3 'only':2
+(1 row)
+
+ + +Things can get slightly tricky +if you want to include apostrophes, backslashes, or spaces +inside your lexemes +(wanting to include either of the latter would be unusual, +but they can be included if you follow the rules). +The main problem is that the apostrophe and backslash +are important both to PostgreSQL when it is interpreting a string, +and to the tsvector conversion function. +You may want to review section +1.1.2.1, +“String Constants” +in the PostgreSQL documentation before proceeding. +

+When you cast strings directly into vectors: +

    +
  • The string is interpreted as a whitespace-separated list of lexemes, + any of which can be suffixed with a colon and a list of positions. +
  • A lexeme can be quoted by preceding it with an apostrophe, + in which case it runs until the next apostrophe; + otherwise a lexeme ends with the first whitespace or colon encountered. +
  • Any character preceded by a backslash, + including whitespace, the apostrophe, the colon, and the backslash itself, + loses its normal meaning and is treated as a letter. + Backslashes are effective + both inside and outside of apostrophe-quoted lexemes. +
  • A lexeme can be suffixed with a list of positions + by appending a colon and a comma-separated list of integers, + each of which can itself be followed by a letter + to designate a position weight + (position weights are described below). +
+ +Here are some example strings, +showing the lexeme you want to insert +together with the string that the ::tsvector operator +needs to see, +and how you would type that string at the PostgreSQL prompt: + + + + + + + + + + + + +
For the lexeme... +you need the string... +which you can type as: +
nugget +nugget +'nugget' +
won't +won't +'won''t' +
pinin' +pinin' +'pinin''' +
'bout +\'bout +'\\''bout' +
white mist +white\ mist +'white\\ mist' +
or: +'white mist' +'''white mist''' +
won't budge +won\'t\ budge +'won\\''t\\ budge' +
or: +'won\'t budge' +'''won\\''t budge''' +
back\slashed +back\\slashed +'back\\\\slashed' +
+ +Remember to use the quoted quoting shown at the right +only when typing in strings as part of a PostgreSQL query. +If you are providing strings through a library +that automatically quotes them +or provides them in binary form to PostgreSQL, +then you can use the strings in the middle instead — +suitably quoted in the language you are using, of course. +

+Position weights are described below +and can be written exactly as they will be displayed +when you select a weighted vector: + +

+=# select 'weighty:1,3A trivial:2B,4'::tsvector
+           tsvector            
+-------------------------------
+ 'trivial':2B,4 'weighty':1,3A
+(1 row)
+
+ +

+Note that if you are composing SQL queries +in a scripting language like Perl or Python, +that itself considers quotes and backslashes special, +then you may have another quoting layer to deal with +on top of the two layers already shown above. +In such cases you may want to write a function +that performs the necessary quoting for you. + +

+Having seen how to create vectors of your own, +it is time to learn how the native tsearch2 parser +reduces documents to vectors. +
+ +

Parsing and Lexing

+ +
+The previous section +described how you can bypass the parser provided by tsearch2 +and populate your table of documents +with vectors of your own devising. +But for those interested in the native tsearch2 facilities, +we present here an overview of how it goes about +reducing documents to vectors. +
+ +The to_tsvector() function reduces documents to vectors +in two stages. +First, a parser breaks the input document +into short sequences of text called tokens. +Each token is usually a word, space, or piece of punctuation, +though some parsers return larger and more exotic items +like HTML tags as single tokens. +Each token returned by the parser +is either discarded +or passed to a dictionary that converts it into a lexeme. +The resulting lexemes are collected into a vector and returned. +

+The choice of which parser and dictionaries to_tsvector() should use +is controlled by your choice of configuration. +The tsearch2 module comes with several configurations, +and you can define more of your own; +in fact the creation of a new configuration is illustrated below, +in the section on position weights. +

+To learn about parsing in more detail, +we will study this example: + +

+=# select to_tsvector('default',
+     'The walls extend upward for well over 100 feet.')
+                       to_tsvector                        
+----------------------------------------------------------
+ '100':8 'feet':9 'wall':2 'well':6 'extend':3 'upward':4
+(1 row)
+
+ +Unlike the to_tsvector() calls used in the above examples, +this one specifies the 'default' configuration explicitly. +When we called to_tsvector() in earlier examples +with only one argument, +it used the current configuration, +which is chosen automatically based on your LOCALE +if that locale is mentioned in the pg_ts_cfg table +(which is shown under the first bullet in the description below). +If your locale is not listed in the table, +your attempts to use the current configuration will return: + +
+ERROR:  Can't find tsearch2 config by locale
+
+ +You can always change the current configuration manually +by calling the set_curcfg() function +described in the section on +Configurations +in the Reference. +

+Each configuration serves as an index into two different tables: +in pg_ts_cfg it determines +which parser will break our text into tokens, +and in pg_ts_cfgmap +it directs each token to a dictionary for processing. +The steps in detail are: + +

    +
  • +

    First, our text is parsed, +using the parser listed for our configuration in the pg_ts_cfg table. +We are using the 'default' configuration, +so the table tells us to use the 'default' parser: + +

    +=# SELECT * FROM pg_ts_cfg WHERE ts_name = 'default'
    + ts_name | prs_name | locale 
    +---------+----------+--------
    + default | default  | C
    +(1 row)
    +
    + +So our text will be parsed as though we had called: + +
    +=# select * from parse('default',
    +     'The walls extend upward for well over 100 feet.')
    +
    + +This breaks the text into a list of tokens +which are each labelled with an integer type: +

    +The112walls112extend112upward112for112well112over1121002212feet1.12 +

    +Each word has been assigned type 1; +each space (represented here by a diamond) and the period, type 12; +and the number one hundred, type 22. +We can retrieve the alias for each type +through the token_type function: + +

    +=# select * from token_type('default')
    +     where tokid = 1 or tokid = 12 or tokid = 22
    + tokid | alias |      descr       
    +-------+-------+------------------
    +     1 | lword | Latin word
    +    12 | blank | Space symbols
    +    22 | uint  | Unsigned integer
    +(3 rows)
    +
    + + +
  • +Next, the tokens are assigned to dictionaries +by looking up their type aliases in pg_ts_cfgmap +to determine which dictionary should process each token. +Since we are using the 'default' configuration: + +
    +=# select * from pg_ts_cfgmap where ts_name = 'default' and
    +      (tok_alias = 'lword' or tok_alias = 'blank' or tok_alias = 'uint')
    + ts_name | tok_alias | dict_name 
    +---------+-----------+-----------
    + default | lword     | {en_stem}
    + default | uint      | {simple}
    +(2 rows)
    +
    + +Since this map provides no dictionary for blank tokens, +the spaces and period are simply discarded, +leaving nine tokens, +which are then numbered by their position: +

    +The1 +walls2 +extend3 +upward4 +for5 +well6 +over7 +1008 +feet9 + +

  • +Finally, the words are reduced to lexemes by their respective dictionaries. +The 100 is submitted to the simple dictionary, +which returns tokens unaltered except for making them lowercase: + +
    +=# select lexize('simple', '100')
    + lexize 
    +--------
    + {100}
    +(1 row)
    +
    + +The other words are submitted to en_stem +which reduces each English word to a linguistic stem, +and then discards stems which belong to its list of stop words; +you can see the list of stop words +in the file whose path is in the dict_initoption field +of the pg_ts_dict table entry for en_stem. +The first three words of our text illustrate respectively +an en_stem stop word, +a word which en_stem alters by stemming, +and a word which en_stem leaves alone: + +
    +=# select lexize('en_stem', 'The')
    + lexize 
    +--------
    + {}
    +(1 row)
    +=# select lexize('en_stem', 'walls')
    + lexize 
    +--------
    + {wall}
    +(1 row)
    +=# select lexize('en_stem', 'extend')
    +  lexize  
    +----------
    + {extend}
    +(1 row)
    +
    + +Once en_stem is done discarding stop words and stemming the rest, +we are left with: +

    +wall2 +extend3 +upward4 +well6 +1008 +feet9 +

    +Which is precisely the result of the example that began this section. +

+Query words are stemmed by the to_tsquery() function +using the same scheme to determine the dictionary for each token, +with the difference that the query parser recognizes as special +the boolean operators that separate query words. + + + + + diff --git a/contrib/tsearch2/docs/tsearch2-ref.html b/contrib/tsearch2/docs/tsearch2-ref.html new file mode 100644 index 0000000..a6d3107 --- /dev/null +++ b/contrib/tsearch2/docs/tsearch2-ref.html @@ -0,0 +1,457 @@ + +tsearch2 reference + + +

The tsearch2 Reference

+ +

+Brandon Craig Rhodes
30 June 2003 (edited by Oleg Bartunov, 2 Aug 2003). +

+This Reference documents the user types and functions +of the tsearch2 module for PostgreSQL. +An introduction to the module is provided +by the tsearch2 Guide, +a companion document to this one. +You can retrieve a beta copy of the tsearch2 module from the +GiST for PostgreSQL +page -- look under the section entitled Development History +for the current version. + +

Vectors and Queries

+ +Vectors and queries both store lexemes, +but for different purposes. +A tsvector stores the lexemes +of the words that are parsed out of a document, +and can also remember the position of each word. +A tsquery specifies a boolean condition among lexemes. +

+Any of the following functions with a configuration argument +can use either an integer id or textual ts_name +to select a configuration; +if the option is omitted, then the current configuration is used. +For more information on the current configuration, +read the next section on Configurations. + +

Vector Operations

+ +
+ to_tsvector( [configuration,] + document TEXT) RETURNS tsvector +
+ Parses a document into tokens, + reduces the tokens to lexemes, + and returns a tsvector which lists the lexemes + together with their positions in the document. + For the best description of this process, + see the section on Parsing and Stemming + in the accompanying tsearch2 Guide. +
+ strip(vector tsvector) RETURNS tsvector +
+ Return a vector which lists the same lexemes + as the given vector, + but which lacks any information + about where in the document each lexeme appeared. + While the returned vector is thus useless for relevance ranking, + it will usually be much smaller. +
+ setweight(vector tsvector, letter) RETURNS tsvector +
+ This function returns a copy of the input vector + in which every location has been labelled + with either the letter + 'A', 'B', or 'C', + or the default label 'D' + (which is the default with which new vectors are created, + and as such is usually not displayed). + These labels are retained when vectors are concatenated, + allowing words from different parts of a document + to be weighted differently by ranking functions. +
+ vector1 || vector2 +
+ concat(vector1 tsvector, vector2 tsvector) + RETURNS tsvector +
+ Returns a vector which combines the lexemes and position information + in the two vectors given as arguments. + Position weight labels (described in the previous paragraph) + are retained intact during the concatenation. + This has at least two uses. + First, + if some sections of your document + need be parsed with different configurations than others, + you can parse them separately + and concatenate the resulting vectors into one. + Second, + you can weight words from some sections of you document + more heavily than those from others by: + parsing the sections into separate vectors; + assigning the vectors different position labels + with the setweight() function; + concatenating them into a single vector; + and then providing a weights argument + to the rank() function + that assigns different weights to positions with different labels. +
+ tsvector_size(vector tsvector) RETURNS INT4 +
+ Returns the number of lexemes stored in the vector. +
+ text::tsvector RETURNS tsvector +
+ Directly casting text to a tsvector + allows you to directly inject lexemes into a vector, + with whatever positions and position weights you choose to specify. + The text should be formatted + like the vector would be printed by the output of a SELECT. + See the Casting + section in the Guide for details. +
+ +

Query Operations

+ +
+ to_tsquery( [configuration,] + querytext text) RETURNS tsvector +
+ Parses a query, + which should be single words separated by the boolean operators + "&" and, + "|" or, + and "!" not, + which can be grouped using parenthesis. + Each word is reduced to a lexeme using the current + or specified configuration. + +
+ querytree(query tsquery) RETURNS text +
+ This might return a textual representation of the given query. +
+ text::tsquery RETURNS tsquery +
+ Directly casting text to a tsquery + allows you to directly inject lexemes into a query, + with whatever positions and position weight flags you choose to specify. + The text should be formatted + like the query would be printed by the output of a SELECT. + See the Casting + section in the Guide for details. +
+ +

Configurations

+ +A configuration specifies all of the equipment necessary +to transform a document into a tsvector: +the parser that breaks its text into tokens, +and the dictionaries which then transform each token into a lexeme. +Every call to to_tsvector() (described above) +uses a configuration to perform its processing. +Three configurations come with tsearch2: + +
    +
  • default -- Indexes words and numbers, + using the en_stem English Snowball stemmer for Latin-alphabet words + and the simple dictionary for all others. +
  • default_russian -- Indexes words and numbers, + using the en_stem English Snowball stemmer for Latin-alphabet words + and the ru_stem Russian Snowball dictionary for all others. +
  • simple -- Processes both words and numbers + with the simple dictionary, + which neither discards any stop words nor alters them. +
+ +The tsearch2 modules initially chooses your current configuration +by looking for your current locale in the locale field +of the pg_ts_cfg table described below. +You can manipulate the current configuration yourself with these functions: + +
+ set_curcfg( id INT | ts_name TEXT + ) RETURNS VOID +
+ Set the current configuration used by to_tsvector + and to_tsquery. +
+ show_curcfg() RETURNS INT4 +
+ Returns the integer id of the current configuration. +
+ +

+Each configuration is defined by a record in the pg_ts_cfg table: + +

create table pg_ts_cfg (
+	id		int not  null primary key,
+	ts_name		text not null,
+	prs_name	text not null,
+	locale		text
+);
+ +The id and ts_name are unique values +which identify the configuration; +the prs_name specifies which parser the configuration uses. +Once this parser has split document text into tokens, +the type of each resulting token -- +or, more specifically, the type's tok_alias +as specified in the parser's lexem_type() table -- +is searched for together with the configuration's ts_name +in the pg_ts_cfgmap table: + +
create table pg_ts_cfgmap (
+	ts_name		text not null,
+	tok_alias	text not null,
+	dict_name	text[],
+	primary key (ts_name,tok_alias)
+);
+ +Those tokens whose types are not listed are discarded. +The remaining tokens are assigned integer positions, +starting with 1 for the first token in the document, +and turned into lexemes with the help of the dictionaries +whose names are given in the dict_name array for their type. +These dictionaries are tried in order, +stopping either with the first one to return a lexeme for the token, +or discarding the token if no dictionary returns a lexeme for it. + +

Testing

+ +Function ts_debug allows easy testing of your current configuration. +You may always test another configuration using set_curcfg function. +

+Example: +

apod=# select * from ts_debug('Tsearch module for PostgreSQL 7.3.3');
+ ts_name | tok_type | description |   token    | dict_name |  tsvector    
+---------+----------+-------------+------------+-----------+--------------
+ default | lword    | Latin word  | Tsearch    | {en_stem} | 'tsearch'
+ default | lword    | Latin word  | module     | {en_stem} | 'modul'
+ default | lword    | Latin word  | for        | {en_stem} | 
+ default | lword    | Latin word  | PostgreSQL | {en_stem} | 'postgresql'
+ default | version  | VERSION     | 7.3.3      | {simple}  | '7.3.3'
+
+Here: +
+
    +
  • tsname - configuration name +
  • tok_type - token type +
  • description - human readable name of tok_type +
  • token - parser's token +
  • dict_name - dictionary used for the token +
  • tsvector - final result
+ + +

Parsers

+ +Each parser is defined by a record in the pg_ts_parser table: + +
create table pg_ts_parser (
+	prs_name	text not null,
+	prs_start	oid not null,
+	prs_nexttoken	oid not null,
+	prs_end		oid not null,
+	prs_headline	oid not null,
+	prs_lextype	oid not null,
+	prs_comment	text
+);
+ +The prs_name uniquely identify the parser, +while prs_comment usually describes its name and version +for the reference of users. +The other items identify the low-level functions +which make the parser operate, +and are only of interest to someone writing a parser of their own. +

+The tsearch2 module comes with one parser named default +which is suitable for parsing most plain text and HTML documents. +

+Each parser argument below +must designate a parser with prs_name; +the current parser is used when this argument is omitted. + +

+ CREATE FUNCTION set_curprs(parser) RETURNS VOID +
+ Selects a current parser + which will be used when any of the following functions + are called without a parser as an argument. +
+ CREATE FUNCTION token_type( + [ parser ] + ) RETURNS SETOF tokentype +
+ Returns a table which defines and describes + each kind of token the parser may produce as output. + For each token type the table gives the tokid + which the parser will label each token of that type, + the alias which names the token type, + and a short description descr for the user to read. +
+ CREATE FUNCTION parse( + [ parser, ] document TEXT + ) RETURNS SETOF tokenout +
+ Parses the given document and returns a series of records, + one for each token produced by parsing. + Each token includes a tokid giving its type + and a lexem which gives its content. +
+ +

Dictionaries

+ +Dictionaries take textual tokens as input, +usually those produced by a parser, +and return lexemes which are usually some reduced form of the token. +Among the dictionaries which come installed with tsearch2 are: + +
    +
  • simple simply folds uppercase letters to lowercase + before returning the word. +
  • en_stem runs an English Snowball stemmer on each word + that attempts to reduce the various forms of a verb or noun + to a single recognizable form. +
  • ru_stem runs a Russian Snowball stemmer on each word. +
+ +Each dictionary is defined by an entry in the pg_ts_dict table: + +
CREATE TABLE pg_ts_dict (
+	dict_name	text not null,
+	dict_init	oid,
+	dict_initoption	text,
+	dict_lexize	oid not null,
+	dict_comment	text
+);
+ +The dict_name +serve as unique identifiers for the dictionary. +The meaning of the dict_initoption varies among dictionaries, +but for the built-in Snowball dictionaries +it specifies a file from which stop words should be read. +The dict_comment is a human-readable description of the dictionary. +The other fields are internal function identifiers +useful only to developers trying to implement their own dictionaries. +

+The argument named dictionary +in each of the following functions +should be dict_name +identifying which dictionary should be used for the operation; +if omitted then the current dictionary is used. + +

+ CREATE FUNCTION set_curdict(dictionary) RETURNS VOID +
+ Selects a current dictionary for use by functions + that do not select a dictionary explicitly. +
+ CREATE FUNCTION lexize( + [ dictionary, ] word text) + RETURNS TEXT[] +
+ Reduces a single word to a lexeme. + Note that lexemes are arrays of zero or more strings, + since in some languages there might be several base words + from which an inflected form could arise. +
+ +

Ranking

+ +Ranking attempts to measure how relevant documents are to particular queries +by inspecting the number of times each search word appears in the document, +and whether different search terms occur near each other. +Note that this information is only available in unstripped vectors -- +ranking functions will only return a useful result +for a tsvector which still has position information! +

+Both of these ranking functions +take an integer normalization option +that specifies whether a document's length should impact its rank. +This is often desirable, +since a hundred-word document with five instances of a search word +is probably more relevant than a thousand-word document with five instances. +The option can have the values: + +

    +
  • 0 (the default) ignores document length. +
  • 1 divides the rank by the logarithm of the length. +
  • 2 divides the rank by the length itself. +
+ +The two ranking functions currently available are: + +
+ CREATE FUNCTION rank(
+ [ weights float4[], ] + vector tsvector, query tsquery, + [ normalization int4 ]
+ ) RETURNS float4
+
+ This is the ranking function from the old version of OpenFTS, + and offers the ability to weight word instances more heavily + depending on how you have classified them. + The weights specify how heavily to weight each category of word: +
{D-weight, C-weight, B-weight, A-weight}
+ If no weights are provided, then these defaults are used: +
{0.1, 0.2, 0.4, 1.0}
+ Often weights are used to mark words from special areas of the document, + like the title or an initial abstract, + and make them more or less important than words in the document body. +
+ CREATE FUNCTION rank_cd(
+ [ K int4, ] + vector tsvector, query tsquery, + [ normalization int4 ]
+ ) RETURNS float4
+
+ This function computes the cover density ranking + for the given document vector and query, + as described in Clarke, Cormack, and Tudhope's + "Relevance Ranking for One to Three Term Queries" + in the 1999 Information Processing and Management. + The value K is one of the values from their formula, + and defaults to K=4. + The examples in their paper K=16; + we can roughly describe the term + as stating how far apart two search terms can fall + before the formula begins penalizing them for lack of proximity. +
+ +

Headlines

+ +
+ CREATE FUNCTION headline(
+ [ id int4, | ts_name text, ] + document text, query tsquery, + [ options text ]
+ ) RETURNS text
+
+ Every form of the the headline() function + accepts a document along with a query, + and returns one or more ellipse-separated excerpts from the document + in which terms from the query are highlighted. + The configuration with which to parse the document + can be specified by either its id or ts_name; + if none is specified that the current configuration is used instead. +

+ An options string if provided should be a comma-separated list + of one or more 'option=value' pairs. + The available options are: +

    +
  • StartSel, StopSel -- + the strings with which query words appearing in the document + should be delimited to distinguish them from other excerpted words. +
  • MaxWords, MinWords -- + limits on the shortest and longest headlines you will accept. +
  • ShortWord -- + this prevents your headline from beginning or ending + with a word which has this many characters or less. + The default value of 3 should eliminate most English + conjunctions and articles. +
+ Any unspecified options receive these defaults: +
StartSel=<b>, StopSel=</b>, MaxWords=35, MinWords=15, ShortWord=3
+ 
+
+ + \ No newline at end of file diff --git a/contrib/tsearch2/gendict/Makefile.IN b/contrib/tsearch2/gendict/Makefile.IN new file mode 100644 index 0000000..c13e496 --- /dev/null +++ b/contrib/tsearch2/gendict/Makefile.IN @@ -0,0 +1,12 @@ +subdir = contrib/CFG_DIR +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global + +MODULE_big = dict_CFG_MODNAME +OBJS = CFG_OFILE +DATA_built = dict_CFG_MODNAME.sql +DOCS = README.CFG_MODNAME +PG_CPPFLAGS = +SHLIB_LINK = ../tsearch2/libtsearch2.a + +include $(top_srcdir)/contrib/contrib-global.mk diff --git a/contrib/tsearch2/gendict/README.gendict b/contrib/tsearch2/gendict/README.gendict new file mode 100644 index 0000000..e91f1b7 --- /dev/null +++ b/contrib/tsearch2/gendict/README.gendict @@ -0,0 +1,130 @@ +Gendict - generate dictionary templates for contrib/tsearch2 module. + +This utility aims to help people creating dictionary for contrib/tsearch v2 +module. Particularly, it has built-in support for snowball stemmers. + +Programming API to tsearch2 dictionaries is described in tsearch v2 +documentation. + + +Prerequisities: + +* PostgreSQL 7.3 and above. + +* You need tsearch2 module sources already compiled + +* Rights to install contrib modules + +Usage: + + run config.sh without parameters to see options and arguments + +Usage: +./config.sh -n DICTNAME ( [ -s [ -p PREFIX ] ] | [ -c CFILES ] [ -h HFILES ] [ -i ] ) [ -v ] [ -d DIR ] [ -C COMMENT ] + -v - be verbose + -d DIR - name of directory in PGSQL_SRC/contrib (default dict_DICTNAME) + -C COMMENT - dictionary comment +Generate Snowball stemmer: +./config.sh -n DICTNAME -s [ -p PREFIX ] [ -v ] [ -d DIR ] [ -C COMMENT ] + -s - generate Snowball wrapper + -p - prefix of Snowball's function, (default DICTNAME) +Generate template dictionary: +./config.sh -n DICTNAME [ -c CFILES ] [ -h HFILES ] [ -i ] [ -v ] [ -d DIR ] [ -C COMMENT ] + -c CFILES - source files, must be placed in contrib/tsearch2/gendict directory. + These files will be used in Makefile. + -h HFILES - header files, must be placed in contrib/tsearch2/gendict directory. + These files will be used in Makefile and subinclude.h + -i - dictionary has init method + + +Example 1: + + Create Portuguese stemmer + + 0. cd PGSQL_SRC/contrib/tsearch2/gendict + + 1. Obtain stem.{c,h} files for Portuguese + + wget http://snowball.tartarus.org/portuguese/stem.c + wget http://snowball.tartarus.org/portuguese/stem.h + + 2. Create template files for Portuguese + + ./config.sh -n pt -s -p portuguese -v -C'Snowball stemmer for Portuguese' + + Note, that argument for -p option should be *the same* as name of stemming + function in stem.c (without _stem) + + A bunch of files will be generated and placed in PGSQL_SRC/contrib/dict_pt + directory. + + 3. Compile and install dictionary + + cd PGSQL_SRC/contrib/dict_pt + make + make install + + 4. Test it + + Sample portuguese words with the stemmed forms are available + from http://snowball.tartarus.org/portuguese/stemmer.html + + createdb testdict + psql testdict < /usr/local/pgsql/share/contrib/tsearch2.sql + psql testdict < /usr/local/pgsql/share/contrib/dict_pt.sql + psql -d testdict -c "select lexize('pt','bobagem');" + lexize + --------- + {bobag} + (1 row) + + Here is what I have in pg_ts_dict table + + psql -d testdict -c "select * from pg_ts_dict where dict_name='pt';" + dict_name | dict_init | dict_initoption | dict_lexize | dict_comment + -----------+-----------+-----------------+-------------+--------------------------------- + pt | 7177806 | | 7159330 | Snowball stemmer for Portuguese + (1 row) + + + Note, that you have already installed dictionary and corresponding + entry in tsearch configuration and you may modify it using + plain SQL commands, for example, specify stop words. + +Example 2: + + a) Simple template dictionary with init method + + ./config.sh -n wow -v -i -C WOW + + b) Create simple template dict (without init method): + ./config.sh -n wow -v -C WOW + + The same as above, but dictionary will have not init method + + Dictionaries obtained in a) and b) are fully working and ready + for use: + a) lowercase input word and remove it if it is a stop word + b) recognizes any word + + c) Simple template dictionary with source files (with init method): + + ./config.sh -n wow -v -i -c a.c -h a.h -C WOW + + Source files ( a.c ) must be placed in contrib/tsearch2/gendict directory. + These files will be used in Makefile. + + Header files ( a.h ), must be placed in contrib/tsearch2/gendict directory. + These files will be used in Makefile and subinclude.h + + d) Simple template dictionary with source files (without init method): + + ./config.sh -n wow -v -c a.c -h a.h -C WOW + + The same as above, but dictionary will have not init method + + After that you have sources in PGSQL_SRC/contrib/dict_wow and + you may edit them to create actual dictionary. + + Please, check Tsearch2 home page (http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/) + for additional information about "Gendict tutorial" and dictionaries. \ No newline at end of file diff --git a/contrib/tsearch2/gendict/config.sh b/contrib/tsearch2/gendict/config.sh new file mode 100755 index 0000000..26bb542 --- /dev/null +++ b/contrib/tsearch2/gendict/config.sh @@ -0,0 +1,183 @@ +#!/bin/sh + +usage () { + echo Usage: + echo $0 -n DICTNAME \( [ -s [ -p PREFIX ] ] \| [ -c CFILES ] [ -h HFILES ] [ -i ] \) [ -v ] [ -d DIR ] [ -C COMMENT ] + echo ' -v - be verbose' + echo ' -d DIR - name of directory in PGSQL_SRL/contrib (default dict_DICTNAME)' + echo ' -C COMMENT - dictionary comment' + echo Generate Snowball stemmer: + echo $0 -n DICTNAME -s [ -p PREFIX ] [ -v ] [ -d DIR ] [ -C COMMENT ] + echo ' -s - generate Snowball wrapper' + echo " -p - prefix of Snowball's function, (default DICTNAME)" + echo Generate template dictionary: + echo $0 -n DICTNAME [ -c CFILES ] [ -h HFILES ] [ -i ] [ -v ] [ -d DIR ] [ -C COMMENT ] + echo ' -c CFILES - source files, must be placed in contrib/tsearch2/gendict directory.' + echo ' These files will be used in Makefile.' + echo ' -h HFILES - header files, must be placed in contrib/tsearch2/gendict directory.' + echo ' These files will be used in Makefile and subinclude.h' + echo ' -i - dictionary has init method' + exit 1; +} + +dictname= +stemmode=no +verbose=no +cfile= +hfile= +dir= +hasinit=no +comment= +prefix= + +while getopts n:c:C:h:d:p:vis opt +do + case "$opt" in + v) verbose=yes;; + s) stemmode=yes;; + i) hasinit=yes;; + n) dictname="$OPTARG";; + c) cfile="$OPTARG";; + h) hfile="$OPTARG";; + d) dir="$OPTARG";; + C) comment="$OPTARG";; + p) prefix="$OPTARG";; + \?) usage;; + esac +done + +[ ${#dictname} -eq 0 ] && usage + +dictname=`echo $dictname | tr '[:upper:]' '[:lower:]'` + +if [ $stemmode = "yes" ] ; then + [ ${#prefix} -eq 0 ] && prefix=$dictname + hasinit=yes + cfile="stem.c" + hfile="stem.h" +fi + +[ ${#dir} -eq 0 ] && dir="dict_$dictname" + +if [ ${#comment} -eq 0 ]; then + comment=null +else + comment="'$comment'" +fi + +ofile= +for f in $cfile +do + f=` echo $f | sed 's#c$#o#'` + ofile="$ofile $f" +done + +if [ $stemmode = "yes" ] ; then + ofile="$ofile dict_snowball.o" +else + ofile="$ofile dict_tmpl.o" +fi + +if [ $verbose = "yes" ]; then + echo Dictname: "'"$dictname"'" + echo Snowball stemmer: $stemmode + echo Has init method: $hasinit + [ $stemmode = "yes" ] && echo Function prefix: $prefix + echo Source files: $cfile + echo Header files: $hfile + echo Object files: $ofile + echo Comment: $comment + echo Directory: ../../$dir +fi + + +[ $verbose = "yes" ] && echo -n 'Build directory... ' +if [ ! -d ../../$dir ]; then + if ! mkdir ../../$dir ; then + echo "Can't create directory ../../$dir" + exit 1 + fi +fi +[ $verbose = "yes" ] && echo ok + + +[ $verbose = "yes" ] && echo -n 'Build Makefile... ' +sed s#CFG_DIR#$dir# < Makefile.IN | sed s#CFG_MODNAME#$dictname# | sed "s#CFG_OFILE#$ofile#" > ../../$dir/Makefile.tmp +if [ $stemmode = "yes" ] ; then + sed "s#^PG_CPPFLAGS.*\$#PG_CPPFLAGS = -I../tsearch2/snowball -I../tsearch2#" < ../../$dir/Makefile.tmp > ../../$dir/Makefile +else + sed "s#^PG_CPPFLAGS.*\$#PG_CPPFLAGS = -I../tsearch2#" < ../../$dir/Makefile.tmp > ../../$dir/Makefile +fi +rm ../../$dir/Makefile.tmp +[ $verbose = "yes" ] && echo ok + + +[ $verbose = "yes" ] && echo -n Build dict_$dictname'.sql.in... ' +if [ $hasinit = "yes" ]; then + sed s#CFG_MODNAME#$dictname# < sql.IN | sed "s#CFG_COMMENT#$comment#" | sed s#^HASINIT## | sed 's#^NOINIT.*$##' > ../../$dir/dict_$dictname.sql.in.tmp + if [ $stemmode = "yes" ] ; then + sed s#^ISSNOWBALL## < ../../$dir/dict_$dictname.sql.in.tmp | sed s#^NOSNOWBALL.*\$## > ../../$dir/dict_$dictname.sql.in + else + sed s#^NOSNOWBALL## < ../../$dir/dict_$dictname.sql.in.tmp | sed s#^ISSNOWBALL.*\$## > ../../$dir/dict_$dictname.sql.in + fi + rm ../../$dir/dict_$dictname.sql.in.tmp +else + sed s#CFG_MODNAME#$dictname# < sql.IN | sed "s#CFG_COMMENT#$comment#" | sed s#^NOINIT## | sed 's#^HASINIT.*$##' | sed s#^NOSNOWBALL## | sed s#^ISSNOWBALL.*\$## > ../../$dir/dict_$dictname.sql.in +fi +[ $verbose = "yes" ] && echo ok + + + +if [ ${#cfile} -ne 0 ] || [ ${#hfile} -ne 0 ] ; then + [ $verbose = "yes" ] && echo -n 'Copy source and header files... ' + if [ ${#cfile} -ne 0 ] ; then + if ! cp $cfile ../../$dir ; then + echo "Cant cp all or one of files: $cfile" + exit 1 + fi + fi + if [ ${#hfile} -ne 0 ] ; then + if ! cp $hfile ../../$dir ; then + echo "Cant cp all or one of files: $hfile" + exit 1 + fi + fi + [ $verbose = "yes" ] && echo ok +fi + + +[ $verbose = "yes" ] && echo -n 'Build sub-include header... ' +echo -n > ../../$dir/subinclude.h +for i in $hfile +do + echo "#include \"$i\"" >> ../../$dir/subinclude.h +done +[ $verbose = "yes" ] && echo ok + + +if [ $stemmode = "yes" ] ; then + [ $verbose = "yes" ] && echo -n 'Build Snowball stemmer... ' + sed s#CFG_MODNAME#$dictname#g < dict_snowball.c.IN | sed s#CFG_PREFIX#$prefix#g > ../../$dir/dict_snowball.c +else + [ $verbose = "yes" ] && echo -n 'Build dictinonary... ' + sed s#CFG_MODNAME#$dictname#g < dict_tmpl.c.IN > ../../$dir/dict_tmpl.c.tmp + if [ $hasinit = "yes" ]; then + sed s#^HASINIT## < ../../$dir/dict_tmpl.c.tmp | sed 's#^NOINIT.*$##' > ../../$dir/dict_tmpl.c + else + sed s#^HASINIT.*\$## < ../../$dir/dict_tmpl.c.tmp | sed 's#^NOINIT##' > ../../$dir/dict_tmpl.c + fi + rm ../../$dir/dict_tmpl.c.tmp +fi +[ $verbose = "yes" ] && echo ok + + +[ $verbose = "yes" ] && echo -n "Build README.$dictname... " +if [ $stemmode = "yes" ] ; then + echo "Autogenerated Snowball's wrapper for $prefix" > ../../$dir/README.$dictname +else + echo "Autogenerated template for $dictname" > ../../$dir/README.$dictname +fi +[ $verbose = "yes" ] && echo ok + +echo All is done + diff --git a/contrib/tsearch2/gendict/dict_snowball.c.IN b/contrib/tsearch2/gendict/dict_snowball.c.IN new file mode 100644 index 0000000..ec25edc --- /dev/null +++ b/contrib/tsearch2/gendict/dict_snowball.c.IN @@ -0,0 +1,56 @@ +/* + * example of Snowball dictionary + * http://snowball.tartarus.org/ + * Teodor Sigaev + */ +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" +#include "snowball/header.h" +#include "subinclude.h" + +typedef struct { + struct SN_env *z; + StopList stoplist; + int (*stem)(struct SN_env * z); +} DictSnowball; + + +PG_FUNCTION_INFO_V1(dinit_CFG_MODNAME); +Datum dinit_CFG_MODNAME(PG_FUNCTION_ARGS); + +Datum +dinit_CFG_MODNAME(PG_FUNCTION_ARGS) { + DictSnowball *d = (DictSnowball*)malloc( sizeof(DictSnowball) ); + + if ( !d ) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(d,0,sizeof(DictSnowball)); + d->stoplist.wordop=lowerstr; + + if ( !PG_ARGISNULL(0) && PG_GETARG_POINTER(0)!=NULL ) { + text *in = PG_GETARG_TEXT_P(0); + readstoplist(in, &(d->stoplist)); + sortstoplist(&(d->stoplist)); + PG_FREE_IF_COPY(in, 0); + } + + d->z = CFG_PREFIX_create_env(); + if (!d->z) { + freestoplist(&(d->stoplist)); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + d->stem=CFG_PREFIX_stem; + + PG_RETURN_POINTER(d); +} + + diff --git a/contrib/tsearch2/gendict/dict_tmpl.c.IN b/contrib/tsearch2/gendict/dict_tmpl.c.IN new file mode 100644 index 0000000..deafdce --- /dev/null +++ b/contrib/tsearch2/gendict/dict_tmpl.c.IN @@ -0,0 +1,66 @@ +/* + * example of dictionary + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" + +#include "subinclude.h" + +HASINIT typedef struct { +HASINIT StopList stoplist; +HASINIT } DictExample; + + +HASINIT PG_FUNCTION_INFO_V1(dinit_CFG_MODNAME); +HASINIT Datum dinit_CFG_MODNAME(PG_FUNCTION_ARGS); + +HASINIT Datum +HASINIT dinit_CFG_MODNAME(PG_FUNCTION_ARGS) { +HASINIT DictExample *d = (DictExample*)malloc( sizeof(DictExample) ); +HASINIT +HASINIT if ( !d ) +HASINIT ereport(ERROR, +HASINIT (errcode(ERRCODE_OUT_OF_MEMORY), +HASINIT errmsg("out of memory"))); +HASINIT memset(d,0,sizeof(DictExample)); +HASINIT +HASINIT d->stoplist.wordop=lowerstr; +HASINIT +HASINIT /* Your INIT code */ +HASINIT +HASINIT if ( !PG_ARGISNULL(0) && PG_GETARG_POINTER(0)!=NULL ) { +HASINIT text *in = PG_GETARG_TEXT_P(0); +HASINIT readstoplist(in, &(d->stoplist)); +HASINIT sortstoplist(&(d->stoplist)); +HASINIT PG_FREE_IF_COPY(in, 0); +HASINIT } +HASINIT +HASINIT PG_RETURN_POINTER(d); +HASINIT } + +PG_FUNCTION_INFO_V1(dlexize_CFG_MODNAME); +Datum dlexize_CFG_MODNAME(PG_FUNCTION_ARGS); +Datum +dlexize_CFG_MODNAME(PG_FUNCTION_ARGS) { +HASINIT DictExample *d = (DictExample*)PG_GETARG_POINTER(0); + char *in = (char*)PG_GETARG_POINTER(1); + char *txt = pnstrdup(in, PG_GETARG_INT32(2)); + char **res=palloc(sizeof(char*)*2); + + /* Your INIT dictionary code */ +HASINIT if ( *txt=='\0' || searchstoplist(&(d->stoplist),txt) ) { +HASINIT pfree(txt); +HASINIT res[0]=NULL; +HASINIT } else + res[0]=txt; + res[1]=NULL; + + PG_RETURN_POINTER(res); +} diff --git a/contrib/tsearch2/gendict/sql.IN b/contrib/tsearch2/gendict/sql.IN new file mode 100644 index 0000000..ff0d842 --- /dev/null +++ b/contrib/tsearch2/gendict/sql.IN @@ -0,0 +1,26 @@ +SET search_path = public; +BEGIN; + +HASINIT create function dinit_CFG_MODNAME(text) +HASINIT returns internal +HASINIT as 'MODULE_PATHNAME' +HASINIT language 'C'; + +NOSNOWBALL create function dlexize_CFG_MODNAME(internal,internal,int4) +NOSNOWBALL returns internal +NOSNOWBALL as 'MODULE_PATHNAME' +NOSNOWBALL language 'C' +NOSNOWBALL with (isstrict); + +insert into pg_ts_dict select + 'CFG_MODNAME', +HASINIT (select oid from pg_proc where proname='dinit_CFG_MODNAME'), +NOINIT null, + null, +ISSNOWBALL (select oid from pg_proc where proname='snb_lexize'), +NOSNOWBALL (select oid from pg_proc where proname='dlexize_CFG_MODNAME'), + CFG_COMMENT +; + + +END; diff --git a/contrib/tsearch2/gistidx.c b/contrib/tsearch2/gistidx.c new file mode 100644 index 0000000..7d55478 --- /dev/null +++ b/contrib/tsearch2/gistidx.c @@ -0,0 +1,688 @@ +#include "postgres.h" + +#include + +#include "access/gist.h" +#include "access/itup.h" +#include "access/rtree.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "storage/bufpage.h" +#include "access/tuptoaster.h" + +#include "tsvector.h" +#include "query.h" +#include "gistidx.h" +#include "crc32.h" + +PG_FUNCTION_INFO_V1(gtsvector_in); +Datum gtsvector_in(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_out); +Datum gtsvector_out(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_compress); +Datum gtsvector_compress(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_decompress); +Datum gtsvector_decompress(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_consistent); +Datum gtsvector_consistent(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_union); +Datum gtsvector_union(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_same); +Datum gtsvector_same(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_penalty); +Datum gtsvector_penalty(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gtsvector_picksplit); +Datum gtsvector_picksplit(PG_FUNCTION_ARGS); + +#define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer(((GISTENTRY *) VARDATA(vec))[(pos)].key)) +#define SUMBIT(val) ( \ + GETBITBYTE(val,0) + \ + GETBITBYTE(val,1) + \ + GETBITBYTE(val,2) + \ + GETBITBYTE(val,3) + \ + GETBITBYTE(val,4) + \ + GETBITBYTE(val,5) + \ + GETBITBYTE(val,6) + \ + GETBITBYTE(val,7) \ +) + + +Datum +gtsvector_in(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("gtsvector_in not implemented"))); + PG_RETURN_DATUM(0); +} + +Datum +gtsvector_out(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("gtsvector_out not implemented"))); + PG_RETURN_DATUM(0); +} + +static int +compareint(const void *a, const void *b) +{ + if (*((int4 *) a) == *((int4 *) b)) + return 0; + return (*((int4 *) a) > *((int4 *) b)) ? 1 : -1; +} + +static int +uniqueint(int4 *a, int4 l) +{ + int4 *ptr, + *res; + + if (l == 1) + return l; + + ptr = res = a; + + qsort((void *) a, l, sizeof(int4), compareint); + + while (ptr - a < l) + if (*ptr != *res) + *(++res) = *ptr++; + else + ptr++; + return res + 1 - a; +} + +static void +makesign(BITVECP sign, GISTTYPE * a) +{ + int4 k, + len = ARRNELEM(a); + int4 *ptr = GETARR(a); + + MemSet((void *) sign, 0, sizeof(BITVEC)); + for (k = 0; k < len; k++) + HASH(sign, ptr[k]); +} + +Datum +gtsvector_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval = entry; + + if (entry->leafkey) + { /* tsvector */ + GISTTYPE *res; + tsvector *toastedval = (tsvector *) DatumGetPointer(entry->key); + tsvector *val = (tsvector *) DatumGetPointer(PG_DETOAST_DATUM(entry->key)); + int4 len; + int4 *arr; + WordEntry *ptr = ARRPTR(val); + char *words = STRPTR(val); + + len = CALCGTSIZE(ARRKEY, val->size); + res = (GISTTYPE *) palloc(len); + res->len = len; + res->flag = ARRKEY; + arr = GETARR(res); + len = val->size; + while (len--) + { + *arr = crc32_sz((uint8 *) &words[ptr->pos], ptr->len); + arr++; + ptr++; + } + + len = uniqueint(GETARR(res), val->size); + if (len != val->size) + { + /* + * there is a collision of hash-function; len is always less + * than val->size + */ + len = CALCGTSIZE(ARRKEY, len); + res = (GISTTYPE *) repalloc((void *) res, len); + res->len = len; + } + if (val != toastedval) + pfree(val); + + /* make signature, if array is too long */ + if (res->len > TOAST_INDEX_TARGET) + { + GISTTYPE *ressign; + + len = CALCGTSIZE(SIGNKEY, 0); + ressign = (GISTTYPE *) palloc(len); + ressign->len = len; + ressign->flag = SIGNKEY; + makesign(GETSIGN(ressign), res); + pfree(res); + res = ressign; + } + + retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); + gistentryinit(*retval, PointerGetDatum(res), + entry->rel, entry->page, + entry->offset, res->len, FALSE); + } + else if (ISSIGNKEY(DatumGetPointer(entry->key)) && + !ISALLTRUE(DatumGetPointer(entry->key))) + { + int4 i, + len; + GISTTYPE *res; + BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); + + LOOPBYTE( + if ((sign[i] & 0xff) != 0xff) + PG_RETURN_POINTER(retval); + ); + + len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0); + res = (GISTTYPE *) palloc(len); + res->len = len; + res->flag = SIGNKEY | ALLISTRUE; + + retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); + gistentryinit(*retval, PointerGetDatum(res), + entry->rel, entry->page, + entry->offset, res->len, FALSE); + } + PG_RETURN_POINTER(retval); +} + +Datum +gtsvector_decompress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTTYPE *key = (GISTTYPE *) DatumGetPointer(PG_DETOAST_DATUM(entry->key)); + + if (key != (GISTTYPE *) DatumGetPointer(entry->key)) + { + GISTENTRY *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); + + gistentryinit(*retval, PointerGetDatum(key), + entry->rel, entry->page, + entry->offset, key->len, FALSE); + + PG_RETURN_POINTER(retval); + } + + PG_RETURN_POINTER(entry); +} + +typedef struct +{ + int4 *arrb; + int4 *arre; +} CHKVAL; + +/* + * is there value 'val' in array or not ? + */ +static bool +checkcondition_arr(void *checkval, ITEM * val) +{ + int4 *StopLow = ((CHKVAL *) checkval)->arrb; + int4 *StopHigh = ((CHKVAL *) checkval)->arre; + int4 *StopMiddle; + + /* Loop invariant: StopLow <= val < StopHigh */ + + while (StopLow < StopHigh) + { + StopMiddle = StopLow + (StopHigh - StopLow) / 2; + if (*StopMiddle == val->val) + return (true); + else if (*StopMiddle < val->val) + StopLow = StopMiddle + 1; + else + StopHigh = StopMiddle; + } + + return (false); +} + +static bool +checkcondition_bit(void *checkval, ITEM * val) +{ + return GETBIT(checkval, HASHVAL(val->val)); +} + +Datum +gtsvector_consistent(PG_FUNCTION_ARGS) +{ + QUERYTYPE *query = (QUERYTYPE *) PG_GETARG_POINTER(1); + GISTTYPE *key = (GISTTYPE *) DatumGetPointer( + ((GISTENTRY *) PG_GETARG_POINTER(0))->key + ); + + if (!query->size) + PG_RETURN_BOOL(false); + + if (ISSIGNKEY(key)) + { + if (ISALLTRUE(key)) + PG_RETURN_BOOL(true); + + PG_RETURN_BOOL(TS_execute( + GETQUERY(query), + (void *) GETSIGN(key), false, + checkcondition_bit + )); + } + else + { /* only leaf pages */ + CHKVAL chkval; + + chkval.arrb = GETARR(key); + chkval.arre = chkval.arrb + ARRNELEM(key); + PG_RETURN_BOOL(TS_execute( + GETQUERY(query), + (void *) &chkval, true, + checkcondition_arr + )); + } +} + +static int4 +unionkey(BITVECP sbase, GISTTYPE * add) +{ + int4 i; + + if (ISSIGNKEY(add)) + { + BITVECP sadd = GETSIGN(add); + + if (ISALLTRUE(add)) + return 1; + + LOOPBYTE( + sbase[i] |= sadd[i]; + ); + } + else + { + int4 *ptr = GETARR(add); + + for (i = 0; i < ARRNELEM(add); i++) + HASH(sbase, ptr[i]); + } + return 0; +} + + +Datum +gtsvector_union(PG_FUNCTION_ARGS) +{ + bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); + int *size = (int *) PG_GETARG_POINTER(1); + BITVEC base; + int4 len = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); + int4 i; + int4 flag = 0; + GISTTYPE *result; + + MemSet((void *) base, 0, sizeof(BITVEC)); + for (i = 0; i < len; i++) + { + if (unionkey(base, GETENTRY(entryvec, i))) + { + flag = ALLISTRUE; + break; + } + } + + flag |= SIGNKEY; + len = CALCGTSIZE(flag, 0); + result = (GISTTYPE *) palloc(len); + *size = result->len = len; + result->flag = flag; + if (!ISALLTRUE(result)) + memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC)); + + PG_RETURN_POINTER(result); +} + +Datum +gtsvector_same(PG_FUNCTION_ARGS) +{ + GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0); + GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (ISSIGNKEY(a)) + { /* then b also ISSIGNKEY */ + if (ISALLTRUE(a) && ISALLTRUE(b)) + *result = true; + else if (ISALLTRUE(a)) + *result = false; + else if (ISALLTRUE(b)) + *result = false; + else + { + int4 i; + BITVECP sa = GETSIGN(a), + sb = GETSIGN(b); + + *result = true; + LOOPBYTE( + if (sa[i] != sb[i]) + { + *result = false; + break; + } + ); + } + } + else + { /* a and b ISARRKEY */ + int4 lena = ARRNELEM(a), + lenb = ARRNELEM(b); + + if (lena != lenb) + *result = false; + else + { + int4 *ptra = GETARR(a), + *ptrb = GETARR(b); + int4 i; + + *result = true; + for (i = 0; i < lena; i++) + if (ptra[i] != ptrb[i]) + { + *result = false; + break; + } + } + } + + PG_RETURN_POINTER(result); +} + +static int4 +sizebitvec(BITVECP sign) +{ + int4 size = 0, + i; + + LOOPBYTE( + size += SUMBIT(*(char *) sign); + sign = (BITVECP) (((char *) sign) + 1); + ); + return size; +} + +static int +hemdistsign(BITVECP a, BITVECP b) { + int i,dist=0; + + LOOPBIT( + if ( GETBIT(a,i) != GETBIT(b,i) ) + dist++; + ); + return dist; +} + +static int +hemdist(GISTTYPE *a, GISTTYPE *b) { + if ( ISALLTRUE(a) ) { + if (ISALLTRUE(b)) + return 0; + else + return SIGLENBIT-sizebitvec(GETSIGN(b)); + } else if (ISALLTRUE(b)) + return SIGLENBIT-sizebitvec(GETSIGN(a)); + + return hemdistsign( GETSIGN(a), GETSIGN(b) ); +} + +Datum +gtsvector_penalty(PG_FUNCTION_ARGS) +{ + GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */ + GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); + float *penalty = (float *) PG_GETARG_POINTER(2); + GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key); + GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key); + BITVECP orig = GETSIGN(origval); + + *penalty = 0.0; + + if (ISARRKEY(newval)) { + BITVEC sign; + makesign(sign, newval); + + if ( ISALLTRUE(origval) ) + *penalty=((float)(SIGLENBIT-sizebitvec(sign)))/(float)(SIGLENBIT+1); + else + *penalty=hemdistsign(sign,orig); + } else { + *penalty=hemdist(origval,newval); + } + PG_RETURN_POINTER(penalty); +} + +typedef struct +{ + bool allistrue; + BITVEC sign; +} CACHESIGN; + +static void +fillcache(CACHESIGN * item, GISTTYPE * key) +{ + item->allistrue = false; + if (ISARRKEY(key)) + makesign(item->sign, key); + else if (ISALLTRUE(key)) + item->allistrue = true; + else + memcpy((void *) item->sign, (void *) GETSIGN(key), sizeof(BITVEC)); +} + +#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) ) +typedef struct +{ + OffsetNumber pos; + int4 cost; +} SPLITCOST; + +static int +comparecost(const void *a, const void *b) +{ + if (((SPLITCOST *) a)->cost == ((SPLITCOST *) b)->cost) + return 0; + else + return (((SPLITCOST *) a)->cost > ((SPLITCOST *) b)->cost) ? 1 : -1; +} + + +static int +hemdistcache(CACHESIGN *a, CACHESIGN *b) { + if ( a->allistrue ) { + if (b->allistrue) + return 0; + else + return SIGLENBIT-sizebitvec(b->sign); + } else if (b->allistrue) + return SIGLENBIT-sizebitvec(a->sign); + + return hemdistsign( a->sign, b->sign ); +} + +Datum +gtsvector_picksplit(PG_FUNCTION_ARGS) +{ + bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); + GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); + OffsetNumber k, + j; + GISTTYPE *datum_l, + *datum_r; + BITVECP union_l, + union_r; + int4 size_alpha, + size_beta; + int4 size_waste, + waste = -1; + int4 nbytes; + OffsetNumber seed_1 = 0, + seed_2 = 0; + OffsetNumber *left, + *right; + OffsetNumber maxoff; + BITVECP ptr; + int i; + CACHESIGN *cache; + SPLITCOST *costvector; + + maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 2; + nbytes = (maxoff + 2) * sizeof(OffsetNumber); + v->spl_left = (OffsetNumber *) palloc(nbytes); + v->spl_right = (OffsetNumber *) palloc(nbytes); + + cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2)); + fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber)); + + for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k)) { + for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j)) { + if (k == FirstOffsetNumber) + fillcache(&cache[j], GETENTRY(entryvec, j)); + + size_waste=hemdistcache(&(cache[j]),&(cache[k])); + if (size_waste > waste) { + waste = size_waste; + seed_1 = k; + seed_2 = j; + } + } + } + + left = v->spl_left; + v->spl_nleft = 0; + right = v->spl_right; + v->spl_nright = 0; + + if (seed_1 == 0 || seed_2 == 0) { + seed_1 = 1; + seed_2 = 2; + } + + /* form initial .. */ + if (cache[seed_1].allistrue) { + datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0)); + datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0); + datum_l->flag = SIGNKEY | ALLISTRUE; + } else { + datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0)); + datum_l->len = CALCGTSIZE(SIGNKEY, 0); + datum_l->flag = SIGNKEY; + memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC)); + } + if (cache[seed_2].allistrue) { + datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0)); + datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0); + datum_r->flag = SIGNKEY | ALLISTRUE; + } else { + datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0)); + datum_r->len = CALCGTSIZE(SIGNKEY, 0); + datum_r->flag = SIGNKEY; + memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC)); + } + + union_l=GETSIGN(datum_l); + union_r=GETSIGN(datum_r); + maxoff = OffsetNumberNext(maxoff); + fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff)); + /* sort before ... */ + costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff); + for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j)) { + costvector[j - 1].pos = j; + size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j])); + size_beta = hemdistcache(&(cache[seed_2]), &(cache[j])); + costvector[j - 1].cost = abs(size_alpha - size_beta); + } + qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost); + + for (k = 0; k < maxoff; k++) { + j = costvector[k].pos; + if (j == seed_1) { + *left++ = j; + v->spl_nleft++; + continue; + } else if (j == seed_2) { + *right++ = j; + v->spl_nright++; + continue; + } + + if (ISALLTRUE(datum_l) || cache[j].allistrue) { + if ( ISALLTRUE(datum_l) && cache[j].allistrue ) + size_alpha=0; + else + size_alpha = SIGLENBIT-sizebitvec( + ( cache[j].allistrue ) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign) + ); + } else { + size_alpha=hemdistsign(cache[j].sign,GETSIGN(datum_l)); + } + + if (ISALLTRUE(datum_r) || cache[j].allistrue) { + if ( ISALLTRUE(datum_r) && cache[j].allistrue ) + size_beta=0; + else + size_beta = SIGLENBIT-sizebitvec( + ( cache[j].allistrue ) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign) + ); + } else { + size_beta=hemdistsign(cache[j].sign,GETSIGN(datum_r)); + } + + if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1)) { + if (ISALLTRUE(datum_l) || cache[j].allistrue) { + if (! ISALLTRUE(datum_l) ) + MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC)); + } else { + ptr=cache[j].sign; + LOOPBYTE( + union_l[i] |= ptr[i]; + ); + } + *left++ = j; + v->spl_nleft++; + } else { + if (ISALLTRUE(datum_r) || cache[j].allistrue) { + if (! ISALLTRUE(datum_r) ) + MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC)); + } else { + ptr=cache[j].sign; + LOOPBYTE( + union_r[i] |= ptr[i]; + ); + } + *right++ = j; + v->spl_nright++; + } + } + + *right = *left = FirstOffsetNumber; + pfree(costvector); + pfree(cache); + v->spl_ldatum = PointerGetDatum(datum_l); + v->spl_rdatum = PointerGetDatum(datum_r); + + PG_RETURN_POINTER(v); +} diff --git a/contrib/tsearch2/gistidx.h b/contrib/tsearch2/gistidx.h new file mode 100644 index 0000000..d081c74 --- /dev/null +++ b/contrib/tsearch2/gistidx.h @@ -0,0 +1,67 @@ +#ifndef __GISTIDX_H__ +#define __GISTIDX_H__ + +/* +#define GISTIDX_DEBUG +*/ + +/* + * signature defines + */ + +#define BITBYTE 8 +#define SIGLENINT 63 /* >121 => key will toast, so it will not + * work !!! */ +#define SIGLEN ( sizeof(int4)*SIGLENINT ) +#define SIGLENBIT (SIGLEN*BITBYTE) + +typedef char BITVEC[SIGLEN]; +typedef char *BITVECP; + +#define LOOPBYTE(a) \ + for(i=0;i> i & 0x01 ) +#define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) ) +#define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITBYTE ) ) +#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 ) + +#define abs(a) ((a) < (0) ? -(a) : (a)) +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT) +#define HASH(sign, val) SETBIT((sign), HASHVAL(val)) + + +/* + * type of index key + */ +typedef struct +{ + int4 len; + int4 flag; + char data[1]; +} GISTTYPE; + +#define ARRKEY 0x01 +#define SIGNKEY 0x02 +#define ALLISTRUE 0x04 + +#define ISARRKEY(x) ( ((GISTTYPE*)x)->flag & ARRKEY ) +#define ISSIGNKEY(x) ( ((GISTTYPE*)x)->flag & SIGNKEY ) +#define ISALLTRUE(x) ( ((GISTTYPE*)x)->flag & ALLISTRUE ) + +#define GTHDRSIZE ( sizeof(int4)*2 ) +#define CALCGTSIZE(flag, len) ( GTHDRSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(int4)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) ) + +#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) ) +#define GETARR(x) ( (int4*)( (char*)x+GTHDRSIZE ) ) +#define ARRNELEM(x) ( ( ((GISTTYPE*)x)->len - GTHDRSIZE )/sizeof(int4) ) + +#endif diff --git a/contrib/tsearch2/ispell/spell.c b/contrib/tsearch2/ispell/spell.c new file mode 100644 index 0000000..45786cc --- /dev/null +++ b/contrib/tsearch2/ispell/spell.c @@ -0,0 +1,656 @@ +#include +#include +#include +#include + +#include "postgres.h" + +#include "spell.h" + +#define MAXNORMLEN 56 + +#define STRNCASECMP(x,y) (strncasecmp(x,y,strlen(y))) + +static int +cmpspell(const void *s1, const void *s2) +{ + return (strcmp(((const SPELL *) s1)->word, ((const SPELL *) s2)->word)); +} + +static void +strlower(char *str) +{ + unsigned char *ptr = (unsigned char *) str; + + while (*ptr) + { + *ptr = tolower(*ptr); + ptr++; + } +} + +/* backward string compaire for suffix tree operations */ +static int +strbcmp(const char *s1, const char *s2) +{ + int l1 = strlen(s1) - 1, + l2 = strlen(s2) - 1; + + while (l1 >= 0 && l2 >= 0) + { + if (s1[l1] < s2[l2]) + return -1; + if (s1[l1] > s2[l2]) + return 1; + l1--; + l2--; + } + if (l1 < l2) + return -1; + if (l1 > l2) + return 1; + + return 0; +} +static int +strbncmp(const char *s1, const char *s2, size_t count) +{ + int l1 = strlen(s1) - 1, + l2 = strlen(s2) - 1, + l = count; + + while (l1 >= 0 && l2 >= 0 && l > 0) + { + if (s1[l1] < s2[l2]) + return -1; + if (s1[l1] > s2[l2]) + return 1; + l1--; + l2--; + l--; + } + if (l == 0) + return 0; + if (l1 < l2) + return -1; + if (l1 > l2) + return 1; + return 0; +} + +static int +cmpaffix(const void *s1, const void *s2) +{ + if (((const AFFIX *) s1)->type < ((const AFFIX *) s2)->type) + return -1; + if (((const AFFIX *) s1)->type > ((const AFFIX *) s2)->type) + return 1; + if (((const AFFIX *) s1)->type == 'p') + return (strcmp(((const AFFIX *) s1)->repl, ((const AFFIX *) s2)->repl)); + else + return (strbcmp(((const AFFIX *) s1)->repl, ((const AFFIX *) s2)->repl)); +} + +int +AddSpell(IspellDict * Conf, const char *word, const char *flag) +{ + if (Conf->nspell >= Conf->mspell) + { + if (Conf->mspell) + { + Conf->mspell += 1024 * 20; + Conf->Spell = (SPELL *) realloc(Conf->Spell, Conf->mspell * sizeof(SPELL)); + } + else + { + Conf->mspell = 1024 * 20; + Conf->Spell = (SPELL *) malloc(Conf->mspell * sizeof(SPELL)); + } + if (Conf->Spell == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + Conf->Spell[Conf->nspell].word = strdup(word); + if (!Conf->Spell[Conf->nspell].word) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + strncpy(Conf->Spell[Conf->nspell].flag, flag, 10); + Conf->nspell++; + return (0); +} + + +int +ImportDictionary(IspellDict * Conf, const char *filename) +{ + unsigned char str[BUFSIZ]; + FILE *dict; + + if (!(dict = fopen(filename, "r"))) + return (1); + while (fgets(str, sizeof(str), dict)) + { + unsigned char *s; + const unsigned char *flag; + + flag = NULL; + if ((s = strchr(str, '/'))) + { + *s = 0; + s++; + flag = s; + while (*s) + { + if (((*s >= 'A') && (*s <= 'Z')) || ((*s >= 'a') && (*s <= 'z'))) + s++; + else + { + *s = 0; + break; + } + } + } + else + flag = ""; + strlower(str); + /* Dont load words if first letter is not required */ + /* It allows to optimize loading at search time */ + s = str; + while (*s) + { + if (*s == '\r') + *s = 0; + if (*s == '\n') + *s = 0; + s++; + } + AddSpell(Conf, str, flag); + } + fclose(dict); + return (0); +} + + +static SPELL * +FindWord(IspellDict * Conf, const char *word, int affixflag) +{ + int l, + c, + r, + resc, + resl, + resr, + i; + + i = (int) (*word) & 255; + l = Conf->SpellTree.Left[i]; + r = Conf->SpellTree.Right[i]; + if (l == -1) + return (NULL); + while (l <= r) + { + c = (l + r) >> 1; + resc = strcmp(Conf->Spell[c].word, word); + if ((resc == 0) && + ((affixflag == 0) || (strchr(Conf->Spell[c].flag, affixflag) != NULL))) + return (&Conf->Spell[c]); + resl = strcmp(Conf->Spell[l].word, word); + if ((resl == 0) && + ((affixflag == 0) || (strchr(Conf->Spell[l].flag, affixflag) != NULL))) + return (&Conf->Spell[l]); + resr = strcmp(Conf->Spell[r].word, word); + if ((resr == 0) && + ((affixflag == 0) || (strchr(Conf->Spell[r].flag, affixflag) != NULL))) + return (&Conf->Spell[r]); + if (resc < 0) + { + l = c + 1; + r--; + } + else if (resc > 0) + { + r = c - 1; + l++; + } + else + { + l++; + r--; + } + } + return (NULL); +} + +int +AddAffix(IspellDict * Conf, int flag, const char *mask, const char *find, const char *repl, int type) +{ + if (Conf->naffixes >= Conf->maffixes) + { + if (Conf->maffixes) + { + Conf->maffixes += 16; + Conf->Affix = (AFFIX *) realloc((void *) Conf->Affix, Conf->maffixes * sizeof(AFFIX)); + } + else + { + Conf->maffixes = 16; + Conf->Affix = (AFFIX *) malloc(Conf->maffixes * sizeof(AFFIX)); + } + if (Conf->Affix == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + if (type == 's') + sprintf(Conf->Affix[Conf->naffixes].mask, "%s$", mask); + else + sprintf(Conf->Affix[Conf->naffixes].mask, "^%s", mask); + Conf->Affix[Conf->naffixes].compile = 1; + Conf->Affix[Conf->naffixes].flag = flag; + Conf->Affix[Conf->naffixes].type = type; + + strcpy(Conf->Affix[Conf->naffixes].find, find); + strcpy(Conf->Affix[Conf->naffixes].repl, repl); + Conf->Affix[Conf->naffixes].replen = strlen(repl); + Conf->naffixes++; + return (0); +} + +static char * +remove_spaces(char *dist, char *src) +{ + char *d, + *s; + + d = dist; + s = src; + while (*s) + { + if (*s != ' ' && *s != '-' && *s != '\t') + { + *d = *s; + d++; + } + s++; + } + *d = 0; + return (dist); +} + + +int +ImportAffixes(IspellDict * Conf, const char *filename) +{ + unsigned char str[BUFSIZ]; + unsigned char flag = 0; + unsigned char mask[BUFSIZ] = ""; + unsigned char find[BUFSIZ] = ""; + unsigned char repl[BUFSIZ] = ""; + unsigned char *s; + int i; + int suffixes = 0; + int prefixes = 0; + FILE *affix; + + if (!(affix = fopen(filename, "r"))) + return (1); + + while (fgets(str, sizeof(str), affix)) + { + if (!STRNCASECMP(str, "suffixes")) + { + suffixes = 1; + prefixes = 0; + continue; + } + if (!STRNCASECMP(str, "prefixes")) + { + suffixes = 0; + prefixes = 1; + continue; + } + if (!STRNCASECMP(str, "flag ")) + { + s = str + 5; + while (strchr("* ", *s)) + s++; + flag = *s; + continue; + } + if ((!suffixes) && (!prefixes)) + continue; + if ((s = strchr(str, '#'))) + *s = 0; + if (!*str) + continue; + strlower(str); + strcpy(mask, ""); + strcpy(find, ""); + strcpy(repl, ""); + i = sscanf(str, "%[^>\n]>%[^,\n],%[^\n]", mask, find, repl); + remove_spaces(str, repl); + strcpy(repl, str); + remove_spaces(str, find); + strcpy(find, str); + remove_spaces(str, mask); + strcpy(mask, str); + switch (i) + { + case 3: + break; + case 2: + if (*find != '\0') + { + strcpy(repl, find); + strcpy(find, ""); + } + break; + default: + continue; + } + + AddAffix(Conf, (int) flag, mask, find, repl, suffixes ? 's' : 'p'); + + } + fclose(affix); + + return (0); +} + +void +SortDictionary(IspellDict * Conf) +{ + int CurLet = -1, + Let; + size_t i; + + qsort((void *) Conf->Spell, Conf->nspell, sizeof(SPELL), cmpspell); + + for (i = 0; i < 256; i++) + Conf->SpellTree.Left[i] = -1; + + for (i = 0; i < Conf->nspell; i++) + { + Let = (int) (*(Conf->Spell[i].word)) & 255; + if (CurLet != Let) + { + Conf->SpellTree.Left[Let] = i; + CurLet = Let; + } + Conf->SpellTree.Right[Let] = i; + } +} + +void +SortAffixes(IspellDict * Conf) +{ + int CurLetP = -1, + CurLetS = -1, + Let; + AFFIX *Affix; + size_t i; + + if (Conf->naffixes > 1) + qsort((void *) Conf->Affix, Conf->naffixes, sizeof(AFFIX), cmpaffix); + for (i = 0; i < 256; i++) + { + Conf->PrefixTree.Left[i] = Conf->PrefixTree.Right[i] = -1; + Conf->SuffixTree.Left[i] = Conf->SuffixTree.Right[i] = -1; + } + + for (i = 0; i < Conf->naffixes; i++) + { + Affix = &(((AFFIX *) Conf->Affix)[i]); + if (Affix->type == 'p') + { + Let = (int) (*(Affix->repl)) & 255; + if (CurLetP != Let) + { + Conf->PrefixTree.Left[Let] = i; + CurLetP = Let; + } + Conf->PrefixTree.Right[Let] = i; + } + else + { + Let = (Affix->replen) ? (int) (Affix->repl[Affix->replen - 1]) & 255 : 0; + if (CurLetS != Let) + { + Conf->SuffixTree.Left[Let] = i; + CurLetS = Let; + } + Conf->SuffixTree.Right[Let] = i; + } + } +} + +static char * +CheckSuffix(const char *word, size_t len, AFFIX * Affix, int *res, IspellDict * Conf) +{ + regmatch_t subs[2]; /* workaround for apache&linux */ + char newword[2 * MAXNORMLEN] = ""; + int err; + + *res = strbncmp(word, Affix->repl, Affix->replen); + if (*res < 0) + return NULL; + if (*res > 0) + return NULL; + strcpy(newword, word); + strcpy(newword + len - Affix->replen, Affix->find); + + if (Affix->compile) + { + err = regcomp(&(Affix->reg), Affix->mask, REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (err) + { + /* regerror(err, &(Affix->reg), regerrstr, ERRSTRSIZE); */ + regfree(&(Affix->reg)); + return (NULL); + } + Affix->compile = 0; + } + if (!(err = regexec(&(Affix->reg), newword, 1, subs, 0))) + { + if (FindWord(Conf, newword, Affix->flag)) + return pstrdup(newword); + } + return NULL; +} + +#define NS 1 +#define MAX_NORM 512 +static int +CheckPrefix(const char *word, size_t len, AFFIX * Affix, IspellDict * Conf, int pi, + char **forms, char ***cur) +{ + regmatch_t subs[NS * 2]; + char newword[2 * MAXNORMLEN] = ""; + int err, + ls, + res, + lres; + size_t newlen; + AFFIX *CAffix = Conf->Affix; + + res = strncmp(word, Affix->repl, Affix->replen); + if (res != 0) + return res; + strcpy(newword, Affix->find); + strcat(newword, word + Affix->replen); + + if (Affix->compile) + { + err = regcomp(&(Affix->reg), Affix->mask, REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (err) + { + /* regerror(err, &(Affix->reg), regerrstr, ERRSTRSIZE); */ + regfree(&(Affix->reg)); + return (0); + } + Affix->compile = 0; + } + if (!(err = regexec(&(Affix->reg), newword, 1, subs, 0))) + { + SPELL *curspell; + + if ((curspell = FindWord(Conf, newword, Affix->flag))) + { + if ((*cur - forms) < (MAX_NORM - 1)) + { + **cur = pstrdup(newword); + (*cur)++; + **cur = NULL; + } + } + newlen = strlen(newword); + ls = Conf->SuffixTree.Left[pi]; + if (ls >= 0 && ((*cur - forms) < (MAX_NORM - 1))) + { + **cur = CheckSuffix(newword, newlen, &CAffix[ls], &lres, Conf); + if (**cur) + { + (*cur)++; + **cur = NULL; + } + } + } + return 0; +} + + +char ** +NormalizeWord(IspellDict * Conf, char *word) +{ +/*regmatch_t subs[NS];*/ + size_t len; + char **forms; + char **cur; + AFFIX *Affix; + int ri, + pi, + ipi, + lp, + rp, + cp, + ls, + rs; + int lres, + rres, + cres = 0; + SPELL *spell; + + len = strlen(word); + if (len > MAXNORMLEN) + return (NULL); + + strlower(word); + + forms = (char **) palloc(MAX_NORM * sizeof(char **)); + cur = forms; + *cur = NULL; + + ri = (int) (*word) & 255; + pi = (int) (word[strlen(word) - 1]) & 255; + Affix = (AFFIX *) Conf->Affix; + + /* Check that the word itself is normal form */ + if ((spell = FindWord(Conf, word, 0))) + { + *cur = pstrdup(word); + cur++; + *cur = NULL; + } + + /* Find all other NORMAL forms of the 'word' */ + + for (ipi = 0; ipi <= pi; ipi += pi) + { + + /* check prefix */ + lp = Conf->PrefixTree.Left[ri]; + rp = Conf->PrefixTree.Right[ri]; + while (lp >= 0 && lp <= rp) + { + cp = (lp + rp) >> 1; + cres = 0; + if ((cur - forms) < (MAX_NORM - 1)) + cres = CheckPrefix(word, len, &Affix[cp], Conf, ipi, forms, &cur); + if ((lp < cp) && ((cur - forms) < (MAX_NORM - 1))) + lres = CheckPrefix(word, len, &Affix[lp], Conf, ipi, forms, &cur); + if ((rp > cp) && ((cur - forms) < (MAX_NORM - 1))) + rres = CheckPrefix(word, len, &Affix[rp], Conf, ipi, forms, &cur); + if (cres < 0) + { + rp = cp - 1; + lp++; + } + else if (cres > 0) + { + lp = cp + 1; + rp--; + } + else + { + lp++; + rp--; + } + } + + /* check suffix */ + ls = Conf->SuffixTree.Left[ipi]; + rs = Conf->SuffixTree.Right[ipi]; + while (ls >= 0 && ls <= rs) + { + if (((cur - forms) < (MAX_NORM - 1))) + { + *cur = CheckSuffix(word, len, &Affix[ls], &lres, Conf); + if (*cur) + { + cur++; + *cur = NULL; + } + } + if ((rs > ls) && ((cur - forms) < (MAX_NORM - 1))) + { + *cur = CheckSuffix(word, len, &Affix[rs], &rres, Conf); + if (*cur) + { + cur++; + *cur = NULL; + } + } + ls++; + rs--; + } /* end while */ + + } /* for ipi */ + + if (cur == forms) + { + pfree(forms); + return (NULL); + } + return (forms); +} + +void +FreeIspell(IspellDict * Conf) +{ + int i; + AFFIX *Affix = (AFFIX *) Conf->Affix; + + for (i = 0; i < Conf->naffixes; i++) + { + if (Affix[i].compile == 0) + regfree(&(Affix[i].reg)); + } + for (i = 0; i < Conf->naffixes; i++) + free(Conf->Spell[i].word); + free(Conf->Affix); + free(Conf->Spell); + memset((void *) Conf, 0, sizeof(IspellDict)); + return; +} diff --git a/contrib/tsearch2/ispell/spell.h b/contrib/tsearch2/ispell/spell.h new file mode 100644 index 0000000..baf5052 --- /dev/null +++ b/contrib/tsearch2/ispell/spell.h @@ -0,0 +1,56 @@ +#ifndef __SPELL_H__ +#define __SPELL_H__ + +#include +#include + +typedef struct spell_struct +{ + char *word; + char flag[10]; +} SPELL; + +typedef struct aff_struct +{ + char flag; + char type; + char mask[33]; + char find[16]; + char repl[16]; + regex_t reg; + size_t replen; + char compile; +} AFFIX; + +typedef struct Tree_struct +{ + int Left[256], + Right[256]; +} Tree_struct; + +typedef struct +{ + int maffixes; + int naffixes; + AFFIX *Affix; + + int nspell; + int mspell; + SPELL *Spell; + Tree_struct SpellTree; + Tree_struct PrefixTree; + Tree_struct SuffixTree; + +} IspellDict; + +char **NormalizeWord(IspellDict * Conf, char *word); +int ImportAffixes(IspellDict * Conf, const char *filename); +int ImportDictionary(IspellDict * Conf, const char *filename); + +int AddSpell(IspellDict * Conf, const char *word, const char *flag); +int AddAffix(IspellDict * Conf, int flag, const char *mask, const char *find, const char *repl, int type); +void SortDictionary(IspellDict * Conf); +void SortAffixes(IspellDict * Conf); +void FreeIspell(IspellDict * Conf); + +#endif diff --git a/contrib/tsearch2/prs_dcfg.c b/contrib/tsearch2/prs_dcfg.c new file mode 100644 index 0000000..6b553e4 --- /dev/null +++ b/contrib/tsearch2/prs_dcfg.c @@ -0,0 +1,179 @@ +/* + * Simple config parser + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" + +#include "dict.h" +#include "common.h" + +#define CS_WAITKEY 0 +#define CS_INKEY 1 +#define CS_WAITEQ 2 +#define CS_WAITVALUE 3 +#define CS_INVALUE 4 +#define CS_IN2VALUE 5 +#define CS_WAITDELIM 6 +#define CS_INESC 7 +#define CS_IN2ESC 8 + +static char * +nstrdup(char *ptr, int len) +{ + char *res = palloc(len + 1), + *cptr; + + memcpy(res, ptr, len); + res[len] = '\0'; + cptr = ptr = res; + while (*ptr) + { + if (*ptr == '\\') + ptr++; + *cptr = *ptr; + ptr++; + cptr++; + } + *cptr = '\0'; + + return res; +} + +void +parse_cfgdict(text *in, Map ** m) +{ + Map *mptr; + char *ptr = VARDATA(in), + *begin = NULL; + char num = 0; + int state = CS_WAITKEY; + + while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ) + { + if (*ptr == ',') + num++; + ptr++; + } + + *m = mptr = (Map *) palloc(sizeof(Map) * (num + 2)); + memset(mptr, 0, sizeof(Map) * (num + 2)); + ptr = VARDATA(in); + while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ) + { + if (state == CS_WAITKEY) + { + if (isalpha(*ptr)) + { + begin = ptr; + state = CS_INKEY; + } + else if (!isspace(*ptr)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Syntax error in position %d near \"%c\"", + (int) (ptr - VARDATA(in)), *ptr))); + } + else if (state == CS_INKEY) + { + if (isspace(*ptr)) + { + mptr->key = nstrdup(begin, ptr - begin); + state = CS_WAITEQ; + } + else if (*ptr == '=') + { + mptr->key = nstrdup(begin, ptr - begin); + state = CS_WAITVALUE; + } + else if (!isalpha(*ptr)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Syntax error in position %d near \"%c\"", + (int) (ptr - VARDATA(in)), *ptr))); + } + else if (state == CS_WAITEQ) + { + if (*ptr == '=') + state = CS_WAITVALUE; + else if (!isspace(*ptr)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Syntax error in position %d near \"%c\"", + (int) (ptr - VARDATA(in)), *ptr))); + } + else if (state == CS_WAITVALUE) + { + if (*ptr == '"') + { + begin = ptr + 1; + state = CS_INVALUE; + } + else if (!isspace(*ptr)) + { + begin = ptr; + state = CS_IN2VALUE; + } + } + else if (state == CS_INVALUE) + { + if (*ptr == '"') + { + mptr->value = nstrdup(begin, ptr - begin); + mptr++; + state = CS_WAITDELIM; + } + else if (*ptr == '\\') + state = CS_INESC; + } + else if (state == CS_IN2VALUE) + { + if (isspace(*ptr) || *ptr == ',') + { + mptr->value = nstrdup(begin, ptr - begin); + mptr++; + state = (*ptr == ',') ? CS_WAITKEY : CS_WAITDELIM; + } + else if (*ptr == '\\') + state = CS_INESC; + } + else if (state == CS_WAITDELIM) + { + if (*ptr == ',') + state = CS_WAITKEY; + else if (!isspace(*ptr)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Syntax error in position %d near \"%c\"", + (int) (ptr - VARDATA(in)), *ptr))); + } + else if (state == CS_INESC) + state = CS_INVALUE; + else if (state == CS_IN2ESC) + state = CS_IN2VALUE; + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad parser state"), + errdetail("%d at position %d near \"%c\"", + state, (int) (ptr - VARDATA(in)), *ptr))); + ptr++; + } + + if (state == CS_IN2VALUE) + { + mptr->value = nstrdup(begin, ptr - begin); + mptr++; + } + else if (!(state == CS_WAITDELIM || state == CS_WAITKEY)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unexpected end of line"))); +} diff --git a/contrib/tsearch2/rank.c b/contrib/tsearch2/rank.c new file mode 100644 index 0000000..5b62c98 --- /dev/null +++ b/contrib/tsearch2/rank.c @@ -0,0 +1,709 @@ +/* + * Relevation + * Teodor Sigaev + */ +#include "postgres.h" +#include + +#include "access/gist.h" +#include "access/itup.h" +#include "utils/builtins.h" +#include "fmgr.h" +#include "funcapi.h" +#include "storage/bufpage.h" +#include "executor/spi.h" +#include "commands/trigger.h" +#include "nodes/pg_list.h" +#include "catalog/namespace.h" + +#include "utils/array.h" + +#include "tsvector.h" +#include "query.h" +#include "common.h" + +PG_FUNCTION_INFO_V1(rank); +Datum rank(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(rank_def); +Datum rank_def(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(rank_cd); +Datum rank_cd(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(rank_cd_def); +Datum rank_cd_def(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(get_covers); +Datum get_covers(PG_FUNCTION_ARGS); + +static float weights[] = {0.1, 0.2, 0.4, 1.0}; + +#define wpos(wep) ( w[ ((WordEntryPos*)(wep))->weight ] ) + +#define DEF_NORM_METHOD 0 + +/* + * Returns a weight of a word collocation + */ +static float4 +word_distance(int4 w) +{ + if (w > 100) + return 1e-30; + + return 1.0 / (1.005 + 0.05 * exp(((float4) w) / 1.5 - 2)); +} + +static int +cnt_length(tsvector * t) +{ + WordEntry *ptr = ARRPTR(t), + *end = (WordEntry *) STRPTR(t); + int len = 0, + clen; + + while (ptr < end) + { + if ((clen = POSDATALEN(t, ptr)) == 0) + len += 1; + else + len += clen; + ptr++; + } + + return len; +} + +static int4 +WordECompareITEM(char *eval, char *qval, WordEntry * ptr, ITEM * item) +{ + if (ptr->len == item->length) + return strncmp( + eval + ptr->pos, + qval + item->distance, + item->length); + + return (ptr->len > item->length) ? 1 : -1; +} + +static WordEntry * +find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item) +{ + WordEntry *StopLow = ARRPTR(t); + WordEntry *StopHigh = (WordEntry *) STRPTR(t); + WordEntry *StopMiddle; + int difference; + + /* Loop invariant: StopLow <= item < StopHigh */ + + while (StopLow < StopHigh) + { + StopMiddle = StopLow + (StopHigh - StopLow) / 2; + difference = WordECompareITEM(STRPTR(t), GETOPERAND(q), StopMiddle, item); + if (difference == 0) + return StopMiddle; + else if (difference < 0) + StopLow = StopMiddle + 1; + else + StopHigh = StopMiddle; + } + + return NULL; +} + +static WordEntryPos POSNULL[] = { + {0, 0}, + {0, MAXENTRYPOS - 1} +}; + +static float +calc_rank_and(float *w, tsvector * t, QUERYTYPE * q) +{ + uint16 **pos = (uint16 **) palloc(sizeof(uint16 *) * q->size); + int i, + k, + l, + p; + WordEntry *entry; + WordEntryPos *post, + *ct; + int4 dimt, + lenct, + dist; + float res = -1.0; + ITEM *item = GETQUERY(q); + + memset(pos, 0, sizeof(uint16 **) * q->size); + *(uint16 *) POSNULL = lengthof(POSNULL) - 1; + + for (i = 0; i < q->size; i++) + { + + if (item[i].type != VAL) + continue; + + entry = find_wordentry(t, q, &(item[i])); + if (!entry) + continue; + + if (entry->haspos) + pos[i] = (uint16 *) _POSDATAPTR(t, entry); + else + pos[i] = (uint16 *) POSNULL; + + + dimt = *(uint16 *) (pos[i]); + post = (WordEntryPos *) (pos[i] + 1); + for (k = 0; k < i; k++) + { + if (!pos[k]) + continue; + lenct = *(uint16 *) (pos[k]); + ct = (WordEntryPos *) (pos[k] + 1); + for (l = 0; l < dimt; l++) + { + for (p = 0; p < lenct; p++) + { + dist = abs(post[l].pos - ct[p].pos); + if (dist || (dist == 0 && (pos[i] == (uint16 *) POSNULL || pos[k] == (uint16 *) POSNULL))) + { + float curw; + + if (!dist) + dist = MAXENTRYPOS; + curw = sqrt(wpos(&(post[l])) * wpos(&(ct[p])) * word_distance(dist)); + res = (res < 0) ? curw : 1.0 - (1.0 - res) * (1.0 - curw); + } + } + } + } + } + pfree(pos); + return res; +} + +static float +calc_rank_or(float *w, tsvector * t, QUERYTYPE * q) +{ + WordEntry *entry; + WordEntryPos *post; + int4 dimt, + j, + i; + float res = -1.0; + ITEM *item = GETQUERY(q); + + *(uint16 *) POSNULL = lengthof(POSNULL) - 1; + + for (i = 0; i < q->size; i++) + { + if (item[i].type != VAL) + continue; + + entry = find_wordentry(t, q, &(item[i])); + if (!entry) + continue; + + if (entry->haspos) + { + dimt = POSDATALEN(t, entry); + post = POSDATAPTR(t, entry); + } + else + { + dimt = *(uint16 *) POSNULL; + post = POSNULL + 1; + } + + for (j = 0; j < dimt; j++) + { + if (res < 0) + res = wpos(&(post[j])); + else + res = 1.0 - (1.0 - res) * (1.0 - wpos(&(post[j]))); + } + } + return res; +} + +static float +calc_rank(float *w, tsvector * t, QUERYTYPE * q, int4 method) +{ + ITEM *item = GETQUERY(q); + float res = 0.0; + + if (!t->size || !q->size) + return 0.0; + + res = (item->type != VAL && item->val == (int4) '&') ? + calc_rank_and(w, t, q) : calc_rank_or(w, t, q); + + if (res < 0) + res = 1e-20; + + switch (method) + { + case 0: + break; + case 1: + res /= log((float) cnt_length(t)); + break; + case 2: + res /= (float) cnt_length(t); + break; + default: + /* internal error */ + elog(ERROR, "unrecognized normalization method: %d", method); + } + + return res; +} + +Datum +rank(PG_FUNCTION_ARGS) +{ + ArrayType *win = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + tsvector *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_DATUM(2)); + int method = DEF_NORM_METHOD; + float res = 0.0; + float ws[lengthof(weights)]; + int i; + + if (ARR_NDIM(win) != 1) + ereport(ERROR, + (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("array of weight must be one-dimensional"))); + + if (ARRNELEMS(win) < lengthof(weights)) + ereport(ERROR, + (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("array of weight is too short"))); + + for (i = 0; i < lengthof(weights); i++) + { + ws[i] = (((float4 *) ARR_DATA_PTR(win))[i] >= 0) ? ((float4 *) ARR_DATA_PTR(win))[i] : weights[i]; + if (ws[i] > 1.0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("weight out of range"))); + } + + if (PG_NARGS() == 4) + method = PG_GETARG_INT32(3); + + res = calc_rank(ws, txt, query, method); + + PG_FREE_IF_COPY(win, 0); + PG_FREE_IF_COPY(txt, 1); + PG_FREE_IF_COPY(query, 2); + PG_RETURN_FLOAT4(res); +} + +Datum +rank_def(PG_FUNCTION_ARGS) +{ + tsvector *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + float res = 0.0; + int method = DEF_NORM_METHOD; + + if (PG_NARGS() == 3) + method = PG_GETARG_INT32(2); + + res = calc_rank(weights, txt, query, method); + + PG_FREE_IF_COPY(txt, 0); + PG_FREE_IF_COPY(query, 1); + PG_RETURN_FLOAT4(res); +} + + +typedef struct +{ + ITEM *item; + int32 pos; +} DocRepresentation; + +static int +compareDocR(const void *a, const void *b) +{ + if (((DocRepresentation *) a)->pos == ((DocRepresentation *) b)->pos) + return 1; + return (((DocRepresentation *) a)->pos > ((DocRepresentation *) b)->pos) ? 1 : -1; +} + + +typedef struct +{ + DocRepresentation *doc; + int len; +} ChkDocR; + +static bool +checkcondition_DR(void *checkval, ITEM * val) +{ + DocRepresentation *ptr = ((ChkDocR *) checkval)->doc; + + while (ptr - ((ChkDocR *) checkval)->doc < ((ChkDocR *) checkval)->len) + { + if (val == ptr->item) + return true; + ptr++; + } + + return false; +} + + +static bool +Cover(DocRepresentation * doc, int len, QUERYTYPE * query, int *pos, int *p, int *q) +{ + int i; + DocRepresentation *ptr, + *f = (DocRepresentation *) 0xffffffff; + ITEM *item = GETQUERY(query); + int lastpos = *pos; + int oldq = *q; + + *p = 0x7fffffff; + *q = 0; + + for (i = 0; i < query->size; i++) + { + if (item->type != VAL) + { + item++; + continue; + } + ptr = doc + *pos; + + while (ptr - doc < len) + { + if (ptr->item == item) + { + if (ptr->pos > *q) + { + *q = ptr->pos; + lastpos = ptr - doc; + } + break; + } + ptr++; + } + + item++; + } + + if (*q == 0) + return false; + + if (*q == oldq) + { /* already check this pos */ + (*pos)++; + return Cover(doc, len, query, pos, p, q); + } + + item = GETQUERY(query); + for (i = 0; i < query->size; i++) + { + if (item->type != VAL) + { + item++; + continue; + } + ptr = doc + lastpos; + + while (ptr >= doc + *pos) + { + if (ptr->item == item) + { + if (ptr->pos < *p) + { + *p = ptr->pos; + f = ptr; + } + break; + } + ptr--; + } + item++; + } + + if (*p <= *q) + { + ChkDocR ch = {f, (doc + lastpos) - f + 1}; + + *pos = f - doc + 1; + if (TS_execute(GETQUERY(query), &ch, false, checkcondition_DR)) + { + /* + * elog(NOTICE,"OP:%d NP:%d P:%d Q:%d", *pos, lastpos, *p, + * *q); + */ + return true; + } + else + return Cover(doc, len, query, pos, p, q); + } + + return false; +} + +static DocRepresentation * +get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen) +{ + ITEM *item = GETQUERY(query); + WordEntry *entry; + WordEntryPos *post; + int4 dimt, + j, + i; + int len = query->size * 4, + cur = 0; + DocRepresentation *doc; + + *(uint16 *) POSNULL = lengthof(POSNULL) - 1; + doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len); + for (i = 0; i < query->size; i++) + { + if (item[i].type != VAL) + continue; + + entry = find_wordentry(txt, query, &(item[i])); + if (!entry) + continue; + + if (entry->haspos) + { + dimt = POSDATALEN(txt, entry); + post = POSDATAPTR(txt, entry); + } + else + { + dimt = *(uint16 *) POSNULL; + post = POSNULL + 1; + } + + while (cur + dimt >= len) + { + len *= 2; + doc = (DocRepresentation *) repalloc(doc, sizeof(DocRepresentation) * len); + } + + for (j = 0; j < dimt; j++) + { + doc[cur].item = &(item[i]); + doc[cur].pos = post[j].pos; + cur++; + } + } + + *doclen = cur; + + if (cur > 0) + { + if (cur > 1) + qsort((void *) doc, cur, sizeof(DocRepresentation), compareDocR); + return doc; + } + + pfree(doc); + return NULL; +} + + +Datum +rank_cd(PG_FUNCTION_ARGS) +{ + int K = PG_GETARG_INT32(0); + tsvector *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_DATUM(2)); + int method = DEF_NORM_METHOD; + DocRepresentation *doc; + float res = 0.0; + int p = 0, + q = 0, + len, + cur; + + doc = get_docrep(txt, query, &len); + if (!doc) + { + PG_FREE_IF_COPY(txt, 1); + PG_FREE_IF_COPY(query, 2); + PG_RETURN_FLOAT4(0.0); + } + + cur = 0; + if (K <= 0) + K = 4; + while (Cover(doc, len, query, &cur, &p, &q)) + res += (q - p + 1 > K) ? ((float) K) / ((float) (q - p + 1)) : 1.0; + + if (PG_NARGS() == 4) + method = PG_GETARG_INT32(3); + + switch (method) + { + case 0: + break; + case 1: + res /= log((float) cnt_length(txt)); + break; + case 2: + res /= (float) cnt_length(txt); + break; + default: + /* internal error */ + elog(ERROR, "unrecognized normalization method: %d", method); + } + + pfree(doc); + PG_FREE_IF_COPY(txt, 1); + PG_FREE_IF_COPY(query, 2); + + PG_RETURN_FLOAT4(res); +} + + +Datum +rank_cd_def(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(DirectFunctionCall4( + rank_cd, + Int32GetDatum(-1), + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1), + (PG_NARGS() == 3) ? PG_GETARG_DATUM(2) : Int32GetDatum(DEF_NORM_METHOD) + )); +} + +/**************debug*************/ + +typedef struct +{ + char *w; + int2 len; + int2 pos; + int2 start; + int2 finish; +} DocWord; + +static int +compareDocWord(const void *a, const void *b) +{ + if (((DocWord *) a)->pos == ((DocWord *) b)->pos) + return 1; + return (((DocWord *) a)->pos > ((DocWord *) b)->pos) ? 1 : -1; +} + + +Datum +get_covers(PG_FUNCTION_ARGS) +{ + tsvector *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + WordEntry *pptr = ARRPTR(txt); + int i, + dlen = 0, + j, + cur = 0, + len = 0, + rlen; + DocWord *dw, + *dwptr; + text *out; + char *cptr; + DocRepresentation *doc; + int pos = 0, + p, + q, + olddwpos = 0; + int ncover = 1; + + doc = get_docrep(txt, query, &rlen); + + if (!doc) + { + out = palloc(VARHDRSZ); + VARATT_SIZEP(out) = VARHDRSZ; + PG_FREE_IF_COPY(txt, 0); + PG_FREE_IF_COPY(query, 1); + PG_RETURN_POINTER(out); + } + + for (i = 0; i < txt->size; i++) + { + if (!pptr[i].haspos) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("no pos info"))); + dlen += POSDATALEN(txt, &(pptr[i])); + } + + dwptr = dw = palloc(sizeof(DocWord) * dlen); + memset(dw, 0, sizeof(DocWord) * dlen); + + for (i = 0; i < txt->size; i++) + { + WordEntryPos *posdata = POSDATAPTR(txt, &(pptr[i])); + + for (j = 0; j < POSDATALEN(txt, &(pptr[i])); j++) + { + dw[cur].w = STRPTR(txt) + pptr[i].pos; + dw[cur].len = pptr[i].len; + dw[cur].pos = posdata[j].pos; + cur++; + } + len += (pptr[i].len + 1) * (int) POSDATALEN(txt, &(pptr[i])); + } + qsort((void *) dw, dlen, sizeof(DocWord), compareDocWord); + + while (Cover(doc, rlen, query, &pos, &p, &q)) + { + dwptr = dw + olddwpos; + while (dwptr->pos < p && dwptr - dw < dlen) + dwptr++; + olddwpos = dwptr - dw; + dwptr->start = ncover; + while (dwptr->pos < q + 1 && dwptr - dw < dlen) + dwptr++; + (dwptr - 1)->finish = ncover; + len += 4 /* {}+two spaces */ + 2 * 16 /* numbers */ ; + ncover++; + } + + out = palloc(VARHDRSZ + len); + cptr = ((char *) out) + VARHDRSZ; + dwptr = dw; + + while (dwptr - dw < dlen) + { + if (dwptr->start) + { + sprintf(cptr, "{%d ", dwptr->start); + cptr = strchr(cptr, '\0'); + } + memcpy(cptr, dwptr->w, dwptr->len); + cptr += dwptr->len; + *cptr = ' '; + cptr++; + if (dwptr->finish) + { + sprintf(cptr, "}%d ", dwptr->finish); + cptr = strchr(cptr, '\0'); + } + dwptr++; + } + + VARATT_SIZEP(out) = cptr - ((char *) out); + + pfree(dw); + pfree(doc); + + PG_FREE_IF_COPY(txt, 0); + PG_FREE_IF_COPY(query, 1); + PG_RETURN_POINTER(out); +} diff --git a/contrib/tsearch2/rewrite.h b/contrib/tsearch2/rewrite.h new file mode 100644 index 0000000..d47788a --- /dev/null +++ b/contrib/tsearch2/rewrite.h @@ -0,0 +1,7 @@ +#ifndef __REWRITE_H__ +#define __REWRITE_H__ + +ITEM *clean_NOT_v2(ITEM * ptr, int4 *len); +ITEM *clean_fakeval_v2(ITEM * ptr, int4 *len); + +#endif diff --git a/contrib/tsearch2/snmap.c b/contrib/tsearch2/snmap.c new file mode 100644 index 0000000..2cd3f53 --- /dev/null +++ b/contrib/tsearch2/snmap.c @@ -0,0 +1,95 @@ +/* + * simple but fast map from str to Oid + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" +#include "snmap.h" +#include "common.h" + +static int +compareSNMapEntry(const void *a, const void *b) +{ + return strcmp(((SNMapEntry *) a)->key, ((SNMapEntry *) b)->key); +} + +void +addSNMap(SNMap * map, char *key, Oid value) +{ + if (map->len >= map->reallen) + { + SNMapEntry *tmp; + int len = (map->reallen) ? 2 * map->reallen : 16; + + tmp = (SNMapEntry *) realloc(map->list, sizeof(SNMapEntry) * len); + if (!tmp) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + map->reallen = len; + map->list = tmp; + } + map->list[map->len].key = strdup(key); + if (!map->list[map->len].key) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + map->list[map->len].value = value; + map->len++; + if (map->len > 1) + qsort(map->list, map->len, sizeof(SNMapEntry), compareSNMapEntry); +} + +void +addSNMap_t(SNMap * map, text *key, Oid value) +{ + char *k = text2char(key); + + addSNMap(map, k, value); + pfree(k); +} + +Oid +findSNMap(SNMap * map, char *key) +{ + SNMapEntry *ptr; + SNMapEntry ks = {key, 0}; + + if (map->len == 0 || !map->list) + return 0; + ptr = (SNMapEntry *) bsearch(&ks, map->list, map->len, sizeof(SNMapEntry), compareSNMapEntry); + return (ptr) ? ptr->value : 0; +} + +Oid +findSNMap_t(SNMap * map, text *key) +{ + char *k = text2char(key); + int res; + + res = findSNMap(map, k); + pfree(k); + return res; +} + +void +freeSNMap(SNMap * map) +{ + SNMapEntry *entry = map->list; + + if (map->list) + { + while (map->len) + { + if (entry->key) + free(entry->key); + entry++; + map->len--; + } + free(map->list); + } + memset(map, 0, sizeof(SNMap)); +} diff --git a/contrib/tsearch2/snmap.h b/contrib/tsearch2/snmap.h new file mode 100644 index 0000000..ae188b6 --- /dev/null +++ b/contrib/tsearch2/snmap.h @@ -0,0 +1,25 @@ +#ifndef __SNMAP_H__ +#define __SNMAP_H__ + +#include "postgres.h" + +typedef struct +{ + char *key; + Oid value; +} SNMapEntry; + +typedef struct +{ + int len; + int reallen; + SNMapEntry *list; +} SNMap; + +void addSNMap(SNMap * map, char *key, Oid value); +void addSNMap_t(SNMap * map, text *key, Oid value); +Oid findSNMap(SNMap * map, char *key); +Oid findSNMap_t(SNMap * map, text *key); +void freeSNMap(SNMap * map); + +#endif diff --git a/contrib/tsearch2/snowball/api.c b/contrib/tsearch2/snowball/api.c new file mode 100644 index 0000000..5cbf37d --- /dev/null +++ b/contrib/tsearch2/snowball/api.c @@ -0,0 +1,65 @@ +#include + +#include "header.h" + +extern struct SN_env * +SN_create_env(int S_size, int I_size, int B_size) +{ + struct SN_env *z = (struct SN_env *) calloc(1, sizeof(struct SN_env)); + + z->p = create_s(); + if (S_size) + { + z->S = (symbol * *) calloc(S_size, sizeof(symbol *)); + { + int i; + + for (i = 0; i < S_size; i++) + z->S[i] = create_s(); + } + z->S_size = S_size; + } + + if (I_size) + { + z->I = (int *) calloc(I_size, sizeof(int)); + z->I_size = I_size; + } + + if (B_size) + { + z->B = (symbol *) calloc(B_size, sizeof(symbol)); + z->B_size = B_size; + } + + return z; +} + +extern void +SN_close_env(struct SN_env * z) +{ + if (z->S_size) + { + { + int i; + + for (i = 0; i < z->S_size; i++) + lose_s(z->S[i]); + } + free(z->S); + } + if (z->I_size) + free(z->I); + if (z->B_size) + free(z->B); + if (z->p) + lose_s(z->p); + free(z); +} + +extern void +SN_set_current(struct SN_env * z, int size, const symbol * s) +{ + replace_s(z, 0, z->l, size, s); + z->c = 0; +} diff --git a/contrib/tsearch2/snowball/api.h b/contrib/tsearch2/snowball/api.h new file mode 100644 index 0000000..b173469 --- /dev/null +++ b/contrib/tsearch2/snowball/api.h @@ -0,0 +1,34 @@ + +typedef unsigned char symbol; + +/* Or replace 'char' above with 'short' for 16 bit characters. + + More precisely, replace 'char' with whatever type guarantees the + character width you need. Note however that sizeof(symbol) should divide + HEAD, defined in header.h as 2*sizeof(int), without remainder, otherwise + there is an alignment problem. In the unlikely event of a problem here, + consult Martin Porter. + +*/ + +struct SN_env +{ + symbol *p; + int c; + int a; + int l; + int lb; + int bra; + int ket; + int S_size; + int I_size; + int B_size; + symbol **S; + int *I; + symbol *B; +}; + +extern struct SN_env *SN_create_env(int S_size, int I_size, int B_size); +extern void SN_close_env(struct SN_env * z); + +extern void SN_set_current(struct SN_env * z, int size, const symbol * s); diff --git a/contrib/tsearch2/snowball/english_stem.c b/contrib/tsearch2/snowball/english_stem.c new file mode 100644 index 0000000..5ddc72c --- /dev/null +++ b/contrib/tsearch2/snowball/english_stem.c @@ -0,0 +1,1107 @@ + +/* This file was generated automatically by the Snowball to ANSI C compiler */ + +#include "header.h" + +extern int english_stem(struct SN_env * z); +static int r_exception2(struct SN_env * z); +static int r_exception1(struct SN_env * z); +static int r_Step_5(struct SN_env * z); +static int r_Step_4(struct SN_env * z); +static int r_Step_3(struct SN_env * z); +static int r_Step_2(struct SN_env * z); +static int r_Step_1c(struct SN_env * z); +static int r_Step_1b(struct SN_env * z); +static int r_Step_1a(struct SN_env * z); +static int r_R2(struct SN_env * z); +static int r_R1(struct SN_env * z); +static int r_shortv(struct SN_env * z); +static int r_mark_regions(struct SN_env * z); +static int r_postlude(struct SN_env * z); +static int r_prelude(struct SN_env * z); + +extern struct SN_env *english_create_env(void); +extern void english_close_env(struct SN_env * z); + +static symbol s_0_0[5] = {'g', 'e', 'n', 'e', 'r'}; + +static struct among a_0[1] = +{ + /* 0 */ {5, s_0_0, -1, -1, 0} +}; + +static symbol s_1_0[3] = {'i', 'e', 'd'}; +static symbol s_1_1[1] = {'s'}; +static symbol s_1_2[3] = {'i', 'e', 's'}; +static symbol s_1_3[4] = {'s', 's', 'e', 's'}; +static symbol s_1_4[2] = {'s', 's'}; +static symbol s_1_5[2] = {'u', 's'}; + +static struct among a_1[6] = +{ + /* 0 */ {3, s_1_0, -1, 2, 0}, + /* 1 */ {1, s_1_1, -1, 3, 0}, + /* 2 */ {3, s_1_2, 1, 2, 0}, + /* 3 */ {4, s_1_3, 1, 1, 0}, + /* 4 */ {2, s_1_4, 1, -1, 0}, + /* 5 */ {2, s_1_5, 1, -1, 0} +}; + +static symbol s_2_1[2] = {'b', 'b'}; +static symbol s_2_2[2] = {'d', 'd'}; +static symbol s_2_3[2] = {'f', 'f'}; +static symbol s_2_4[2] = {'g', 'g'}; +static symbol s_2_5[2] = {'b', 'l'}; +static symbol s_2_6[2] = {'m', 'm'}; +static symbol s_2_7[2] = {'n', 'n'}; +static symbol s_2_8[2] = {'p', 'p'}; +static symbol s_2_9[2] = {'r', 'r'}; +static symbol s_2_10[2] = {'a', 't'}; +static symbol s_2_11[2] = {'t', 't'}; +static symbol s_2_12[2] = {'i', 'z'}; + +static struct among a_2[13] = +{ + /* 0 */ {0, 0, -1, 3, 0}, + /* 1 */ {2, s_2_1, 0, 2, 0}, + /* 2 */ {2, s_2_2, 0, 2, 0}, + /* 3 */ {2, s_2_3, 0, 2, 0}, + /* 4 */ {2, s_2_4, 0, 2, 0}, + /* 5 */ {2, s_2_5, 0, 1, 0}, + /* 6 */ {2, s_2_6, 0, 2, 0}, + /* 7 */ {2, s_2_7, 0, 2, 0}, + /* 8 */ {2, s_2_8, 0, 2, 0}, + /* 9 */ {2, s_2_9, 0, 2, 0}, + /* 10 */ {2, s_2_10, 0, 1, 0}, + /* 11 */ {2, s_2_11, 0, 2, 0}, + /* 12 */ {2, s_2_12, 0, 1, 0} +}; + +static symbol s_3_0[2] = {'e', 'd'}; +static symbol s_3_1[3] = {'e', 'e', 'd'}; +static symbol s_3_2[3] = {'i', 'n', 'g'}; +static symbol s_3_3[4] = {'e', 'd', 'l', 'y'}; +static symbol s_3_4[5] = {'e', 'e', 'd', 'l', 'y'}; +static symbol s_3_5[5] = {'i', 'n', 'g', 'l', 'y'}; + +static struct among a_3[6] = +{ + /* 0 */ {2, s_3_0, -1, 2, 0}, + /* 1 */ {3, s_3_1, 0, 1, 0}, + /* 2 */ {3, s_3_2, -1, 2, 0}, + /* 3 */ {4, s_3_3, -1, 2, 0}, + /* 4 */ {5, s_3_4, 3, 1, 0}, + /* 5 */ {5, s_3_5, -1, 2, 0} +}; + +static symbol s_4_0[4] = {'a', 'n', 'c', 'i'}; +static symbol s_4_1[4] = {'e', 'n', 'c', 'i'}; +static symbol s_4_2[3] = {'o', 'g', 'i'}; +static symbol s_4_3[2] = {'l', 'i'}; +static symbol s_4_4[3] = {'b', 'l', 'i'}; +static symbol s_4_5[4] = {'a', 'b', 'l', 'i'}; +static symbol s_4_6[4] = {'a', 'l', 'l', 'i'}; +static symbol s_4_7[5] = {'f', 'u', 'l', 'l', 'i'}; +static symbol s_4_8[6] = {'l', 'e', 's', 's', 'l', 'i'}; +static symbol s_4_9[5] = {'o', 'u', 's', 'l', 'i'}; +static symbol s_4_10[5] = {'e', 'n', 't', 'l', 'i'}; +static symbol s_4_11[5] = {'a', 'l', 'i', 't', 'i'}; +static symbol s_4_12[6] = {'b', 'i', 'l', 'i', 't', 'i'}; +static symbol s_4_13[5] = {'i', 'v', 'i', 't', 'i'}; +static symbol s_4_14[6] = {'t', 'i', 'o', 'n', 'a', 'l'}; +static symbol s_4_15[7] = {'a', 't', 'i', 'o', 'n', 'a', 'l'}; +static symbol s_4_16[5] = {'a', 'l', 'i', 's', 'm'}; +static symbol s_4_17[5] = {'a', 't', 'i', 'o', 'n'}; +static symbol s_4_18[7] = {'i', 'z', 'a', 't', 'i', 'o', 'n'}; +static symbol s_4_19[4] = {'i', 'z', 'e', 'r'}; +static symbol s_4_20[4] = {'a', 't', 'o', 'r'}; +static symbol s_4_21[7] = {'i', 'v', 'e', 'n', 'e', 's', 's'}; +static symbol s_4_22[7] = {'f', 'u', 'l', 'n', 'e', 's', 's'}; +static symbol s_4_23[7] = {'o', 'u', 's', 'n', 'e', 's', 's'}; + +static struct among a_4[24] = +{ + /* 0 */ {4, s_4_0, -1, 3, 0}, + /* 1 */ {4, s_4_1, -1, 2, 0}, + /* 2 */ {3, s_4_2, -1, 13, 0}, + /* 3 */ {2, s_4_3, -1, 16, 0}, + /* 4 */ {3, s_4_4, 3, 12, 0}, + /* 5 */ {4, s_4_5, 4, 4, 0}, + /* 6 */ {4, s_4_6, 3, 8, 0}, + /* 7 */ {5, s_4_7, 3, 14, 0}, + /* 8 */ {6, s_4_8, 3, 15, 0}, + /* 9 */ {5, s_4_9, 3, 10, 0}, + /* 10 */ {5, s_4_10, 3, 5, 0}, + /* 11 */ {5, s_4_11, -1, 8, 0}, + /* 12 */ {6, s_4_12, -1, 12, 0}, + /* 13 */ {5, s_4_13, -1, 11, 0}, + /* 14 */ {6, s_4_14, -1, 1, 0}, + /* 15 */ {7, s_4_15, 14, 7, 0}, + /* 16 */ {5, s_4_16, -1, 8, 0}, + /* 17 */ {5, s_4_17, -1, 7, 0}, + /* 18 */ {7, s_4_18, 17, 6, 0}, + /* 19 */ {4, s_4_19, -1, 6, 0}, + /* 20 */ {4, s_4_20, -1, 7, 0}, + /* 21 */ {7, s_4_21, -1, 11, 0}, + /* 22 */ {7, s_4_22, -1, 9, 0}, + /* 23 */ {7, s_4_23, -1, 10, 0} +}; + +static symbol s_5_0[5] = {'i', 'c', 'a', 't', 'e'}; +static symbol s_5_1[5] = {'a', 't', 'i', 'v', 'e'}; +static symbol s_5_2[5] = {'a', 'l', 'i', 'z', 'e'}; +static symbol s_5_3[5] = {'i', 'c', 'i', 't', 'i'}; +static symbol s_5_4[4] = {'i', 'c', 'a', 'l'}; +static symbol s_5_5[6] = {'t', 'i', 'o', 'n', 'a', 'l'}; +static symbol s_5_6[7] = {'a', 't', 'i', 'o', 'n', 'a', 'l'}; +static symbol s_5_7[3] = {'f', 'u', 'l'}; +static symbol s_5_8[4] = {'n', 'e', 's', 's'}; + +static struct among a_5[9] = +{ + /* 0 */ {5, s_5_0, -1, 4, 0}, + /* 1 */ {5, s_5_1, -1, 6, 0}, + /* 2 */ {5, s_5_2, -1, 3, 0}, + /* 3 */ {5, s_5_3, -1, 4, 0}, + /* 4 */ {4, s_5_4, -1, 4, 0}, + /* 5 */ {6, s_5_5, -1, 1, 0}, + /* 6 */ {7, s_5_6, 5, 2, 0}, + /* 7 */ {3, s_5_7, -1, 5, 0}, + /* 8 */ {4, s_5_8, -1, 5, 0} +}; + +static symbol s_6_0[2] = {'i', 'c'}; +static symbol s_6_1[4] = {'a', 'n', 'c', 'e'}; +static symbol s_6_2[4] = {'e', 'n', 'c', 'e'}; +static symbol s_6_3[4] = {'a', 'b', 'l', 'e'}; +static symbol s_6_4[4] = {'i', 'b', 'l', 'e'}; +static symbol s_6_5[3] = {'a', 't', 'e'}; +static symbol s_6_6[3] = {'i', 'v', 'e'}; +static symbol s_6_7[3] = {'i', 'z', 'e'}; +static symbol s_6_8[3] = {'i', 't', 'i'}; +static symbol s_6_9[2] = {'a', 'l'}; +static symbol s_6_10[3] = {'i', 's', 'm'}; +static symbol s_6_11[3] = {'i', 'o', 'n'}; +static symbol s_6_12[2] = {'e', 'r'}; +static symbol s_6_13[3] = {'o', 'u', 's'}; +static symbol s_6_14[3] = {'a', 'n', 't'}; +static symbol s_6_15[3] = {'e', 'n', 't'}; +static symbol s_6_16[4] = {'m', 'e', 'n', 't'}; +static symbol s_6_17[5] = {'e', 'm', 'e', 'n', 't'}; + +static struct among a_6[18] = +{ + /* 0 */ {2, s_6_0, -1, 1, 0}, + /* 1 */ {4, s_6_1, -1, 1, 0}, + /* 2 */ {4, s_6_2, -1, 1, 0}, + /* 3 */ {4, s_6_3, -1, 1, 0}, + /* 4 */ {4, s_6_4, -1, 1, 0}, + /* 5 */ {3, s_6_5, -1, 1, 0}, + /* 6 */ {3, s_6_6, -1, 1, 0}, + /* 7 */ {3, s_6_7, -1, 1, 0}, + /* 8 */ {3, s_6_8, -1, 1, 0}, + /* 9 */ {2, s_6_9, -1, 1, 0}, + /* 10 */ {3, s_6_10, -1, 1, 0}, + /* 11 */ {3, s_6_11, -1, 2, 0}, + /* 12 */ {2, s_6_12, -1, 1, 0}, + /* 13 */ {3, s_6_13, -1, 1, 0}, + /* 14 */ {3, s_6_14, -1, 1, 0}, + /* 15 */ {3, s_6_15, -1, 1, 0}, + /* 16 */ {4, s_6_16, 15, 1, 0}, + /* 17 */ {5, s_6_17, 16, 1, 0} +}; + +static symbol s_7_0[1] = {'e'}; +static symbol s_7_1[1] = {'l'}; + +static struct among a_7[2] = +{ + /* 0 */ {1, s_7_0, -1, 1, 0}, + /* 1 */ {1, s_7_1, -1, 2, 0} +}; + +static symbol s_8_0[7] = {'s', 'u', 'c', 'c', 'e', 'e', 'd'}; +static symbol s_8_1[7] = {'p', 'r', 'o', 'c', 'e', 'e', 'd'}; +static symbol s_8_2[6] = {'e', 'x', 'c', 'e', 'e', 'd'}; +static symbol s_8_3[7] = {'c', 'a', 'n', 'n', 'i', 'n', 'g'}; +static symbol s_8_4[6] = {'i', 'n', 'n', 'i', 'n', 'g'}; +static symbol s_8_5[7] = {'e', 'a', 'r', 'r', 'i', 'n', 'g'}; +static symbol s_8_6[7] = {'h', 'e', 'r', 'r', 'i', 'n', 'g'}; +static symbol s_8_7[6] = {'o', 'u', 't', 'i', 'n', 'g'}; + +static struct among a_8[8] = +{ + /* 0 */ {7, s_8_0, -1, -1, 0}, + /* 1 */ {7, s_8_1, -1, -1, 0}, + /* 2 */ {6, s_8_2, -1, -1, 0}, + /* 3 */ {7, s_8_3, -1, -1, 0}, + /* 4 */ {6, s_8_4, -1, -1, 0}, + /* 5 */ {7, s_8_5, -1, -1, 0}, + /* 6 */ {7, s_8_6, -1, -1, 0}, + /* 7 */ {6, s_8_7, -1, -1, 0} +}; + +static symbol s_9_0[5] = {'a', 'n', 'd', 'e', 's'}; +static symbol s_9_1[5] = {'a', 't', 'l', 'a', 's'}; +static symbol s_9_2[4] = {'b', 'i', 'a', 's'}; +static symbol s_9_3[6] = {'c', 'o', 's', 'm', 'o', 's'}; +static symbol s_9_4[5] = {'d', 'y', 'i', 'n', 'g'}; +static symbol s_9_5[5] = {'e', 'a', 'r', 'l', 'y'}; +static symbol s_9_6[6] = {'g', 'e', 'n', 't', 'l', 'y'}; +static symbol s_9_7[4] = {'h', 'o', 'w', 'e'}; +static symbol s_9_8[4] = {'i', 'd', 'l', 'y'}; +static symbol s_9_9[5] = {'l', 'y', 'i', 'n', 'g'}; +static symbol s_9_10[4] = {'n', 'e', 'w', 's'}; +static symbol s_9_11[4] = {'o', 'n', 'l', 'y'}; +static symbol s_9_12[6] = {'s', 'i', 'n', 'g', 'l', 'y'}; +static symbol s_9_13[5] = {'s', 'k', 'i', 'e', 's'}; +static symbol s_9_14[4] = {'s', 'k', 'i', 's'}; +static symbol s_9_15[3] = {'s', 'k', 'y'}; +static symbol s_9_16[5] = {'t', 'y', 'i', 'n', 'g'}; +static symbol s_9_17[4] = {'u', 'g', 'l', 'y'}; + +static struct among a_9[18] = +{ + /* 0 */ {5, s_9_0, -1, -1, 0}, + /* 1 */ {5, s_9_1, -1, -1, 0}, + /* 2 */ {4, s_9_2, -1, -1, 0}, + /* 3 */ {6, s_9_3, -1, -1, 0}, + /* 4 */ {5, s_9_4, -1, 3, 0}, + /* 5 */ {5, s_9_5, -1, 9, 0}, + /* 6 */ {6, s_9_6, -1, 7, 0}, + /* 7 */ {4, s_9_7, -1, -1, 0}, + /* 8 */ {4, s_9_8, -1, 6, 0}, + /* 9 */ {5, s_9_9, -1, 4, 0}, + /* 10 */ {4, s_9_10, -1, -1, 0}, + /* 11 */ {4, s_9_11, -1, 10, 0}, + /* 12 */ {6, s_9_12, -1, 11, 0}, + /* 13 */ {5, s_9_13, -1, 2, 0}, + /* 14 */ {4, s_9_14, -1, 1, 0}, + /* 15 */ {3, s_9_15, -1, -1, 0}, + /* 16 */ {5, s_9_16, -1, 5, 0}, + /* 17 */ {4, s_9_17, -1, 8, 0} +}; + +static unsigned char g_v[] = {17, 65, 16, 1}; + +static unsigned char g_v_WXY[] = {1, 17, 65, 208, 1}; + +static unsigned char g_valid_LI[] = {55, 141, 2}; + +static symbol s_0[] = {'y'}; +static symbol s_1[] = {'Y'}; +static symbol s_2[] = {'y'}; +static symbol s_3[] = {'Y'}; +static symbol s_4[] = {'s', 's'}; +static symbol s_5[] = {'i', 'e'}; +static symbol s_6[] = {'i'}; +static symbol s_7[] = {'e', 'e'}; +static symbol s_8[] = {'e'}; +static symbol s_9[] = {'e'}; +static symbol s_10[] = {'y'}; +static symbol s_11[] = {'Y'}; +static symbol s_12[] = {'i'}; +static symbol s_13[] = {'t', 'i', 'o', 'n'}; +static symbol s_14[] = {'e', 'n', 'c', 'e'}; +static symbol s_15[] = {'a', 'n', 'c', 'e'}; +static symbol s_16[] = {'a', 'b', 'l', 'e'}; +static symbol s_17[] = {'e', 'n', 't'}; +static symbol s_18[] = {'i', 'z', 'e'}; +static symbol s_19[] = {'a', 't', 'e'}; +static symbol s_20[] = {'a', 'l'}; +static symbol s_21[] = {'f', 'u', 'l'}; +static symbol s_22[] = {'o', 'u', 's'}; +static symbol s_23[] = {'i', 'v', 'e'}; +static symbol s_24[] = {'b', 'l', 'e'}; +static symbol s_25[] = {'l'}; +static symbol s_26[] = {'o', 'g'}; +static symbol s_27[] = {'f', 'u', 'l'}; +static symbol s_28[] = {'l', 'e', 's', 's'}; +static symbol s_29[] = {'t', 'i', 'o', 'n'}; +static symbol s_30[] = {'a', 't', 'e'}; +static symbol s_31[] = {'a', 'l'}; +static symbol s_32[] = {'i', 'c'}; +static symbol s_33[] = {'s'}; +static symbol s_34[] = {'t'}; +static symbol s_35[] = {'l'}; +static symbol s_36[] = {'s', 'k', 'i'}; +static symbol s_37[] = {'s', 'k', 'y'}; +static symbol s_38[] = {'d', 'i', 'e'}; +static symbol s_39[] = {'l', 'i', 'e'}; +static symbol s_40[] = {'t', 'i', 'e'}; +static symbol s_41[] = {'i', 'd', 'l'}; +static symbol s_42[] = {'g', 'e', 'n', 't', 'l'}; +static symbol s_43[] = {'u', 'g', 'l', 'i'}; +static symbol s_44[] = {'e', 'a', 'r', 'l', 'i'}; +static symbol s_45[] = {'o', 'n', 'l', 'i'}; +static symbol s_46[] = {'s', 'i', 'n', 'g', 'l'}; +static symbol s_47[] = {'Y'}; +static symbol s_48[] = {'y'}; + +static int +r_prelude(struct SN_env * z) +{ + z->B[0] = 0; /* unset Y_found, line 24 */ + { + int c = z->c; /* do, line 25 */ + + z->bra = z->c; /* [, line 25 */ + if (!(eq_s(z, 1, s_0))) + goto lab0; + z->ket = z->c; /* ], line 25 */ + if (!(in_grouping(z, g_v, 97, 121))) + goto lab0; + slice_from_s(z, 1, s_1); /* <-, line 25 */ + z->B[0] = 1; /* set Y_found, line 25 */ +lab0: + z->c = c; + } + { + int c = z->c; /* do, line 26 */ + + while (1) + { /* repeat, line 26 */ + int c = z->c; + + while (1) + { /* goto, line 26 */ + int c = z->c; + + if (!(in_grouping(z, g_v, 97, 121))) + goto lab3; + z->bra = z->c; /* [, line 26 */ + if (!(eq_s(z, 1, s_2))) + goto lab3; + z->ket = z->c; /* ], line 26 */ + z->c = c; + break; + lab3: + z->c = c; + if (z->c >= z->l) + goto lab2; + z->c++; + } + slice_from_s(z, 1, s_3); /* <-, line 26 */ + z->B[0] = 1; /* set Y_found, line 26 */ + continue; + lab2: + z->c = c; + break; + } + z->c = c; + } + return 1; +} + +static int +r_mark_regions(struct SN_env * z) +{ + z->I[0] = z->l; + z->I[1] = z->l; + { + int c = z->c; /* do, line 32 */ + + { + int c = z->c; /* or, line 36 */ + + if (!(find_among(z, a_0, 1))) + goto lab2; /* among, line 33 */ + goto lab1; + lab2: + z->c = c; + while (1) + { /* gopast, line 36 */ + if (!(in_grouping(z, g_v, 97, 121))) + goto lab3; + break; + lab3: + if (z->c >= z->l) + goto lab0; + z->c++; + } + while (1) + { /* gopast, line 36 */ + if (!(out_grouping(z, g_v, 97, 121))) + goto lab4; + break; + lab4: + if (z->c >= z->l) + goto lab0; + z->c++; + } + } +lab1: + z->I[0] = z->c; /* setmark p1, line 37 */ + while (1) + { /* gopast, line 38 */ + if (!(in_grouping(z, g_v, 97, 121))) + goto lab5; + break; + lab5: + if (z->c >= z->l) + goto lab0; + z->c++; + } + while (1) + { /* gopast, line 38 */ + if (!(out_grouping(z, g_v, 97, 121))) + goto lab6; + break; + lab6: + if (z->c >= z->l) + goto lab0; + z->c++; + } + z->I[1] = z->c; /* setmark p2, line 38 */ +lab0: + z->c = c; + } + return 1; +} + +static int +r_shortv(struct SN_env * z) +{ + { + int m = z->l - z->c; /* or, line 46 */ + + if (!(out_grouping_b(z, g_v_WXY, 89, 121))) + goto lab1; + if (!(in_grouping_b(z, g_v, 97, 121))) + goto lab1; + if (!(out_grouping_b(z, g_v, 97, 121))) + goto lab1; + goto lab0; +lab1: + z->c = z->l - m; + if (!(out_grouping_b(z, g_v, 97, 121))) + return 0; + if (!(in_grouping_b(z, g_v, 97, 121))) + return 0; + if (z->c > z->lb) + return 0; /* atlimit, line 47 */ + } +lab0: + return 1; +} + +static int +r_R1(struct SN_env * z) +{ + if (!(z->I[0] <= z->c)) + return 0; + return 1; +} + +static int +r_R2(struct SN_env * z) +{ + if (!(z->I[1] <= z->c)) + return 0; + return 1; +} + +static int +r_Step_1a(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 54 */ + among_var = find_among_b(z, a_1, 6); /* substring, line 54 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 54 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_from_s(z, 2, s_4); /* <-, line 55 */ + break; + case 2: + { + int m = z->l - z->c; /* or, line 57 */ + + if (z->c <= z->lb) + goto lab1; + z->c--; /* next, line 57 */ + if (z->c > z->lb) + goto lab1; /* atlimit, line 57 */ + slice_from_s(z, 2, s_5); /* <-, line 57 */ + goto lab0; + lab1: + z->c = z->l - m; + slice_from_s(z, 1, s_6); /* <-, line 57 */ + } + lab0: + break; + case 3: + if (z->c <= z->lb) + return 0; + z->c--; /* next, line 58 */ + while (1) + { /* gopast, line 58 */ + if (!(in_grouping_b(z, g_v, 97, 121))) + goto lab2; + break; + lab2: + if (z->c <= z->lb) + return 0; + z->c--; + } + slice_del(z); /* delete, line 58 */ + break; + } + return 1; +} + +static int +r_Step_1b(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 64 */ + among_var = find_among_b(z, a_3, 6); /* substring, line 64 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 64 */ + switch (among_var) + { + case 0: + return 0; + case 1: + if (!r_R1(z)) + return 0; /* call R1, line 66 */ + slice_from_s(z, 2, s_7); /* <-, line 66 */ + break; + case 2: + { + int m_test = z->l - z->c; /* test, line 69 */ + + while (1) + { /* gopast, line 69 */ + if (!(in_grouping_b(z, g_v, 97, 121))) + goto lab0; + break; + lab0: + if (z->c <= z->lb) + return 0; + z->c--; + } + z->c = z->l - m_test; + } + slice_del(z); /* delete, line 69 */ + { + int m_test = z->l - z->c; /* test, line 70 */ + + among_var = find_among_b(z, a_2, 13); /* substring, line 70 */ + if (!(among_var)) + return 0; + z->c = z->l - m_test; + } + switch (among_var) + { + case 0: + return 0; + case 1: + { + int c = z->c; + + insert_s(z, z->c, z->c, 1, s_8); /* <+, line 72 */ + z->c = c; + } + break; + case 2: + z->ket = z->c; /* [, line 75 */ + if (z->c <= z->lb) + return 0; + z->c--; /* next, line 75 */ + z->bra = z->c; /* ], line 75 */ + slice_del(z); /* delete, line 75 */ + break; + case 3: + if (z->c != z->I[0]) + return 0; /* atmark, line 76 */ + { + int m_test = z->l - z->c; /* test, line 76 */ + + if (!r_shortv(z)) + return 0; /* call shortv, line 76 */ + z->c = z->l - m_test; + } + { + int c = z->c; + + insert_s(z, z->c, z->c, 1, s_9); /* <+, line 76 */ + z->c = c; + } + break; + } + break; + } + return 1; +} + +static int +r_Step_1c(struct SN_env * z) +{ + z->ket = z->c; /* [, line 83 */ + { + int m = z->l - z->c; /* or, line 83 */ + + if (!(eq_s_b(z, 1, s_10))) + goto lab1; + goto lab0; +lab1: + z->c = z->l - m; + if (!(eq_s_b(z, 1, s_11))) + return 0; + } +lab0: + z->bra = z->c; /* ], line 83 */ + if (!(out_grouping_b(z, g_v, 97, 121))) + return 0; + { + int m = z->l - z->c; /* not, line 84 */ + + if (z->c > z->lb) + goto lab2; /* atlimit, line 84 */ + return 0; +lab2: + z->c = z->l - m; + } + slice_from_s(z, 1, s_12); /* <-, line 85 */ + return 1; +} + +static int +r_Step_2(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 89 */ + among_var = find_among_b(z, a_4, 24); /* substring, line 89 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 89 */ + if (!r_R1(z)) + return 0; /* call R1, line 89 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_from_s(z, 4, s_13); /* <-, line 90 */ + break; + case 2: + slice_from_s(z, 4, s_14); /* <-, line 91 */ + break; + case 3: + slice_from_s(z, 4, s_15); /* <-, line 92 */ + break; + case 4: + slice_from_s(z, 4, s_16); /* <-, line 93 */ + break; + case 5: + slice_from_s(z, 3, s_17); /* <-, line 94 */ + break; + case 6: + slice_from_s(z, 3, s_18); /* <-, line 96 */ + break; + case 7: + slice_from_s(z, 3, s_19); /* <-, line 98 */ + break; + case 8: + slice_from_s(z, 2, s_20); /* <-, line 100 */ + break; + case 9: + slice_from_s(z, 3, s_21); /* <-, line 101 */ + break; + case 10: + slice_from_s(z, 3, s_22); /* <-, line 103 */ + break; + case 11: + slice_from_s(z, 3, s_23); /* <-, line 105 */ + break; + case 12: + slice_from_s(z, 3, s_24); /* <-, line 107 */ + break; + case 13: + if (!(eq_s_b(z, 1, s_25))) + return 0; + slice_from_s(z, 2, s_26); /* <-, line 108 */ + break; + case 14: + slice_from_s(z, 3, s_27); /* <-, line 109 */ + break; + case 15: + slice_from_s(z, 4, s_28); /* <-, line 110 */ + break; + case 16: + if (!(in_grouping_b(z, g_valid_LI, 99, 116))) + return 0; + slice_del(z); /* delete, line 111 */ + break; + } + return 1; +} + +static int +r_Step_3(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 116 */ + among_var = find_among_b(z, a_5, 9); /* substring, line 116 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 116 */ + if (!r_R1(z)) + return 0; /* call R1, line 116 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_from_s(z, 4, s_29); /* <-, line 117 */ + break; + case 2: + slice_from_s(z, 3, s_30); /* <-, line 118 */ + break; + case 3: + slice_from_s(z, 2, s_31); /* <-, line 119 */ + break; + case 4: + slice_from_s(z, 2, s_32); /* <-, line 121 */ + break; + case 5: + slice_del(z); /* delete, line 123 */ + break; + case 6: + if (!r_R2(z)) + return 0; /* call R2, line 125 */ + slice_del(z); /* delete, line 125 */ + break; + } + return 1; +} + +static int +r_Step_4(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 130 */ + among_var = find_among_b(z, a_6, 18); /* substring, line 130 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 130 */ + if (!r_R2(z)) + return 0; /* call R2, line 130 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 133 */ + break; + case 2: + { + int m = z->l - z->c; /* or, line 134 */ + + if (!(eq_s_b(z, 1, s_33))) + goto lab1; + goto lab0; + lab1: + z->c = z->l - m; + if (!(eq_s_b(z, 1, s_34))) + return 0; + } + lab0: + slice_del(z); /* delete, line 134 */ + break; + } + return 1; +} + +static int +r_Step_5(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 139 */ + among_var = find_among_b(z, a_7, 2); /* substring, line 139 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 139 */ + switch (among_var) + { + case 0: + return 0; + case 1: + { + int m = z->l - z->c; /* or, line 140 */ + + if (!r_R2(z)) + goto lab1; /* call R2, line 140 */ + goto lab0; + lab1: + z->c = z->l - m; + if (!r_R1(z)) + return 0; /* call R1, line 140 */ + { + int m = z->l - z->c; /* not, line 140 */ + + if (!r_shortv(z)) + goto lab2; /* call shortv, line 140 */ + return 0; + lab2: + z->c = z->l - m; + } + } + lab0: + slice_del(z); /* delete, line 140 */ + break; + case 2: + if (!r_R2(z)) + return 0; /* call R2, line 141 */ + if (!(eq_s_b(z, 1, s_35))) + return 0; + slice_del(z); /* delete, line 141 */ + break; + } + return 1; +} + +static int +r_exception2(struct SN_env * z) +{ + z->ket = z->c; /* [, line 147 */ + if (!(find_among_b(z, a_8, 8))) + return 0; /* substring, line 147 */ + z->bra = z->c; /* ], line 147 */ + if (z->c > z->lb) + return 0; /* atlimit, line 147 */ + return 1; +} + +static int +r_exception1(struct SN_env * z) +{ + int among_var; + + z->bra = z->c; /* [, line 159 */ + among_var = find_among(z, a_9, 18); /* substring, line 159 */ + if (!(among_var)) + return 0; + z->ket = z->c; /* ], line 159 */ + if (z->c < z->l) + return 0; /* atlimit, line 159 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_from_s(z, 3, s_36); /* <-, line 163 */ + break; + case 2: + slice_from_s(z, 3, s_37); /* <-, line 164 */ + break; + case 3: + slice_from_s(z, 3, s_38); /* <-, line 165 */ + break; + case 4: + slice_from_s(z, 3, s_39); /* <-, line 166 */ + break; + case 5: + slice_from_s(z, 3, s_40); /* <-, line 167 */ + break; + case 6: + slice_from_s(z, 3, s_41); /* <-, line 171 */ + break; + case 7: + slice_from_s(z, 5, s_42); /* <-, line 172 */ + break; + case 8: + slice_from_s(z, 4, s_43); /* <-, line 173 */ + break; + case 9: + slice_from_s(z, 5, s_44); /* <-, line 174 */ + break; + case 10: + slice_from_s(z, 4, s_45); /* <-, line 175 */ + break; + case 11: + slice_from_s(z, 5, s_46); /* <-, line 176 */ + break; + } + return 1; +} + +static int +r_postlude(struct SN_env * z) +{ + if (!(z->B[0])) + return 0; /* Boolean test Y_found, line 192 */ + while (1) + { /* repeat, line 192 */ + int c = z->c; + + while (1) + { /* goto, line 192 */ + int c = z->c; + + z->bra = z->c; /* [, line 192 */ + if (!(eq_s(z, 1, s_47))) + goto lab1; + z->ket = z->c; /* ], line 192 */ + z->c = c; + break; + lab1: + z->c = c; + if (z->c >= z->l) + goto lab0; + z->c++; + } + slice_from_s(z, 1, s_48); /* <-, line 192 */ + continue; +lab0: + z->c = c; + break; + } + return 1; +} + +extern int +english_stem(struct SN_env * z) +{ + { + int c = z->c; /* or, line 196 */ + + if (!r_exception1(z)) + goto lab1; /* call exception1, line 196 */ + goto lab0; +lab1: + z->c = c; + { + int c_test = z->c; /* test, line 198 */ + + { + int c = z->c + 3; + + if (0 > c || c > z->l) + return 0; + z->c = c; /* hop, line 198 */ + } + z->c = c_test; + } + { + int c = z->c; /* do, line 199 */ + + if (!r_prelude(z)) + goto lab2; /* call prelude, line 199 */ + lab2: + z->c = c; + } + { + int c = z->c; /* do, line 200 */ + + if (!r_mark_regions(z)) + goto lab3; /* call mark_regions, line 200 */ + lab3: + z->c = c; + } + z->lb = z->c; + z->c = z->l; /* backwards, line 201 */ + + { + int m = z->l - z->c; /* do, line 203 */ + + if (!r_Step_1a(z)) + goto lab4; /* call Step_1a, line 203 */ + lab4: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* or, line 205 */ + + if (!r_exception2(z)) + goto lab6; /* call exception2, line 205 */ + goto lab5; + lab6: + z->c = z->l - m; + { + int m = z->l - z->c; /* do, line 207 */ + + if (!r_Step_1b(z)) + goto lab7; /* call Step_1b, line 207 */ + lab7: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 208 */ + + if (!r_Step_1c(z)) + goto lab8; /* call Step_1c, line 208 */ + lab8: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 210 */ + + if (!r_Step_2(z)) + goto lab9; /* call Step_2, line 210 */ + lab9: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 211 */ + + if (!r_Step_3(z)) + goto lab10; /* call Step_3, line 211 */ + lab10: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 212 */ + + if (!r_Step_4(z)) + goto lab11; /* call Step_4, line 212 */ + lab11: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 214 */ + + if (!r_Step_5(z)) + goto lab12; /* call Step_5, line 214 */ + lab12: + z->c = z->l - m; + } + } +lab5: + z->c = z->lb; + { + int c = z->c; /* do, line 217 */ + + if (!r_postlude(z)) + goto lab13; /* call postlude, line 217 */ + lab13: + z->c = c; + } + } +lab0: + return 1; +} + +extern struct SN_env * +english_create_env(void) +{ + return SN_create_env(0, 2, 1); +} + +extern void +english_close_env(struct SN_env * z) +{ + SN_close_env(z); +} diff --git a/contrib/tsearch2/snowball/english_stem.h b/contrib/tsearch2/snowball/english_stem.h new file mode 100644 index 0000000..7a52f9c --- /dev/null +++ b/contrib/tsearch2/snowball/english_stem.h @@ -0,0 +1,7 @@ + +/* This file was generated automatically by the Snowball to ANSI C compiler */ + +extern struct SN_env *english_create_env(void); +extern void english_close_env(struct SN_env * z); + +extern int english_stem(struct SN_env * z); diff --git a/contrib/tsearch2/snowball/header.h b/contrib/tsearch2/snowball/header.h new file mode 100644 index 0000000..4d4f127 --- /dev/null +++ b/contrib/tsearch2/snowball/header.h @@ -0,0 +1,51 @@ +#include "api.h" + +#define HEAD 2*sizeof(int) + +#define SIZE(p) ((int *)(p))[-1] +#define SET_SIZE(p, n) ((int *)(p))[-1] = n +#define CAPACITY(p) ((int *)(p))[-2] + +struct among +{ + int s_size; /* number of chars in string */ + symbol *s; /* search string */ + int substring_i; /* index to longest matching substring */ + int result; /* result of the lookup */ + int (*function) (struct SN_env *); +}; + +extern symbol *create_s(void); +extern void lose_s(symbol * p); + +extern int in_grouping(struct SN_env * z, unsigned char *s, int min, int max); +extern int in_grouping_b(struct SN_env * z, unsigned char *s, int min, int max); +extern int out_grouping(struct SN_env * z, unsigned char *s, int min, int max); +extern int out_grouping_b(struct SN_env * z, unsigned char *s, int min, int max); + +extern int in_range(struct SN_env * z, int min, int max); +extern int in_range_b(struct SN_env * z, int min, int max); +extern int out_range(struct SN_env * z, int min, int max); +extern int out_range_b(struct SN_env * z, int min, int max); + +extern int eq_s(struct SN_env * z, int s_size, symbol * s); +extern int eq_s_b(struct SN_env * z, int s_size, symbol * s); +extern int eq_v(struct SN_env * z, symbol * p); +extern int eq_v_b(struct SN_env * z, symbol * p); + +extern int find_among(struct SN_env * z, struct among * v, int v_size); +extern int find_among_b(struct SN_env * z, struct among * v, int v_size); + +extern symbol *increase_size(symbol * p, int n); +extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s); +extern void slice_from_s(struct SN_env * z, int s_size, symbol * s); +extern void slice_from_v(struct SN_env * z, symbol * p); +extern void slice_del(struct SN_env * z); + +extern void insert_s(struct SN_env * z, int bra, int ket, int s_size, symbol * s); +extern void insert_v(struct SN_env * z, int bra, int ket, symbol * p); + +extern symbol *slice_to(struct SN_env * z, symbol * p); +extern symbol *assign_to(struct SN_env * z, symbol * p); + +extern void debug(struct SN_env * z, int number, int line_count); diff --git a/contrib/tsearch2/snowball/russian_stem.c b/contrib/tsearch2/snowball/russian_stem.c new file mode 100644 index 0000000..bbbddd8 --- /dev/null +++ b/contrib/tsearch2/snowball/russian_stem.c @@ -0,0 +1,766 @@ + +/* This file was generated automatically by the Snowball to ANSI C compiler */ + +#include "header.h" + +extern int russian_stem(struct SN_env * z); +static int r_tidy_up(struct SN_env * z); +static int r_derivational(struct SN_env * z); +static int r_noun(struct SN_env * z); +static int r_verb(struct SN_env * z); +static int r_reflexive(struct SN_env * z); +static int r_adjectival(struct SN_env * z); +static int r_adjective(struct SN_env * z); +static int r_perfective_gerund(struct SN_env * z); +static int r_R2(struct SN_env * z); +static int r_mark_regions(struct SN_env * z); + +extern struct SN_env *russian_create_env(void); +extern void russian_close_env(struct SN_env * z); + +static symbol s_0_0[3] = {215, 219, 201}; +static symbol s_0_1[4] = {201, 215, 219, 201}; +static symbol s_0_2[4] = {217, 215, 219, 201}; +static symbol s_0_3[1] = {215}; +static symbol s_0_4[2] = {201, 215}; +static symbol s_0_5[2] = {217, 215}; +static symbol s_0_6[5] = {215, 219, 201, 211, 216}; +static symbol s_0_7[6] = {201, 215, 219, 201, 211, 216}; +static symbol s_0_8[6] = {217, 215, 219, 201, 211, 216}; + +static struct among a_0[9] = +{ + /* 0 */ {3, s_0_0, -1, 1, 0}, + /* 1 */ {4, s_0_1, 0, 2, 0}, + /* 2 */ {4, s_0_2, 0, 2, 0}, + /* 3 */ {1, s_0_3, -1, 1, 0}, + /* 4 */ {2, s_0_4, 3, 2, 0}, + /* 5 */ {2, s_0_5, 3, 2, 0}, + /* 6 */ {5, s_0_6, -1, 1, 0}, + /* 7 */ {6, s_0_7, 6, 2, 0}, + /* 8 */ {6, s_0_8, 6, 2, 0} +}; + +static symbol s_1_0[2] = {192, 192}; +static symbol s_1_1[2] = {197, 192}; +static symbol s_1_2[2] = {207, 192}; +static symbol s_1_3[2] = {213, 192}; +static symbol s_1_4[2] = {197, 197}; +static symbol s_1_5[2] = {201, 197}; +static symbol s_1_6[2] = {207, 197}; +static symbol s_1_7[2] = {217, 197}; +static symbol s_1_8[2] = {201, 200}; +static symbol s_1_9[2] = {217, 200}; +static symbol s_1_10[3] = {201, 205, 201}; +static symbol s_1_11[3] = {217, 205, 201}; +static symbol s_1_12[2] = {197, 202}; +static symbol s_1_13[2] = {201, 202}; +static symbol s_1_14[2] = {207, 202}; +static symbol s_1_15[2] = {217, 202}; +static symbol s_1_16[2] = {197, 205}; +static symbol s_1_17[2] = {201, 205}; +static symbol s_1_18[2] = {207, 205}; +static symbol s_1_19[2] = {217, 205}; +static symbol s_1_20[3] = {197, 199, 207}; +static symbol s_1_21[3] = {207, 199, 207}; +static symbol s_1_22[2] = {193, 209}; +static symbol s_1_23[2] = {209, 209}; +static symbol s_1_24[3] = {197, 205, 213}; +static symbol s_1_25[3] = {207, 205, 213}; + +static struct among a_1[26] = +{ + /* 0 */ {2, s_1_0, -1, 1, 0}, + /* 1 */ {2, s_1_1, -1, 1, 0}, + /* 2 */ {2, s_1_2, -1, 1, 0}, + /* 3 */ {2, s_1_3, -1, 1, 0}, + /* 4 */ {2, s_1_4, -1, 1, 0}, + /* 5 */ {2, s_1_5, -1, 1, 0}, + /* 6 */ {2, s_1_6, -1, 1, 0}, + /* 7 */ {2, s_1_7, -1, 1, 0}, + /* 8 */ {2, s_1_8, -1, 1, 0}, + /* 9 */ {2, s_1_9, -1, 1, 0}, + /* 10 */ {3, s_1_10, -1, 1, 0}, + /* 11 */ {3, s_1_11, -1, 1, 0}, + /* 12 */ {2, s_1_12, -1, 1, 0}, + /* 13 */ {2, s_1_13, -1, 1, 0}, + /* 14 */ {2, s_1_14, -1, 1, 0}, + /* 15 */ {2, s_1_15, -1, 1, 0}, + /* 16 */ {2, s_1_16, -1, 1, 0}, + /* 17 */ {2, s_1_17, -1, 1, 0}, + /* 18 */ {2, s_1_18, -1, 1, 0}, + /* 19 */ {2, s_1_19, -1, 1, 0}, + /* 20 */ {3, s_1_20, -1, 1, 0}, + /* 21 */ {3, s_1_21, -1, 1, 0}, + /* 22 */ {2, s_1_22, -1, 1, 0}, + /* 23 */ {2, s_1_23, -1, 1, 0}, + /* 24 */ {3, s_1_24, -1, 1, 0}, + /* 25 */ {3, s_1_25, -1, 1, 0} +}; + +static symbol s_2_0[2] = {197, 205}; +static symbol s_2_1[2] = {206, 206}; +static symbol s_2_2[2] = {215, 219}; +static symbol s_2_3[3] = {201, 215, 219}; +static symbol s_2_4[3] = {217, 215, 219}; +static symbol s_2_5[1] = {221}; +static symbol s_2_6[2] = {192, 221}; +static symbol s_2_7[3] = {213, 192, 221}; + +static struct among a_2[8] = +{ + /* 0 */ {2, s_2_0, -1, 1, 0}, + /* 1 */ {2, s_2_1, -1, 1, 0}, + /* 2 */ {2, s_2_2, -1, 1, 0}, + /* 3 */ {3, s_2_3, 2, 2, 0}, + /* 4 */ {3, s_2_4, 2, 2, 0}, + /* 5 */ {1, s_2_5, -1, 1, 0}, + /* 6 */ {2, s_2_6, 5, 1, 0}, + /* 7 */ {3, s_2_7, 6, 2, 0} +}; + +static symbol s_3_0[2] = {211, 209}; +static symbol s_3_1[2] = {211, 216}; + +static struct among a_3[2] = +{ + /* 0 */ {2, s_3_0, -1, 1, 0}, + /* 1 */ {2, s_3_1, -1, 1, 0} +}; + +static symbol s_4_0[1] = {192}; +static symbol s_4_1[2] = {213, 192}; +static symbol s_4_2[2] = {204, 193}; +static symbol s_4_3[3] = {201, 204, 193}; +static symbol s_4_4[3] = {217, 204, 193}; +static symbol s_4_5[2] = {206, 193}; +static symbol s_4_6[3] = {197, 206, 193}; +static symbol s_4_7[3] = {197, 212, 197}; +static symbol s_4_8[3] = {201, 212, 197}; +static symbol s_4_9[3] = {202, 212, 197}; +static symbol s_4_10[4] = {197, 202, 212, 197}; +static symbol s_4_11[4] = {213, 202, 212, 197}; +static symbol s_4_12[2] = {204, 201}; +static symbol s_4_13[3] = {201, 204, 201}; +static symbol s_4_14[3] = {217, 204, 201}; +static symbol s_4_15[1] = {202}; +static symbol s_4_16[2] = {197, 202}; +static symbol s_4_17[2] = {213, 202}; +static symbol s_4_18[1] = {204}; +static symbol s_4_19[2] = {201, 204}; +static symbol s_4_20[2] = {217, 204}; +static symbol s_4_21[2] = {197, 205}; +static symbol s_4_22[2] = {201, 205}; +static symbol s_4_23[2] = {217, 205}; +static symbol s_4_24[1] = {206}; +static symbol s_4_25[2] = {197, 206}; +static symbol s_4_26[2] = {204, 207}; +static symbol s_4_27[3] = {201, 204, 207}; +static symbol s_4_28[3] = {217, 204, 207}; +static symbol s_4_29[2] = {206, 207}; +static symbol s_4_30[3] = {197, 206, 207}; +static symbol s_4_31[3] = {206, 206, 207}; +static symbol s_4_32[2] = {192, 212}; +static symbol s_4_33[3] = {213, 192, 212}; +static symbol s_4_34[2] = {197, 212}; +static symbol s_4_35[3] = {213, 197, 212}; +static symbol s_4_36[2] = {201, 212}; +static symbol s_4_37[2] = {209, 212}; +static symbol s_4_38[2] = {217, 212}; +static symbol s_4_39[2] = {212, 216}; +static symbol s_4_40[3] = {201, 212, 216}; +static symbol s_4_41[3] = {217, 212, 216}; +static symbol s_4_42[3] = {197, 219, 216}; +static symbol s_4_43[3] = {201, 219, 216}; +static symbol s_4_44[2] = {206, 217}; +static symbol s_4_45[3] = {197, 206, 217}; + +static struct among a_4[46] = +{ + /* 0 */ {1, s_4_0, -1, 2, 0}, + /* 1 */ {2, s_4_1, 0, 2, 0}, + /* 2 */ {2, s_4_2, -1, 1, 0}, + /* 3 */ {3, s_4_3, 2, 2, 0}, + /* 4 */ {3, s_4_4, 2, 2, 0}, + /* 5 */ {2, s_4_5, -1, 1, 0}, + /* 6 */ {3, s_4_6, 5, 2, 0}, + /* 7 */ {3, s_4_7, -1, 1, 0}, + /* 8 */ {3, s_4_8, -1, 2, 0}, + /* 9 */ {3, s_4_9, -1, 1, 0}, + /* 10 */ {4, s_4_10, 9, 2, 0}, + /* 11 */ {4, s_4_11, 9, 2, 0}, + /* 12 */ {2, s_4_12, -1, 1, 0}, + /* 13 */ {3, s_4_13, 12, 2, 0}, + /* 14 */ {3, s_4_14, 12, 2, 0}, + /* 15 */ {1, s_4_15, -1, 1, 0}, + /* 16 */ {2, s_4_16, 15, 2, 0}, + /* 17 */ {2, s_4_17, 15, 2, 0}, + /* 18 */ {1, s_4_18, -1, 1, 0}, + /* 19 */ {2, s_4_19, 18, 2, 0}, + /* 20 */ {2, s_4_20, 18, 2, 0}, + /* 21 */ {2, s_4_21, -1, 1, 0}, + /* 22 */ {2, s_4_22, -1, 2, 0}, + /* 23 */ {2, s_4_23, -1, 2, 0}, + /* 24 */ {1, s_4_24, -1, 1, 0}, + /* 25 */ {2, s_4_25, 24, 2, 0}, + /* 26 */ {2, s_4_26, -1, 1, 0}, + /* 27 */ {3, s_4_27, 26, 2, 0}, + /* 28 */ {3, s_4_28, 26, 2, 0}, + /* 29 */ {2, s_4_29, -1, 1, 0}, + /* 30 */ {3, s_4_30, 29, 2, 0}, + /* 31 */ {3, s_4_31, 29, 1, 0}, + /* 32 */ {2, s_4_32, -1, 1, 0}, + /* 33 */ {3, s_4_33, 32, 2, 0}, + /* 34 */ {2, s_4_34, -1, 1, 0}, + /* 35 */ {3, s_4_35, 34, 2, 0}, + /* 36 */ {2, s_4_36, -1, 2, 0}, + /* 37 */ {2, s_4_37, -1, 2, 0}, + /* 38 */ {2, s_4_38, -1, 2, 0}, + /* 39 */ {2, s_4_39, -1, 1, 0}, + /* 40 */ {3, s_4_40, 39, 2, 0}, + /* 41 */ {3, s_4_41, 39, 2, 0}, + /* 42 */ {3, s_4_42, -1, 1, 0}, + /* 43 */ {3, s_4_43, -1, 2, 0}, + /* 44 */ {2, s_4_44, -1, 1, 0}, + /* 45 */ {3, s_4_45, 44, 2, 0} +}; + +static symbol s_5_0[1] = {192}; +static symbol s_5_1[2] = {201, 192}; +static symbol s_5_2[2] = {216, 192}; +static symbol s_5_3[1] = {193}; +static symbol s_5_4[1] = {197}; +static symbol s_5_5[2] = {201, 197}; +static symbol s_5_6[2] = {216, 197}; +static symbol s_5_7[2] = {193, 200}; +static symbol s_5_8[2] = {209, 200}; +static symbol s_5_9[3] = {201, 209, 200}; +static symbol s_5_10[1] = {201}; +static symbol s_5_11[2] = {197, 201}; +static symbol s_5_12[2] = {201, 201}; +static symbol s_5_13[3] = {193, 205, 201}; +static symbol s_5_14[3] = {209, 205, 201}; +static symbol s_5_15[4] = {201, 209, 205, 201}; +static symbol s_5_16[1] = {202}; +static symbol s_5_17[2] = {197, 202}; +static symbol s_5_18[3] = {201, 197, 202}; +static symbol s_5_19[2] = {201, 202}; +static symbol s_5_20[2] = {207, 202}; +static symbol s_5_21[2] = {193, 205}; +static symbol s_5_22[2] = {197, 205}; +static symbol s_5_23[3] = {201, 197, 205}; +static symbol s_5_24[2] = {207, 205}; +static symbol s_5_25[2] = {209, 205}; +static symbol s_5_26[3] = {201, 209, 205}; +static symbol s_5_27[1] = {207}; +static symbol s_5_28[1] = {209}; +static symbol s_5_29[2] = {201, 209}; +static symbol s_5_30[2] = {216, 209}; +static symbol s_5_31[1] = {213}; +static symbol s_5_32[2] = {197, 215}; +static symbol s_5_33[2] = {207, 215}; +static symbol s_5_34[1] = {216}; +static symbol s_5_35[1] = {217}; + +static struct among a_5[36] = +{ + /* 0 */ {1, s_5_0, -1, 1, 0}, + /* 1 */ {2, s_5_1, 0, 1, 0}, + /* 2 */ {2, s_5_2, 0, 1, 0}, + /* 3 */ {1, s_5_3, -1, 1, 0}, + /* 4 */ {1, s_5_4, -1, 1, 0}, + /* 5 */ {2, s_5_5, 4, 1, 0}, + /* 6 */ {2, s_5_6, 4, 1, 0}, + /* 7 */ {2, s_5_7, -1, 1, 0}, + /* 8 */ {2, s_5_8, -1, 1, 0}, + /* 9 */ {3, s_5_9, 8, 1, 0}, + /* 10 */ {1, s_5_10, -1, 1, 0}, + /* 11 */ {2, s_5_11, 10, 1, 0}, + /* 12 */ {2, s_5_12, 10, 1, 0}, + /* 13 */ {3, s_5_13, 10, 1, 0}, + /* 14 */ {3, s_5_14, 10, 1, 0}, + /* 15 */ {4, s_5_15, 14, 1, 0}, + /* 16 */ {1, s_5_16, -1, 1, 0}, + /* 17 */ {2, s_5_17, 16, 1, 0}, + /* 18 */ {3, s_5_18, 17, 1, 0}, + /* 19 */ {2, s_5_19, 16, 1, 0}, + /* 20 */ {2, s_5_20, 16, 1, 0}, + /* 21 */ {2, s_5_21, -1, 1, 0}, + /* 22 */ {2, s_5_22, -1, 1, 0}, + /* 23 */ {3, s_5_23, 22, 1, 0}, + /* 24 */ {2, s_5_24, -1, 1, 0}, + /* 25 */ {2, s_5_25, -1, 1, 0}, + /* 26 */ {3, s_5_26, 25, 1, 0}, + /* 27 */ {1, s_5_27, -1, 1, 0}, + /* 28 */ {1, s_5_28, -1, 1, 0}, + /* 29 */ {2, s_5_29, 28, 1, 0}, + /* 30 */ {2, s_5_30, 28, 1, 0}, + /* 31 */ {1, s_5_31, -1, 1, 0}, + /* 32 */ {2, s_5_32, -1, 1, 0}, + /* 33 */ {2, s_5_33, -1, 1, 0}, + /* 34 */ {1, s_5_34, -1, 1, 0}, + /* 35 */ {1, s_5_35, -1, 1, 0} +}; + +static symbol s_6_0[3] = {207, 211, 212}; +static symbol s_6_1[4] = {207, 211, 212, 216}; + +static struct among a_6[2] = +{ + /* 0 */ {3, s_6_0, -1, 1, 0}, + /* 1 */ {4, s_6_1, -1, 1, 0} +}; + +static symbol s_7_0[4] = {197, 202, 219, 197}; +static symbol s_7_1[1] = {206}; +static symbol s_7_2[1] = {216}; +static symbol s_7_3[3] = {197, 202, 219}; + +static struct among a_7[4] = +{ + /* 0 */ {4, s_7_0, -1, 1, 0}, + /* 1 */ {1, s_7_1, -1, 2, 0}, + /* 2 */ {1, s_7_2, -1, 3, 0}, + /* 3 */ {3, s_7_3, -1, 1, 0} +}; + +static unsigned char g_v[] = {35, 130, 34, 18}; + +static symbol s_0[] = {193}; +static symbol s_1[] = {209}; +static symbol s_2[] = {193}; +static symbol s_3[] = {209}; +static symbol s_4[] = {193}; +static symbol s_5[] = {209}; +static symbol s_6[] = {206}; +static symbol s_7[] = {206}; +static symbol s_8[] = {206}; +static symbol s_9[] = {201}; + +static int +r_mark_regions(struct SN_env * z) +{ + z->I[0] = z->l; + z->I[1] = z->l; + { + int c = z->c; /* do, line 100 */ + + while (1) + { /* gopast, line 101 */ + if (!(in_grouping(z, g_v, 192, 220))) + goto lab1; + break; + lab1: + if (z->c >= z->l) + goto lab0; + z->c++; + } + z->I[0] = z->c; /* setmark pV, line 101 */ + while (1) + { /* gopast, line 101 */ + if (!(out_grouping(z, g_v, 192, 220))) + goto lab2; + break; + lab2: + if (z->c >= z->l) + goto lab0; + z->c++; + } + while (1) + { /* gopast, line 102 */ + if (!(in_grouping(z, g_v, 192, 220))) + goto lab3; + break; + lab3: + if (z->c >= z->l) + goto lab0; + z->c++; + } + while (1) + { /* gopast, line 102 */ + if (!(out_grouping(z, g_v, 192, 220))) + goto lab4; + break; + lab4: + if (z->c >= z->l) + goto lab0; + z->c++; + } + z->I[1] = z->c; /* setmark p2, line 102 */ +lab0: + z->c = c; + } + return 1; +} + +static int +r_R2(struct SN_env * z) +{ + if (!(z->I[1] <= z->c)) + return 0; + return 1; +} + +static int +r_perfective_gerund(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 111 */ + among_var = find_among_b(z, a_0, 9); /* substring, line 111 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 111 */ + switch (among_var) + { + case 0: + return 0; + case 1: + { + int m = z->l - z->c; /* or, line 115 */ + + if (!(eq_s_b(z, 1, s_0))) + goto lab1; + goto lab0; + lab1: + z->c = z->l - m; + if (!(eq_s_b(z, 1, s_1))) + return 0; + } + lab0: + slice_del(z); /* delete, line 115 */ + break; + case 2: + slice_del(z); /* delete, line 122 */ + break; + } + return 1; +} + +static int +r_adjective(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 127 */ + among_var = find_among_b(z, a_1, 26); /* substring, line 127 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 127 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 136 */ + break; + } + return 1; +} + +static int +r_adjectival(struct SN_env * z) +{ + int among_var; + + if (!r_adjective(z)) + return 0; /* call adjective, line 141 */ + { + int m = z->l - z->c; /* try, line 148 */ + + z->ket = z->c; /* [, line 149 */ + among_var = find_among_b(z, a_2, 8); /* substring, line 149 */ + if (!(among_var)) + { + z->c = z->l - m; + goto lab0; + } + z->bra = z->c; /* ], line 149 */ + switch (among_var) + { + case 0: + { + z->c = z->l - m; + goto lab0; + } + case 1: + { + int m = z->l - z->c; /* or, line 154 */ + + if (!(eq_s_b(z, 1, s_2))) + goto lab2; + goto lab1; + lab2: + z->c = z->l - m; + if (!(eq_s_b(z, 1, s_3))) + { + z->c = z->l - m; + goto lab0; + } + } + lab1: + slice_del(z); /* delete, line 154 */ + break; + case 2: + slice_del(z); /* delete, line 161 */ + break; + } +lab0: + ; + } + return 1; +} + +static int +r_reflexive(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 168 */ + among_var = find_among_b(z, a_3, 2); /* substring, line 168 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 168 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 171 */ + break; + } + return 1; +} + +static int +r_verb(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 176 */ + among_var = find_among_b(z, a_4, 46); /* substring, line 176 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 176 */ + switch (among_var) + { + case 0: + return 0; + case 1: + { + int m = z->l - z->c; /* or, line 182 */ + + if (!(eq_s_b(z, 1, s_4))) + goto lab1; + goto lab0; + lab1: + z->c = z->l - m; + if (!(eq_s_b(z, 1, s_5))) + return 0; + } + lab0: + slice_del(z); /* delete, line 182 */ + break; + case 2: + slice_del(z); /* delete, line 190 */ + break; + } + return 1; +} + +static int +r_noun(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 199 */ + among_var = find_among_b(z, a_5, 36); /* substring, line 199 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 199 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 206 */ + break; + } + return 1; +} + +static int +r_derivational(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 215 */ + among_var = find_among_b(z, a_6, 2); /* substring, line 215 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 215 */ + if (!r_R2(z)) + return 0; /* call R2, line 215 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 218 */ + break; + } + return 1; +} + +static int +r_tidy_up(struct SN_env * z) +{ + int among_var; + + z->ket = z->c; /* [, line 223 */ + among_var = find_among_b(z, a_7, 4); /* substring, line 223 */ + if (!(among_var)) + return 0; + z->bra = z->c; /* ], line 223 */ + switch (among_var) + { + case 0: + return 0; + case 1: + slice_del(z); /* delete, line 227 */ + z->ket = z->c; /* [, line 228 */ + if (!(eq_s_b(z, 1, s_6))) + return 0; + z->bra = z->c; /* ], line 228 */ + if (!(eq_s_b(z, 1, s_7))) + return 0; + slice_del(z); /* delete, line 228 */ + break; + case 2: + if (!(eq_s_b(z, 1, s_8))) + return 0; + slice_del(z); /* delete, line 231 */ + break; + case 3: + slice_del(z); /* delete, line 233 */ + break; + } + return 1; +} + +extern int +russian_stem(struct SN_env * z) +{ + { + int c = z->c; /* do, line 240 */ + + if (!r_mark_regions(z)) + goto lab0; /* call mark_regions, line 240 */ +lab0: + z->c = c; + } + z->lb = z->c; + z->c = z->l; /* backwards, line 241 */ + + { + int m = z->l - z->c; /* setlimit, line 241 */ + int m3; + + if (z->c < z->I[0]) + return 0; + z->c = z->I[0]; /* tomark, line 241 */ + m3 = z->lb; + z->lb = z->c; + z->c = z->l - m; + { + int m = z->l - z->c; /* do, line 242 */ + + { + int m = z->l - z->c; /* or, line 243 */ + + if (!r_perfective_gerund(z)) + goto lab3; /* call perfective_gerund, line 243 */ + goto lab2; + lab3: + z->c = z->l - m; + { + int m = z->l - z->c; /* try, line 244 */ + + if (!r_reflexive(z)) + { + z->c = z->l - m; + goto lab4; + } /* call reflexive, line 244 */ + lab4: + ; + } + { + int m = z->l - z->c; /* or, line 245 */ + + if (!r_adjectival(z)) + goto lab6; /* call adjectival, line 245 */ + goto lab5; + lab6: + z->c = z->l - m; + if (!r_verb(z)) + goto lab7; /* call verb, line 245 */ + goto lab5; + lab7: + z->c = z->l - m; + if (!r_noun(z)) + goto lab1; /* call noun, line 245 */ + } + lab5: + ; + } + lab2: + lab1: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* try, line 248 */ + + z->ket = z->c; /* [, line 248 */ + if (!(eq_s_b(z, 1, s_9))) + { + z->c = z->l - m; + goto lab8; + } + z->bra = z->c; /* ], line 248 */ + slice_del(z); /* delete, line 248 */ + lab8: + ; + } + { + int m = z->l - z->c; /* do, line 251 */ + + if (!r_derivational(z)) + goto lab9; /* call derivational, line 251 */ + lab9: + z->c = z->l - m; + } + { + int m = z->l - z->c; /* do, line 252 */ + + if (!r_tidy_up(z)) + goto lab10; /* call tidy_up, line 252 */ + lab10: + z->c = z->l - m; + } + z->lb = m3; + } + z->c = z->lb; + return 1; +} + +extern struct SN_env * +russian_create_env(void) +{ + return SN_create_env(0, 2, 0); +} + +extern void +russian_close_env(struct SN_env * z) +{ + SN_close_env(z); +} diff --git a/contrib/tsearch2/snowball/russian_stem.h b/contrib/tsearch2/snowball/russian_stem.h new file mode 100644 index 0000000..69369e2 --- /dev/null +++ b/contrib/tsearch2/snowball/russian_stem.h @@ -0,0 +1,7 @@ + +/* This file was generated automatically by the Snowball to ANSI C compiler */ + +extern struct SN_env *russian_create_env(void); +extern void russian_close_env(struct SN_env * z); + +extern int russian_stem(struct SN_env * z); diff --git a/contrib/tsearch2/snowball/utilities.c b/contrib/tsearch2/snowball/utilities.c new file mode 100644 index 0000000..4ec71dc --- /dev/null +++ b/contrib/tsearch2/snowball/utilities.c @@ -0,0 +1,516 @@ + +#include +#include +#include + +#include "header.h" + +#define unless(C) if(!(C)) + +#define CREATE_SIZE 1 + +extern symbol * +create_s(void) +{ + symbol *p = (symbol *) (HEAD + (char *) malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol))); + + CAPACITY(p) = CREATE_SIZE; + SET_SIZE(p, CREATE_SIZE); + return p; +} + +extern void +lose_s(symbol * p) +{ + free((char *) p - HEAD); +} + +extern int +in_grouping(struct SN_env * z, unsigned char *s, int min, int max) +{ + if (z->c >= z->l) + return 0; + { + int ch = z->p[z->c]; + + if + (ch > max || (ch -= min) < 0 || + (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) + return 0; + } + z->c++; + return 1; +} + +extern int +in_grouping_b(struct SN_env * z, unsigned char *s, int min, int max) +{ + if (z->c <= z->lb) + return 0; + { + int ch = z->p[z->c - 1]; + + if + (ch > max || (ch -= min) < 0 || + (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) + return 0; + } + z->c--; + return 1; +} + +extern int +out_grouping(struct SN_env * z, unsigned char *s, int min, int max) +{ + if (z->c >= z->l) + return 0; + { + int ch = z->p[z->c]; + + unless + (ch > max || (ch -= min) < 0 || + (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; + } + z->c++; + return 1; +} + +extern int +out_grouping_b(struct SN_env * z, unsigned char *s, int min, int max) +{ + if (z->c <= z->lb) + return 0; + { + int ch = z->p[z->c - 1]; + + unless + (ch > max || (ch -= min) < 0 || + (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 0; + } + z->c--; + return 1; +} + + +extern int +in_range(struct SN_env * z, int min, int max) +{ + if (z->c >= z->l) + return 0; + { + int ch = z->p[z->c]; + + if + (ch > max || ch < min) + return 0; + } + z->c++; + return 1; +} + +extern int +in_range_b(struct SN_env * z, int min, int max) +{ + if (z->c <= z->lb) + return 0; + { + int ch = z->p[z->c - 1]; + + if + (ch > max || ch < min) + return 0; + } + z->c--; + return 1; +} + +extern int +out_range(struct SN_env * z, int min, int max) +{ + if (z->c >= z->l) + return 0; + { + int ch = z->p[z->c]; + + unless + (ch > max || ch < min) return 0; + } + z->c++; + return 1; +} + +extern int +out_range_b(struct SN_env * z, int min, int max) +{ + if (z->c <= z->lb) + return 0; + { + int ch = z->p[z->c - 1]; + + unless + (ch > max || ch < min) return 0; + } + z->c--; + return 1; +} + +extern int +eq_s(struct SN_env * z, int s_size, symbol * s) +{ + if (z->l - z->c < s_size || + memcmp(z->p + z->c, s, s_size * sizeof(symbol)) != 0) + return 0; + z->c += s_size; + return 1; +} + +extern int +eq_s_b(struct SN_env * z, int s_size, symbol * s) +{ + if (z->c - z->lb < s_size || + memcmp(z->p + z->c - s_size, s, s_size * sizeof(symbol)) != 0) + return 0; + z->c -= s_size; + return 1; +} + +extern int +eq_v(struct SN_env * z, symbol * p) +{ + return eq_s(z, SIZE(p), p); +} + +extern int +eq_v_b(struct SN_env * z, symbol * p) +{ + return eq_s_b(z, SIZE(p), p); +} + +extern int +find_among(struct SN_env * z, struct among * v, int v_size) +{ + int i = 0; + int j = v_size; + + int c = z->c; + int l = z->l; + symbol *q = z->p + c; + + struct among *w; + + int common_i = 0; + int common_j = 0; + + int first_key_inspected = 0; + + while (1) + { + int k = i + ((j - i) >> 1); + int diff = 0; + int common = common_i < common_j ? common_i : common_j; /* smaller */ + + w = v + k; + { + int i; + + for (i = common; i < w->s_size; i++) + { + if (c + common == l) + { + diff = -1; + break; + } + diff = q[common] - w->s[i]; + if (diff != 0) + break; + common++; + } + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) + break; /* v->s has been inspected */ + if (j == i) + break; /* only one item in v */ + + /* + * - but now we need to go round once more to get v->s + * inspected. This looks messy, but is actually the optimal + * approach. + */ + + if (first_key_inspected) + break; + first_key_inspected = 1; + } + } + while (1) + { + w = v + i; + if (common_i >= w->s_size) + { + z->c = c + w->s_size; + if (w->function == 0) + return w->result; + { + int res = w->function(z); + + z->c = c + w->s_size; + if (res) + return w->result; + } + } + i = w->substring_i; + if (i < 0) + return 0; + } +} + +/* find_among_b is for backwards processing. Same comments apply */ + +extern int +find_among_b(struct SN_env * z, struct among * v, int v_size) +{ + int i = 0; + int j = v_size; + + int c = z->c; + int lb = z->lb; + symbol *q = z->p + c - 1; + + struct among *w; + + int common_i = 0; + int common_j = 0; + + int first_key_inspected = 0; + + while (1) + { + int k = i + ((j - i) >> 1); + int diff = 0; + int common = common_i < common_j ? common_i : common_j; + + w = v + k; + { + int i; + + for (i = w->s_size - 1 - common; i >= 0; i--) + { + if (c - common == lb) + { + diff = -1; + break; + } + diff = q[-common] - w->s[i]; + if (diff != 0) + break; + common++; + } + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) + break; + if (j == i) + break; + if (first_key_inspected) + break; + first_key_inspected = 1; + } + } + while (1) + { + w = v + i; + if (common_i >= w->s_size) + { + z->c = c - w->s_size; + if (w->function == 0) + return w->result; + { + int res = w->function(z); + + z->c = c - w->s_size; + if (res) + return w->result; + } + } + i = w->substring_i; + if (i < 0) + return 0; + } +} + + +extern symbol * +increase_size(symbol * p, int n) +{ + int new_size = n + 20; + symbol *q = (symbol *) (HEAD + (char *) malloc(HEAD + (new_size + 1) * sizeof(symbol))); + + CAPACITY(q) = new_size; + memmove(q, p, CAPACITY(p) * sizeof(symbol)); + lose_s(p); + return q; +} + +/* to replace symbols between c_bra and c_ket in z->p by the + s_size symbols at s +*/ + +extern int +replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s) +{ + int adjustment = s_size - (c_ket - c_bra); + int len = SIZE(z->p); + + if (adjustment != 0) + { + if (adjustment + len > CAPACITY(z->p)) + z->p = increase_size(z->p, adjustment + len); + memmove(z->p + c_ket + adjustment, z->p + c_ket, (len - c_ket) * sizeof(symbol)); + SET_SIZE(z->p, adjustment + len); + z->l += adjustment; + if (z->c >= c_ket) + z->c += adjustment; + else if (z->c > c_bra) + z->c = c_bra; + } + unless(s_size == 0) memmove(z->p + c_bra, s, s_size * sizeof(symbol)); + return adjustment; +} + +static void +slice_check(struct SN_env * z) +{ + if (!(0 <= z->bra && + z->bra <= z->ket && + z->ket <= z->l && + z->l <= SIZE(z->p))) /* this line could be removed */ + { + fprintf(stderr, "faulty slice operation:\n"); + debug(z, -1, 0); + exit(1); + } +} + +extern void +slice_from_s(struct SN_env * z, int s_size, symbol * s) +{ + slice_check(z); + replace_s(z, z->bra, z->ket, s_size, s); +} + +extern void +slice_from_v(struct SN_env * z, symbol * p) +{ + slice_from_s(z, SIZE(p), p); +} + +extern void +slice_del(struct SN_env * z) +{ + slice_from_s(z, 0, 0); +} + +extern void +insert_s(struct SN_env * z, int bra, int ket, int s_size, symbol * s) +{ + int adjustment = replace_s(z, bra, ket, s_size, s); + + if (bra <= z->bra) + z->bra += adjustment; + if (bra <= z->ket) + z->ket += adjustment; +} + +extern void +insert_v(struct SN_env * z, int bra, int ket, symbol * p) +{ + int adjustment = replace_s(z, bra, ket, SIZE(p), p); + + if (bra <= z->bra) + z->bra += adjustment; + if (bra <= z->ket) + z->ket += adjustment; +} + +extern symbol * +slice_to(struct SN_env * z, symbol * p) +{ + slice_check(z); + { + int len = z->ket - z->bra; + + if (CAPACITY(p) < len) + p = increase_size(p, len); + memmove(p, z->p + z->bra, len * sizeof(symbol)); + SET_SIZE(p, len); + } + return p; +} + +extern symbol * +assign_to(struct SN_env * z, symbol * p) +{ + int len = z->l; + + if (CAPACITY(p) < len) + p = increase_size(p, len); + memmove(p, z->p, len * sizeof(symbol)); + SET_SIZE(p, len); + return p; +} + +extern void +debug(struct SN_env * z, int number, int line_count) +{ + int i; + int limit = SIZE(z->p); + + /* if (number >= 0) printf("%3d (line %4d): '", number, line_count); */ + if (number >= 0) + printf("%3d (line %4d): [%d]'", number, line_count, limit); + for (i = 0; i <= limit; i++) + { + if (z->lb == i) + printf("{"); + if (z->bra == i) + printf("["); + if (z->c == i) + printf("|"); + if (z->ket == i) + printf("]"); + if (z->l == i) + printf("}"); + if (i < limit) + { + int ch = z->p[i]; + + if (ch == 0) + ch = '#'; + printf("%c", ch); + } + } + printf("'\n"); +} diff --git a/contrib/tsearch2/stopword.c b/contrib/tsearch2/stopword.c new file mode 100644 index 0000000..f91abeb --- /dev/null +++ b/contrib/tsearch2/stopword.c @@ -0,0 +1,126 @@ +/* + * stopword library + * Teodor Sigaev + */ +#include +#include +#include +#include + +#include "postgres.h" +#include "common.h" +#include "dict.h" + +#define STOPBUFLEN 4096 + +char * +lowerstr(char *str) +{ + char *ptr = str; + + while (*ptr) + { + *ptr = tolower(*(unsigned char *) ptr); + ptr++; + } + return str; +} + +void +freestoplist(StopList * s) +{ + char **ptr = s->stop; + + if (ptr) + while (*ptr && s->len > 0) + { + free(*ptr); + ptr++; + s->len--; + free(s->stop); + } + memset(s, 0, sizeof(StopList)); +} + +void +readstoplist(text *in, StopList * s) +{ + char **stop = NULL; + + s->len = 0; + if (in && VARSIZE(in) - VARHDRSZ > 0) + { + char *filename = text2char(in); + FILE *hin = NULL; + char buf[STOPBUFLEN]; + int reallen = 0; + + if ((hin = fopen(filename, "r")) == NULL) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not open file \"%s\": %m", + filename))); + + while (fgets(buf, STOPBUFLEN, hin)) + { + buf[strlen(buf) - 1] = '\0'; + if (*buf == '\0') + continue; + + if (s->len >= reallen) + { + char **tmp; + + reallen = (reallen) ? reallen * 2 : 16; + tmp = (char **) realloc((void *) stop, sizeof(char *) * reallen); + if (!tmp) + { + freestoplist(s); + fclose(hin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + stop = tmp; + } + + stop[s->len] = strdup(buf); + if (!stop[s->len]) + { + freestoplist(s); + fclose(hin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + if (s->wordop) + stop[s->len] = (s->wordop) (stop[s->len]); + + (s->len)++; + } + fclose(hin); + pfree(filename); + } + s->stop = stop; +} + +static int +comparestr(const void *a, const void *b) +{ + return strcmp(*(char **) a, *(char **) b); +} + +void +sortstoplist(StopList * s) +{ + if (s->stop && s->len > 0) + qsort(s->stop, s->len, sizeof(char *), comparestr); +} + +bool +searchstoplist(StopList * s, char *key) +{ + if (s->wordop) + key = (*(s->wordop)) (key); + return (s->stop && s->len > 0 && bsearch(&key, s->stop, s->len, sizeof(char *), comparestr)) ? true : false; +} diff --git a/contrib/tsearch2/stopword/english.stop b/contrib/tsearch2/stopword/english.stop new file mode 100644 index 0000000..a913011 --- /dev/null +++ b/contrib/tsearch2/stopword/english.stop @@ -0,0 +1,128 @@ +i +me +my +myself +we +our +ours +ourselves +you +your +yours +yourself +yourselves +he +him +his +himself +she +her +hers +herself +it +its +itself +they +them +their +theirs +themselves +what +which +who +whom +this +that +these +those +am +is +are +was +were +be +been +being +have +has +had +having +do +does +did +doing +a +an +the +and +but +if +or +because +as +until +while +of +at +by +for +with +about +against +between +into +through +during +before +after +above +below +to +from +up +down +in +out +on +off +over +under +again +further +then +once +here +there +when +where +why +how +all +any +both +each +few +more +most +other +some +such +no +nor +not +only +own +same +so +than +too +very +s +t +can +will +just +don +should +now + diff --git a/contrib/tsearch2/stopword/russian.stop b/contrib/tsearch2/stopword/russian.stop new file mode 100644 index 0000000..1877e3a --- /dev/null +++ b/contrib/tsearch2/stopword/russian.stop @@ -0,0 +1,151 @@ +É +× +×Ï +ÎÅ +ÞÔÏ +ÏÎ +ÎÁ +Ñ +Ó +ÓÏ +ËÁË +Á +ÔÏ +×ÓÅ +ÏÎÁ +ÔÁË +ÅÇÏ +ÎÏ +ÄÁ +ÔÙ +Ë +Õ +ÖÅ +×Ù +ÚÁ +ÂÙ +ÐÏ +ÔÏÌØËÏ +ÅÅ +ÍÎÅ +ÂÙÌÏ +×ÏÔ +ÏÔ +ÍÅÎÑ +ÅÝÅ +ÎÅÔ +Ï +ÉÚ +ÅÍÕ +ÔÅÐÅÒØ +ËÏÇÄÁ +ÄÁÖÅ +ÎÕ +×ÄÒÕÇ +ÌÉ +ÅÓÌÉ +ÕÖÅ +ÉÌÉ +ÎÉ +ÂÙÔØ +ÂÙÌ +ÎÅÇÏ +ÄÏ +×ÁÓ +ÎÉÂÕÄØ +ÏÐÑÔØ +ÕÖ +×ÁÍ +×ÅÄØ +ÔÁÍ +ÐÏÔÏÍ +ÓÅÂÑ +ÎÉÞÅÇÏ +ÅÊ +ÍÏÖÅÔ +ÏÎÉ +ÔÕÔ +ÇÄÅ +ÅÓÔØ +ÎÁÄÏ +ÎÅÊ +ÄÌÑ +ÍÙ +ÔÅÂÑ +ÉÈ +ÞÅÍ +ÂÙÌÁ +ÓÁÍ +ÞÔÏ +ÂÅÚ +ÂÕÄÔÏ +ÞÅÇÏ +ÒÁÚ +ÔÏÖÅ +ÓÅÂÅ +ÐÏÄ +ÂÕÄÅÔ +Ö +ÔÏÇÄÁ +ËÔÏ +ÜÔÏÔ +ÔÏÇÏ +ÐÏÔÏÍÕ +ÜÔÏÇÏ +ËÁËÏÊ +ÓÏ×ÓÅÍ +ÎÉÍ +ÚÄÅÓØ +ÜÔÏÍ +ÏÄÉÎ +ÐÏÞÔÉ +ÍÏÊ +ÔÅÍ +ÞÔÏÂÙ +ÎÅÅ +ÓÅÊÞÁÓ +ÂÙÌÉ +ËÕÄÁ +ÚÁÞÅÍ +×ÓÅÈ +ÎÉËÏÇÄÁ +ÍÏÖÎÏ +ÐÒÉ +ÎÁËÏÎÅà +Ä×Á +Ï +ÄÒÕÇÏÊ +ÈÏÔØ +ÐÏÓÌÅ +ÎÁÄ +ÂÏÌØÛÅ +ÔÏÔ +ÞÅÒÅÚ +ÜÔÉ +ÎÁÓ +ÐÒÏ +×ÓÅÇÏ +ÎÉÈ +ËÁËÁÑ +ÍÎÏÇÏ +ÒÁÚ×Å +ÔÒÉ +ÜÔÕ +ÍÏÑ +×ÐÒÏÞÅÍ +ÈÏÒÏÛÏ +Ó×ÏÀ +ÜÔÏÊ +ÐÅÒÅÄ +ÉÎÏÇÄÁ +ÌÕÞÛÅ +ÞÕÔØ +ÔÏÍ +ÎÅÌØÚÑ +ÔÁËÏÊ +ÉÍ +ÂÏÌÅÅ +×ÓÅÇÄÁ +ËÏÎÅÞÎÏ +×ÓÀ +ÍÅÖÄÕ diff --git a/contrib/tsearch2/ts_cfg.c b/contrib/tsearch2/ts_cfg.c new file mode 100644 index 0000000..ad06d90 --- /dev/null +++ b/contrib/tsearch2/ts_cfg.c @@ -0,0 +1,594 @@ +/* + * interface functions to tscfg + * Teodor Sigaev + */ +#include +#include +#include +#include +#include + +#include "postgres.h" +#include "fmgr.h" +#include "utils/array.h" +#include "catalog/pg_type.h" +#include "executor/spi.h" + +#include "ts_cfg.h" +#include "dict.h" +#include "wparser.h" +#include "snmap.h" +#include "common.h" +#include "tsvector.h" + +/*********top interface**********/ + +static void *plan_getcfg_bylocale = NULL; +static void *plan_getcfg = NULL; +static void *plan_getmap = NULL; +static void *plan_name2id = NULL; +static Oid current_cfg_id = 0; + +void +init_cfg(Oid id, TSCfgInfo * cfg) +{ + Oid arg[2] = {OIDOID, OIDOID}; + bool isnull; + Datum pars[2] = {ObjectIdGetDatum(id), ObjectIdGetDatum(id)}; + int stat, + i, + j; + text *ptr; + text *prsname = NULL; + MemoryContext oldcontext; + + memset(cfg, 0, sizeof(TSCfgInfo)); + SPI_connect(); + if (!plan_getcfg) + { + plan_getcfg = SPI_saveplan(SPI_prepare("select prs_name from pg_ts_cfg where oid = $1", 1, arg)); + if (!plan_getcfg) + ts_error(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_getcfg, pars, " ", 1); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + { + prsname = (text *) DatumGetPointer( + SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull) + ); + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + prsname = ptextdup(prsname); + MemoryContextSwitchTo(oldcontext); + + cfg->id = id; + } + else + ts_error(ERROR, "No tsearch cfg with id %d", id); + + arg[0] = TEXTOID; + if (!plan_getmap) + { + plan_getmap = SPI_saveplan(SPI_prepare("select lt.tokid, pg_ts_cfgmap.dict_name from pg_ts_cfgmap, pg_ts_cfg, token_type( $1 ) as lt where lt.alias = pg_ts_cfgmap.tok_alias and pg_ts_cfgmap.ts_name = pg_ts_cfg.ts_name and pg_ts_cfg.oid= $2 order by lt.tokid desc;", 2, arg)); + if (!plan_getmap) + ts_error(ERROR, "SPI_prepare() failed"); + } + + pars[0] = PointerGetDatum(prsname); + stat = SPI_execp(plan_getmap, pars, " ", 0); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed <= 0) + ts_error(ERROR, "No parser with id %d", id); + + for (i = 0; i < SPI_processed; i++) + { + int lexid = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull)); + ArrayType *toasted_a = (ArrayType *) PointerGetDatum(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull)); + ArrayType *a; + + if (!cfg->map) + { + cfg->len = lexid + 1; + cfg->map = (ListDictionary *) malloc(sizeof(ListDictionary) * cfg->len); + if (!cfg->map) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + memset(cfg->map, 0, sizeof(ListDictionary) * cfg->len); + } + + if (isnull) + continue; + + a = (ArrayType *) PointerGetDatum(PG_DETOAST_DATUM(DatumGetPointer(toasted_a))); + + if (ARR_NDIM(a) != 1) + ts_error(ERROR, "Wrong dimension"); + if (ARRNELEMS(a) < 1) + continue; + + cfg->map[lexid].len = ARRNELEMS(a); + cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len); + memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len); + ptr = (text *) ARR_DATA_PTR(a); + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + for (j = 0; j < cfg->map[lexid].len; j++) + { + cfg->map[lexid].dict_id[j] = PointerGetDatum(ptextdup(ptr)); + ptr = NEXTVAL(ptr); + } + MemoryContextSwitchTo(oldcontext); + + if (a != toasted_a) + pfree(a); + } + + SPI_finish(); + cfg->prs_id = name2id_prs(prsname); + pfree(prsname); + for (i = 0; i < cfg->len; i++) + { + for (j = 0; j < cfg->map[i].len; j++) + { + ptr = (text *) DatumGetPointer(cfg->map[i].dict_id[j]); + cfg->map[i].dict_id[j] = ObjectIdGetDatum(name2id_dict(ptr)); + pfree(ptr); + } + } +} + +typedef struct +{ + TSCfgInfo *last_cfg; + int len; + int reallen; + TSCfgInfo *list; + SNMap name2id_map; +} CFGList; + +static CFGList CList = {NULL, 0, 0, NULL, {0, 0, NULL}}; + +void +reset_cfg(void) +{ + freeSNMap(&(CList.name2id_map)); + if (CList.list) + { + int i, + j; + + for (i = 0; i < CList.len; i++) + if (CList.list[i].map) + { + for (j = 0; j < CList.list[i].len; j++) + if (CList.list[i].map[j].dict_id) + free(CList.list[i].map[j].dict_id); + free(CList.list[i].map); + } + free(CList.list); + } + memset(&CList, 0, sizeof(CFGList)); +} + +static int +comparecfg(const void *a, const void *b) +{ + return ((TSCfgInfo *) a)->id - ((TSCfgInfo *) b)->id; +} + +TSCfgInfo * +findcfg(Oid id) +{ + /* last used cfg */ + if (CList.last_cfg && CList.last_cfg->id == id) + return CList.last_cfg; + + /* already used cfg */ + if (CList.len != 0) + { + TSCfgInfo key; + + key.id = id; + CList.last_cfg = bsearch(&key, CList.list, CList.len, sizeof(TSCfgInfo), comparecfg); + if (CList.last_cfg != NULL) + return CList.last_cfg; + } + + /* last chance */ + if (CList.len == CList.reallen) + { + TSCfgInfo *tmp; + int reallen = (CList.reallen) ? 2 * CList.reallen : 16; + + tmp = (TSCfgInfo *) realloc(CList.list, sizeof(TSCfgInfo) * reallen); + if (!tmp) + ts_error(ERROR, "No memory"); + CList.reallen = reallen; + CList.list = tmp; + } + CList.last_cfg = &(CList.list[CList.len]); + init_cfg(id, CList.last_cfg); + CList.len++; + qsort(CList.list, CList.len, sizeof(TSCfgInfo), comparecfg); + return findcfg(id); /* qsort changed order!! */ ; +} + + +Oid +name2id_cfg(text *name) +{ + Oid arg[1] = {TEXTOID}; + bool isnull; + Datum pars[1] = {PointerGetDatum(name)}; + int stat; + Oid id = findSNMap_t(&(CList.name2id_map), name); + + if (id) + return id; + + SPI_connect(); + if (!plan_name2id) + { + plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_cfg where ts_name = $1", 1, arg)); + if (!plan_name2id) + /* internal error */ + elog(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_name2id, pars, " ", 1); + if (stat < 0) + /* internal error */ + elog(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + { + id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + if (isnull) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("null id for tsearch config"))); + } + else + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("no tsearch config"))); + + SPI_finish(); + addSNMap_t(&(CList.name2id_map), name, id); + return id; +} + + +void +parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen) +{ + int type, + lenlemm, + i; + char *lemm = NULL; + WParserInfo *prsobj = findprs(cfg->prs_id); + + prsobj->prs = (void *) DatumGetPointer( + FunctionCall2( + &(prsobj->start_info), + PointerGetDatum(buf), + Int32GetDatum(buflen) + ) + ); + + while ((type = DatumGetInt32(FunctionCall3( + &(prsobj->getlexeme_info), + PointerGetDatum(prsobj->prs), + PointerGetDatum(&lemm), + PointerGetDatum(&lenlemm)))) != 0) + { + + if (lenlemm >= MAXSTRLEN) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("word is too long"))); + + if (type >= cfg->len) /* skip this type of lexem */ + continue; + + for (i = 0; i < cfg->map[type].len; i++) + { + DictInfo *dict = finddict(DatumGetObjectId(cfg->map[type].dict_id[i])); + char **norms, + **ptr; + + norms = ptr = (char **) DatumGetPointer( + FunctionCall3( + &(dict->lexize_info), + PointerGetDatum(dict->dictionary), + PointerGetDatum(lemm), + PointerGetDatum(lenlemm) + ) + ); + if (!norms) /* dictionary doesn't know this lexem */ + continue; + + prs->pos++; /* set pos */ + + while (*ptr) + { + if (prs->curwords == prs->lenwords) + { + prs->lenwords *= 2; + prs->words = (WORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(WORD)); + } + + prs->words[prs->curwords].len = strlen(*ptr); + prs->words[prs->curwords].word = *ptr; + prs->words[prs->curwords].alen = 0; + prs->words[prs->curwords].pos.pos = LIMITPOS(prs->pos); + ptr++; + prs->curwords++; + } + pfree(norms); + break; /* lexem already normalized or is stop + * word */ + } + } + + FunctionCall1( + &(prsobj->end_info), + PointerGetDatum(prsobj->prs) + ); +} + +static void +hladdword(HLPRSTEXT * prs, char *buf, int4 buflen, int type) +{ + while (prs->curwords >= prs->lenwords) + { + prs->lenwords *= 2; + prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD)); + } + memset(&(prs->words[prs->curwords]), 0, sizeof(HLWORD)); + prs->words[prs->curwords].type = (uint8) type; + prs->words[prs->curwords].len = buflen; + prs->words[prs->curwords].word = palloc(buflen); + memcpy(prs->words[prs->curwords].word, buf, buflen); + prs->curwords++; +} + +static void +hlfinditem(HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int buflen) +{ + int i; + ITEM *item = GETQUERY(query); + HLWORD *word = &(prs->words[prs->curwords - 1]); + + while (prs->curwords + query->size >= prs->lenwords) + { + prs->lenwords *= 2; + prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD)); + } + + for (i = 0; i < query->size; i++) + { + if (item->type == VAL && item->length == buflen && strncmp(GETOPERAND(query) + item->distance, buf, buflen) == 0) + { + if (word->item) + { + memcpy(&(prs->words[prs->curwords]), word, sizeof(HLWORD)); + prs->words[prs->curwords].item = item; + prs->words[prs->curwords].repeated = 1; + prs->curwords++; + } + else + word->item = item; + } + item++; + } +} + +void +hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4 buflen) +{ + int type, + lenlemm, + i; + char *lemm = NULL; + WParserInfo *prsobj = findprs(cfg->prs_id); + + prsobj->prs = (void *) DatumGetPointer( + FunctionCall2( + &(prsobj->start_info), + PointerGetDatum(buf), + Int32GetDatum(buflen) + ) + ); + + while ((type = DatumGetInt32(FunctionCall3( + &(prsobj->getlexeme_info), + PointerGetDatum(prsobj->prs), + PointerGetDatum(&lemm), + PointerGetDatum(&lenlemm)))) != 0) + { + + if (lenlemm >= MAXSTRLEN) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("word is too long"))); + + hladdword(prs, lemm, lenlemm, type); + + if (type >= cfg->len) + continue; + + for (i = 0; i < cfg->map[type].len; i++) + { + DictInfo *dict = finddict(DatumGetObjectId(cfg->map[type].dict_id[i])); + char **norms, + **ptr; + + norms = ptr = (char **) DatumGetPointer( + FunctionCall3( + &(dict->lexize_info), + PointerGetDatum(dict->dictionary), + PointerGetDatum(lemm), + PointerGetDatum(lenlemm) + ) + ); + if (!norms) /* dictionary doesn't know this lexem */ + continue; + + while (*ptr) + { + hlfinditem(prs, query, *ptr, strlen(*ptr)); + pfree(*ptr); + ptr++; + } + pfree(norms); + break; /* lexem already normalized or is stop + * word */ + } + } + + FunctionCall1( + &(prsobj->end_info), + PointerGetDatum(prsobj->prs) + ); +} + +text * +genhl(HLPRSTEXT * prs) +{ + text *out; + int len = 128; + char *ptr; + HLWORD *wrd = prs->words; + + out = (text *) palloc(len); + ptr = ((char *) out) + VARHDRSZ; + + while (wrd - prs->words < prs->curwords) + { + while (wrd->len + prs->stopsellen + prs->startsellen + (ptr - ((char *) out)) >= len) + { + int dist = ptr - ((char *) out); + + len *= 2; + out = (text *) repalloc(out, len); + ptr = ((char *) out) + dist; + } + + if (wrd->in && !wrd->skip && !wrd->repeated) + { + if (wrd->replace) + { + *ptr = ' '; + ptr++; + } + else + { + if (wrd->selected) + { + memcpy(ptr, prs->startsel, prs->startsellen); + ptr += prs->startsellen; + } + memcpy(ptr, wrd->word, wrd->len); + ptr += wrd->len; + if (wrd->selected) + { + memcpy(ptr, prs->stopsel, prs->stopsellen); + ptr += prs->stopsellen; + } + } + } + + if (!wrd->repeated) + pfree(wrd->word); + + wrd++; + } + + VARATT_SIZEP(out) = ptr - ((char *) out); + return out; +} + +int +get_currcfg(void) +{ + Oid arg[1] = {TEXTOID}; + const char *curlocale; + Datum pars[1]; + bool isnull; + int stat; + + if (current_cfg_id > 0) + return current_cfg_id; + + SPI_connect(); + if (!plan_getcfg_bylocale) + { + plan_getcfg_bylocale = SPI_saveplan(SPI_prepare("select oid from pg_ts_cfg where locale = $1 ", 1, arg)); + if (!plan_getcfg_bylocale) + /* internal error */ + elog(ERROR, "SPI_prepare() failed"); + } + + curlocale = setlocale(LC_CTYPE, NULL); + pars[0] = PointerGetDatum(char2text((char *) curlocale)); + stat = SPI_execp(plan_getcfg_bylocale, pars, " ", 1); + + if (stat < 0) + /* internal error */ + elog(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + current_cfg_id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + else + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not find tsearch config by locale"))); + + pfree(DatumGetPointer(pars[0])); + SPI_finish(); + return current_cfg_id; +} + +PG_FUNCTION_INFO_V1(set_curcfg); +Datum set_curcfg(PG_FUNCTION_ARGS); +Datum +set_curcfg(PG_FUNCTION_ARGS) +{ + findcfg(PG_GETARG_OID(0)); + current_cfg_id = PG_GETARG_OID(0); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(set_curcfg_byname); +Datum set_curcfg_byname(PG_FUNCTION_ARGS); +Datum +set_curcfg_byname(PG_FUNCTION_ARGS) +{ + text *name = PG_GETARG_TEXT_P(0); + + DirectFunctionCall1( + set_curcfg, + ObjectIdGetDatum(name2id_cfg(name)) + ); + PG_FREE_IF_COPY(name, 0); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(show_curcfg); +Datum show_curcfg(PG_FUNCTION_ARGS); +Datum +show_curcfg(PG_FUNCTION_ARGS) +{ + PG_RETURN_OID(get_currcfg()); +} + +PG_FUNCTION_INFO_V1(reset_tsearch); +Datum reset_tsearch(PG_FUNCTION_ARGS); +Datum +reset_tsearch(PG_FUNCTION_ARGS) +{ + ts_error(NOTICE, "TSearch cache cleaned"); + PG_RETURN_VOID(); +} diff --git a/contrib/tsearch2/ts_cfg.h b/contrib/tsearch2/ts_cfg.h new file mode 100644 index 0000000..cde35ca --- /dev/null +++ b/contrib/tsearch2/ts_cfg.h @@ -0,0 +1,75 @@ +#ifndef __TS_CFG_H__ +#define __TS_CFG_H__ +#include "postgres.h" +#include "query.h" + +typedef struct +{ + int len; + Datum *dict_id; +} ListDictionary; + +typedef struct +{ + Oid id; + Oid prs_id; + int len; + ListDictionary *map; +} TSCfgInfo; + +Oid name2id_cfg(text *name); +TSCfgInfo *findcfg(Oid id); +void init_cfg(Oid id, TSCfgInfo * cfg); +void reset_cfg(void); + +typedef struct +{ + uint16 len; + union + { + uint16 pos; + uint16 *apos; + } pos; + char *word; + uint32 alen; +} WORD; + +typedef struct +{ + WORD *words; + int4 lenwords; + int4 curwords; + int4 pos; +} PRSTEXT; + +typedef struct +{ + uint16 len; + uint8 selected:1, + in:1, + skip:1, + replace:1, + repeated:1; + uint8 type; + char *word; + ITEM *item; +} HLWORD; + +typedef struct +{ + HLWORD *words; + int4 lenwords; + int4 curwords; + char *startsel; + char *stopsel; + int2 startsellen; + int2 stopsellen; +} HLPRSTEXT; + +void hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4 buflen); +text *genhl(HLPRSTEXT * prs); + +void parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen); +int get_currcfg(void); + +#endif diff --git a/contrib/tsearch2/ts_stat.c b/contrib/tsearch2/ts_stat.c new file mode 100644 index 0000000..732f25b --- /dev/null +++ b/contrib/tsearch2/ts_stat.c @@ -0,0 +1,484 @@ +/* + * stat functions + */ + +#include "tsvector.h" +#include "ts_stat.h" +#include "funcapi.h" +#include "catalog/pg_type.h" +#include "executor/spi.h" +#include "common.h" + +PG_FUNCTION_INFO_V1(tsstat_in); +Datum tsstat_in(PG_FUNCTION_ARGS); +Datum +tsstat_in(PG_FUNCTION_ARGS) +{ + tsstat *stat = palloc(STATHDRSIZE); + + stat->len = STATHDRSIZE; + stat->size = 0; + PG_RETURN_POINTER(stat); +} + +PG_FUNCTION_INFO_V1(tsstat_out); +Datum tsstat_out(PG_FUNCTION_ARGS); +Datum +tsstat_out(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("tsstat_out not implemented"))); + PG_RETURN_NULL(); +} + +static WordEntry ** +SEI_realloc(WordEntry ** in, uint32 *len) +{ + if (*len == 0 || in == NULL) + { + *len = 8; + in = palloc(sizeof(WordEntry *) * (*len)); + } + else + { + *len *= 2; + in = repalloc(in, sizeof(WordEntry *) * (*len)); + } + return in; +} + +static int +compareStatWord(StatEntry * a, WordEntry * b, tsstat * stat, tsvector * txt) +{ + if (a->len == b->len) + return strncmp( + STATSTRPTR(stat) + a->pos, + STRPTR(txt) + b->pos, + a->len + ); + return (a->len > b->len) ? 1 : -1; +} + +static tsstat * +formstat(tsstat * stat, tsvector * txt, WordEntry ** entry, uint32 len) +{ + tsstat *newstat; + uint32 totallen, + nentry; + uint32 slen = 0; + WordEntry **ptr = entry; + char *curptr; + StatEntry *sptr, + *nptr; + + while (ptr - entry < len) + { + slen += (*ptr)->len; + ptr++; + } + + nentry = stat->size + len; + slen += STATSTRSIZE(stat); + totallen = CALCSTATSIZE(nentry, slen); + newstat = palloc(totallen); + newstat->len = totallen; + newstat->size = nentry; + + memcpy(STATSTRPTR(newstat), STATSTRPTR(stat), STATSTRSIZE(stat)); + curptr = STATSTRPTR(newstat) + STATSTRSIZE(stat); + + ptr = entry; + sptr = STATPTR(stat); + nptr = STATPTR(newstat); + + if (len == 1) + { + StatEntry *StopLow = STATPTR(stat); + StatEntry *StopHigh = (StatEntry *) STATSTRPTR(stat); + + while (StopLow < StopHigh) + { + sptr = StopLow + (StopHigh - StopLow) / 2; + if (compareStatWord(sptr, *ptr, stat, txt) < 0) + StopLow = sptr + 1; + else + StopHigh = sptr; + } + nptr = STATPTR(newstat) + (StopLow - STATPTR(stat)); + memcpy(STATPTR(newstat), STATPTR(stat), sizeof(StatEntry) * (StopLow - STATPTR(stat))); + nptr->nentry = POSDATALEN(txt, *ptr); + if (nptr->nentry == 0) + nptr->nentry = 1; + nptr->ndoc = 1; + nptr->len = (*ptr)->len; + memcpy(curptr, STRPTR(txt) + (*ptr)->pos, nptr->len); + nptr->pos = curptr - STATSTRPTR(newstat); + memcpy(nptr + 1, StopLow, sizeof(StatEntry) * (((StatEntry *) STATSTRPTR(stat)) - StopLow)); + } + else + { + while (sptr - STATPTR(stat) < stat->size && ptr - entry < len) + { + if (compareStatWord(sptr, *ptr, stat, txt) < 0) + { + memcpy(nptr, sptr, sizeof(StatEntry)); + sptr++; + } + else + { + nptr->nentry = POSDATALEN(txt, *ptr); + if (nptr->nentry == 0) + nptr->nentry = 1; + nptr->ndoc = 1; + nptr->len = (*ptr)->len; + memcpy(curptr, STRPTR(txt) + (*ptr)->pos, nptr->len); + nptr->pos = curptr - STATSTRPTR(newstat); + curptr += nptr->len; + ptr++; + } + nptr++; + } + + memcpy(nptr, sptr, sizeof(StatEntry) * (stat->size - (sptr - STATPTR(stat)))); + + while (ptr - entry < len) + { + nptr->nentry = POSDATALEN(txt, *ptr); + if (nptr->nentry == 0) + nptr->nentry = 1; + nptr->ndoc = 1; + nptr->len = (*ptr)->len; + memcpy(curptr, STRPTR(txt) + (*ptr)->pos, nptr->len); + nptr->pos = curptr - STATSTRPTR(newstat); + curptr += nptr->len; + ptr++; + nptr++; + } + } + + return newstat; +} + +PG_FUNCTION_INFO_V1(ts_accum); +Datum ts_accum(PG_FUNCTION_ARGS); +Datum +ts_accum(PG_FUNCTION_ARGS) +{ + tsstat *newstat, + *stat = (tsstat *) PG_GETARG_POINTER(0); + tsvector *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + WordEntry **newentry = NULL; + uint32 len = 0, + cur = 0; + StatEntry *sptr; + WordEntry *wptr; + + if (stat == NULL || PG_ARGISNULL(0)) + { /* Init in first */ + stat = palloc(STATHDRSIZE); + stat->len = STATHDRSIZE; + stat->size = 0; + } + + /* simple check of correctness */ + if (txt == NULL || PG_ARGISNULL(1) || txt->size == 0) + { + PG_FREE_IF_COPY(txt, 1); + PG_RETURN_POINTER(stat); + } + + sptr = STATPTR(stat); + wptr = ARRPTR(txt); + + if (stat->size < 100 * txt->size) + { /* merge */ + while (sptr - STATPTR(stat) < stat->size && wptr - ARRPTR(txt) < txt->size) + { + int cmp = compareStatWord(sptr, wptr, stat, txt); + + if (cmp < 0) + sptr++; + else if (cmp == 0) + { + int n = POSDATALEN(txt, wptr); + + if (n == 0) + n = 1; + sptr->ndoc++; + sptr->nentry += n; + sptr++; + wptr++; + } + else + { + if (cur == len) + newentry = SEI_realloc(newentry, &len); + newentry[cur] = wptr; + wptr++; + cur++; + } + } + + while (wptr - ARRPTR(txt) < txt->size) + { + if (cur == len) + newentry = SEI_realloc(newentry, &len); + newentry[cur] = wptr; + wptr++; + cur++; + } + } + else + { /* search */ + while (wptr - ARRPTR(txt) < txt->size) + { + StatEntry *StopLow = STATPTR(stat); + StatEntry *StopHigh = (StatEntry *) STATSTRPTR(stat); + int cmp; + + while (StopLow < StopHigh) + { + sptr = StopLow + (StopHigh - StopLow) / 2; + cmp = compareStatWord(sptr, wptr, stat, txt); + if (cmp == 0) + { + int n = POSDATALEN(txt, wptr); + + if (n == 0) + n = 1; + sptr->ndoc++; + sptr->nentry += n; + break; + } + else if (cmp < 0) + StopLow = sptr + 1; + else + StopHigh = sptr; + } + + if (StopLow >= StopHigh) + { /* not found */ + if (cur == len) + newentry = SEI_realloc(newentry, &len); + newentry[cur] = wptr; + cur++; + } + wptr++; + } + } + + + if (cur == 0) + { /* no new words */ + PG_FREE_IF_COPY(txt, 1); + PG_RETURN_POINTER(stat); + } + + newstat = formstat(stat, txt, newentry, cur); + pfree(newentry); + PG_FREE_IF_COPY(txt, 1); + /* pfree(stat); */ + + PG_RETURN_POINTER(newstat); +} + +typedef struct +{ + uint32 cur; + tsvector *stat; +} StatStorage; + +static void +ts_setup_firstcall(FuncCallContext *funcctx, tsstat * stat) +{ + TupleDesc tupdesc; + MemoryContext oldcontext; + StatStorage *st; + + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + st = palloc(sizeof(StatStorage)); + st->cur = 0; + st->stat = palloc(stat->len); + memcpy(st->stat, stat, stat->len); + funcctx->user_fctx = (void *) st; + tupdesc = RelationNameGetTupleDesc("statinfo"); + funcctx->slot = TupleDescGetSlot(tupdesc); + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + MemoryContextSwitchTo(oldcontext); +} + + +static Datum +ts_process_call(FuncCallContext *funcctx) +{ + StatStorage *st; + + st = (StatStorage *) funcctx->user_fctx; + + if (st->cur < st->stat->size) + { + Datum result; + char *values[3]; + char ndoc[16]; + char nentry[16]; + StatEntry *entry = STATPTR(st->stat) + st->cur; + HeapTuple tuple; + + values[1] = ndoc; + sprintf(ndoc, "%d", entry->ndoc); + values[2] = nentry; + sprintf(nentry, "%d", entry->nentry); + values[0] = palloc(entry->len + 1); + memcpy(values[0], STATSTRPTR(st->stat) + entry->pos, entry->len); + (values[0])[entry->len] = '\0'; + + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + result = TupleGetDatum(funcctx->slot, tuple); + + pfree(values[0]); + st->cur++; + return result; + } + else + { + pfree(st->stat); + pfree(st); + } + + return (Datum) 0; +} + +PG_FUNCTION_INFO_V1(ts_accum_finish); +Datum ts_accum_finish(PG_FUNCTION_ARGS); +Datum +ts_accum_finish(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + funcctx = SRF_FIRSTCALL_INIT(); + ts_setup_firstcall(funcctx, (tsstat *) PG_GETARG_POINTER(0)); + } + + funcctx = SRF_PERCALL_SETUP(); + if ((result = ts_process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + +static Oid tiOid = InvalidOid; +static void +get_ti_Oid(void) +{ + int ret; + bool isnull; + + if ((ret = SPI_exec("select oid from pg_type where typname='tsvector'", 1)) < 0) + /* internal error */ + elog(ERROR, "SPI_exec to get tsvector oid returns %d", ret); + + if (SPI_processed < 0) + /* internal error */ + elog(ERROR, "There is no tsvector type"); + tiOid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + if (tiOid == InvalidOid) + /* internal error */ + elog(ERROR, "tsvector type has InvalidOid"); +} + +static tsstat * +ts_stat_sql(text *txt) +{ + char *query = text2char(txt); + int i; + tsstat *newstat, + *stat; + bool isnull; + Portal portal; + void *plan; + + if (tiOid == InvalidOid) + get_ti_Oid(); + + if ((plan = SPI_prepare(query, 0, NULL)) == NULL) + /* internal error */ + elog(ERROR, "SPI_prepare('%s') returns NULL", query); + + if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL)) == NULL) + /* internal error */ + elog(ERROR, "SPI_cursor_open('%s') returns NULL", query); + + SPI_cursor_fetch(portal, true, 100); + + if (SPI_tuptable->tupdesc->natts != 1) + /* internal error */ + elog(ERROR, "number of fields doesn't equal to 1"); + + if (SPI_gettypeid(SPI_tuptable->tupdesc, 1) != tiOid) + /* internal error */ + elog(ERROR, "column isn't of tsvector type"); + + stat = palloc(STATHDRSIZE); + stat->len = STATHDRSIZE; + stat->size = 0; + + while (SPI_processed > 0) + { + for (i = 0; i < SPI_processed; i++) + { + Datum data = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull); + + if (!isnull) + { + newstat = (tsstat *) DatumGetPointer(DirectFunctionCall2( + ts_accum, + PointerGetDatum(stat), + data + )); + if (stat != newstat && stat) + pfree(stat); + stat = newstat; + } + } + + SPI_freetuptable(SPI_tuptable); + SPI_cursor_fetch(portal, true, 100); + } + + SPI_freetuptable(SPI_tuptable); + SPI_cursor_close(portal); + SPI_freeplan(plan); + pfree(query); + + return stat; +} + +PG_FUNCTION_INFO_V1(ts_stat); +Datum ts_stat(PG_FUNCTION_ARGS); +Datum +ts_stat(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + tsstat *stat; + text *txt = PG_GETARG_TEXT_P(0); + + funcctx = SRF_FIRSTCALL_INIT(); + SPI_connect(); + stat = ts_stat_sql(txt); + PG_FREE_IF_COPY(txt, 0); + ts_setup_firstcall(funcctx, stat); + SPI_finish(); + } + + funcctx = SRF_PERCALL_SETUP(); + if ((result = ts_process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} diff --git a/contrib/tsearch2/ts_stat.h b/contrib/tsearch2/ts_stat.h new file mode 100644 index 0000000..37d1e7b --- /dev/null +++ b/contrib/tsearch2/ts_stat.h @@ -0,0 +1,32 @@ +#ifndef __TXTIDX_STAT_H__ +#define __TXTIDX_STAT_H__ + +#include "postgres.h" + +#include "access/gist.h" +#include "access/itup.h" +#include "utils/builtins.h" +#include "storage/bufpage.h" + +typedef struct +{ + uint32 len; + uint32 pos; + uint32 ndoc; + uint32 nentry; +} StatEntry; + +typedef struct +{ + int4 len; + int4 size; + char data[1]; +} tsstat; + +#define STATHDRSIZE (sizeof(int4)*2) +#define CALCSTATSIZE(x, lenstr) ( x * sizeof(StatEntry) + STATHDRSIZE + lenstr ) +#define STATPTR(x) ( (StatEntry*) ( (char*)x + STATHDRSIZE ) ) +#define STATSTRPTR(x) ( (char*)x + STATHDRSIZE + ( sizeof(StatEntry) * ((tsvector*)x)->size ) ) +#define STATSTRSIZE(x) ( ((tsvector*)x)->len - STATHDRSIZE - ( sizeof(StatEntry) * ((tsvector*)x)->size ) ) + +#endif diff --git a/contrib/tsearch2/tsvector.c b/contrib/tsearch2/tsvector.c new file mode 100644 index 0000000..c8002c0 --- /dev/null +++ b/contrib/tsearch2/tsvector.c @@ -0,0 +1,932 @@ +/* + * In/Out definitions for tsvector type + * Internal structure: + * string of values, array of position lexem in string and it's length + * Teodor Sigaev + */ +#include "postgres.h" + +#include "access/gist.h" +#include "access/itup.h" +#include "utils/builtins.h" +#include "storage/bufpage.h" +#include "executor/spi.h" +#include "commands/trigger.h" +#include "nodes/pg_list.h" +#include "catalog/namespace.h" + +#include "utils/pg_locale.h" + +#include /* tolower */ +#include "tsvector.h" +#include "query.h" +#include "ts_cfg.h" +#include "common.h" + +PG_FUNCTION_INFO_V1(tsvector_in); +Datum tsvector_in(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(tsvector_out); +Datum tsvector_out(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(to_tsvector); +Datum to_tsvector(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(to_tsvector_current); +Datum to_tsvector_current(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(to_tsvector_name); +Datum to_tsvector_name(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(tsearch2); +Datum tsearch2(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(tsvector_length); +Datum tsvector_length(PG_FUNCTION_ARGS); + +/* + * in/out text index type + */ +static int +comparePos(const void *a, const void *b) +{ + if (((WordEntryPos *) a)->pos == ((WordEntryPos *) b)->pos) + return 1; + return (((WordEntryPos *) a)->pos > ((WordEntryPos *) b)->pos) ? 1 : -1; +} + +static int +uniquePos(WordEntryPos * a, int4 l) +{ + WordEntryPos *ptr, + *res; + + res = a; + if (l == 1) + return l; + + qsort((void *) a, l, sizeof(WordEntryPos), comparePos); + + ptr = a + 1; + while (ptr - a < l) + { + if (ptr->pos != res->pos) + { + res++; + res->pos = ptr->pos; + res->weight = ptr->weight; + if (res - a >= MAXNUMPOS - 1 || res->pos == MAXENTRYPOS - 1) + break; + } + else if (ptr->weight > res->weight) + res->weight = ptr->weight; + ptr++; + } + return res + 1 - a; +} + +static char *BufferStr; +static int +compareentry(const void *a, const void *b) +{ + if (((WordEntryIN *) a)->entry.len == ((WordEntryIN *) b)->entry.len) + { + return strncmp( + &BufferStr[((WordEntryIN *) a)->entry.pos], + &BufferStr[((WordEntryIN *) b)->entry.pos], + ((WordEntryIN *) a)->entry.len); + } + return (((WordEntryIN *) a)->entry.len > ((WordEntryIN *) b)->entry.len) ? 1 : -1; +} + +static int +uniqueentry(WordEntryIN * a, int4 l, char *buf, int4 *outbuflen) +{ + WordEntryIN *ptr, + *res; + + res = a; + if (l == 1) + { + if (a->entry.haspos) + { + *(uint16 *) (a->pos) = uniquePos(&(a->pos[1]), *(uint16 *) (a->pos)); + *outbuflen = SHORTALIGN(res->entry.len) + (*(uint16 *) (a->pos) + 1) * sizeof(WordEntryPos); + } + return l; + } + + ptr = a + 1; + BufferStr = buf; + qsort((void *) a, l, sizeof(WordEntryIN), compareentry); + + while (ptr - a < l) + { + if (!(ptr->entry.len == res->entry.len && + strncmp(&buf[ptr->entry.pos], &buf[res->entry.pos], res->entry.len) == 0)) + { + if (res->entry.haspos) + { + *(uint16 *) (res->pos) = uniquePos(&(res->pos[1]), *(uint16 *) (res->pos)); + *outbuflen += *(uint16 *) (res->pos) * sizeof(WordEntryPos); + } + *outbuflen += SHORTALIGN(res->entry.len); + res++; + memcpy(res, ptr, sizeof(WordEntryIN)); + } + else if (ptr->entry.haspos) + { + if (res->entry.haspos) + { + int4 len = *(uint16 *) (ptr->pos) + 1 + *(uint16 *) (res->pos); + + res->pos = (WordEntryPos *) repalloc(res->pos, len * sizeof(WordEntryPos)); + memcpy(&(res->pos[*(uint16 *) (res->pos) + 1]), + &(ptr->pos[1]), *(uint16 *) (ptr->pos) * sizeof(WordEntryPos)); + *(uint16 *) (res->pos) += *(uint16 *) (ptr->pos); + pfree(ptr->pos); + } + else + { + res->entry.haspos = 1; + res->pos = ptr->pos; + } + } + ptr++; + } + if (res->entry.haspos) + { + *(uint16 *) (res->pos) = uniquePos(&(res->pos[1]), *(uint16 *) (res->pos)); + *outbuflen += *(uint16 *) (res->pos) * sizeof(WordEntryPos); + } + *outbuflen += SHORTALIGN(res->entry.len); + + return res + 1 - a; +} + +#define WAITWORD 1 +#define WAITENDWORD 2 +#define WAITNEXTCHAR 3 +#define WAITENDCMPLX 4 +#define WAITPOSINFO 5 +#define INPOSINFO 6 +#define WAITPOSDELIM 7 + +#define RESIZEPRSBUF \ +do { \ + if ( state->curpos - state->word + 1 >= state->len ) \ + { \ + int4 clen = state->curpos - state->word; \ + state->len *= 2; \ + state->word = (char*)repalloc( (void*)state->word, state->len ); \ + state->curpos = state->word + clen; \ + } \ +} while (0) + +int4 +gettoken_tsvector(TI_IN_STATE * state) +{ + int4 oldstate = 0; + + state->curpos = state->word; + state->state = WAITWORD; + state->alen = 0; + + while (1) + { + if (state->state == WAITWORD) + { + if (*(state->prsbuf) == '\0') + return 0; + else if (*(state->prsbuf) == '\'') + state->state = WAITENDCMPLX; + else if (*(state->prsbuf) == '\\') + { + state->state = WAITNEXTCHAR; + oldstate = WAITENDWORD; + } + else if (state->oprisdelim && ISOPERATOR(*(state->prsbuf))) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + else if (*(state->prsbuf) != ' ') + { + *(state->curpos) = *(state->prsbuf); + state->curpos++; + state->state = WAITENDWORD; + } + } + else if (state->state == WAITNEXTCHAR) + { + if (*(state->prsbuf) == '\0') + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("there is no escaped character"))); + else + { + RESIZEPRSBUF; + *(state->curpos) = *(state->prsbuf); + state->curpos++; + state->state = oldstate; + } + } + else if (state->state == WAITENDWORD) + { + if (*(state->prsbuf) == '\\') + { + state->state = WAITNEXTCHAR; + oldstate = WAITENDWORD; + } + else if (*(state->prsbuf) == ' ' || *(state->prsbuf) == '\0' || + (state->oprisdelim && ISOPERATOR(*(state->prsbuf)))) + { + RESIZEPRSBUF; + if (state->curpos == state->word) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + *(state->curpos) = '\0'; + return 1; + } + else if (*(state->prsbuf) == ':') + { + if (state->curpos == state->word) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + *(state->curpos) = '\0'; + if (state->oprisdelim) + return 1; + else + state->state = INPOSINFO; + } + else + { + RESIZEPRSBUF; + *(state->curpos) = *(state->prsbuf); + state->curpos++; + } + } + else if (state->state == WAITENDCMPLX) + { + if (*(state->prsbuf) == '\'') + { + RESIZEPRSBUF; + *(state->curpos) = '\0'; + if (state->curpos == state->word) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + if (state->oprisdelim) + { + state->prsbuf++; + return 1; + } + else + state->state = WAITPOSINFO; + } + else if (*(state->prsbuf) == '\\') + { + state->state = WAITNEXTCHAR; + oldstate = WAITENDCMPLX; + } + else if (*(state->prsbuf) == '\0') + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + else + { + RESIZEPRSBUF; + *(state->curpos) = *(state->prsbuf); + state->curpos++; + } + } + else if (state->state == WAITPOSINFO) + { + if (*(state->prsbuf) == ':') + state->state = INPOSINFO; + else + return 1; + } + else if (state->state == INPOSINFO) + { + if (isdigit(*(state->prsbuf))) + { + if (state->alen == 0) + { + state->alen = 4; + state->pos = (WordEntryPos *) palloc(sizeof(WordEntryPos) * state->alen); + *(uint16 *) (state->pos) = 0; + } + else if (*(uint16 *) (state->pos) + 1 >= state->alen) + { + state->alen *= 2; + state->pos = (WordEntryPos *) repalloc(state->pos, sizeof(WordEntryPos) * state->alen); + } + (*(uint16 *) (state->pos))++; + state->pos[*(uint16 *) (state->pos)].pos = LIMITPOS(atoi(state->prsbuf)); + if (state->pos[*(uint16 *) (state->pos)].pos == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("wrong position info"))); + state->pos[*(uint16 *) (state->pos)].weight = 0; + state->state = WAITPOSDELIM; + } + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + } + else if (state->state == WAITPOSDELIM) + { + if (*(state->prsbuf) == ',') + state->state = INPOSINFO; + else if (tolower(*(state->prsbuf)) == 'a' || *(state->prsbuf) == '*') + { + if (state->pos[*(uint16 *) (state->pos)].weight) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + state->pos[*(uint16 *) (state->pos)].weight = 3; + } + else if (tolower(*(state->prsbuf)) == 'b') + { + if (state->pos[*(uint16 *) (state->pos)].weight) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + state->pos[*(uint16 *) (state->pos)].weight = 2; + } + else if (tolower(*(state->prsbuf)) == 'c') + { + if (state->pos[*(uint16 *) (state->pos)].weight) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + state->pos[*(uint16 *) (state->pos)].weight = 1; + } + else if (tolower(*(state->prsbuf)) == 'd') + { + if (state->pos[*(uint16 *) (state->pos)].weight) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + state->pos[*(uint16 *) (state->pos)].weight = 0; + } + else if (isspace(*(state->prsbuf)) || *(state->prsbuf) == '\0') + return 1; + else if (!isdigit(*(state->prsbuf))) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"))); + } + else + /* internal error */ + elog(ERROR, "internal error"); + state->prsbuf++; + } + + return 0; +} + +Datum +tsvector_in(PG_FUNCTION_ARGS) +{ + char *buf = PG_GETARG_CSTRING(0); + TI_IN_STATE state; + WordEntryIN *arr; + WordEntry *inarr; + int4 len = 0, + totallen = 64; + tsvector *in; + char *tmpbuf, + *cur; + int4 i, + buflen = 256; + + state.prsbuf = buf; + state.len = 32; + state.word = (char *) palloc(state.len); + state.oprisdelim = false; + + arr = (WordEntryIN *) palloc(sizeof(WordEntryIN) * totallen); + cur = tmpbuf = (char *) palloc(buflen); + while (gettoken_tsvector(&state)) + { + if (len >= totallen) + { + totallen *= 2; + arr = (WordEntryIN *) repalloc((void *) arr, sizeof(WordEntryIN) * totallen); + } + while ((cur - tmpbuf) + (state.curpos - state.word) >= buflen) + { + int4 dist = cur - tmpbuf; + + buflen *= 2; + tmpbuf = (char *) repalloc((void *) tmpbuf, buflen); + cur = tmpbuf + dist; + } + if (state.curpos - state.word >= MAXSTRLEN) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("word is too long"))); + arr[len].entry.len = state.curpos - state.word; + if (cur - tmpbuf > MAXSTRPOS) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("too long value"))); + arr[len].entry.pos = cur - tmpbuf; + memcpy((void *) cur, (void *) state.word, arr[len].entry.len); + cur += arr[len].entry.len; + if (state.alen) + { + arr[len].entry.haspos = 1; + arr[len].pos = state.pos; + } + else + arr[len].entry.haspos = 0; + len++; + } + pfree(state.word); + + if (len > 0) + len = uniqueentry(arr, len, tmpbuf, &buflen); + totallen = CALCDATASIZE(len, buflen); + in = (tsvector *) palloc(totallen); + memset(in, 0, totallen); + in->len = totallen; + in->size = len; + cur = STRPTR(in); + inarr = ARRPTR(in); + for (i = 0; i < len; i++) + { + memcpy((void *) cur, (void *) &tmpbuf[arr[i].entry.pos], arr[i].entry.len); + arr[i].entry.pos = cur - STRPTR(in); + cur += SHORTALIGN(arr[i].entry.len); + if (arr[i].entry.haspos) + { + memcpy(cur, arr[i].pos, (*(uint16 *) arr[i].pos + 1) * sizeof(WordEntryPos)); + cur += (*(uint16 *) arr[i].pos + 1) * sizeof(WordEntryPos); + pfree(arr[i].pos); + } + memcpy(&(inarr[i]), &(arr[i].entry), sizeof(WordEntry)); + } + pfree(tmpbuf); + pfree(arr); + PG_RETURN_POINTER(in); +} + +Datum +tsvector_length(PG_FUNCTION_ARGS) +{ + tsvector *in = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int4 ret = in->size; + + PG_FREE_IF_COPY(in, 0); + PG_RETURN_INT32(ret); +} + +Datum +tsvector_out(PG_FUNCTION_ARGS) +{ + tsvector *out = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *outbuf; + int4 i, + j, + lenbuf = 0, + pp; + WordEntry *ptr = ARRPTR(out); + char *curin, + *curout; + + lenbuf = out->size * 2 /* '' */ + out->size - 1 /* space */ + 2 /* \0 */ ; + for (i = 0; i < out->size; i++) + { + lenbuf += ptr[i].len * 2 /* for escape */ ; + if (ptr[i].haspos) + lenbuf += 7 * POSDATALEN(out, &(ptr[i])); + } + + curout = outbuf = (char *) palloc(lenbuf); + for (i = 0; i < out->size; i++) + { + curin = STRPTR(out) + ptr->pos; + if (i != 0) + *curout++ = ' '; + *curout++ = '\''; + j = ptr->len; + while (j--) + { + if (*curin == '\'') + { + int4 pos = curout - outbuf; + + outbuf = (char *) repalloc((void *) outbuf, ++lenbuf); + curout = outbuf + pos; + *curout++ = '\\'; + } + *curout++ = *curin++; + } + *curout++ = '\''; + if ((pp = POSDATALEN(out, ptr)) != 0) + { + WordEntryPos *wptr; + + *curout++ = ':'; + wptr = POSDATAPTR(out, ptr); + while (pp) + { + sprintf(curout, "%d", wptr->pos); + curout = strchr(curout, '\0'); + switch (wptr->weight) + { + case 3: + *curout++ = 'A'; + break; + case 2: + *curout++ = 'B'; + break; + case 1: + *curout++ = 'C'; + break; + case 0: + default: + break; + } + if (pp > 1) + *curout++ = ','; + pp--; + wptr++; + } + } + ptr++; + } + *curout = '\0'; + outbuf[lenbuf - 1] = '\0'; + PG_FREE_IF_COPY(out, 0); + PG_RETURN_POINTER(outbuf); +} + +static int +compareWORD(const void *a, const void *b) +{ + if (((WORD *) a)->len == ((WORD *) b)->len) + { + int res = strncmp( + ((WORD *) a)->word, + ((WORD *) b)->word, + ((WORD *) b)->len); + + if (res == 0) + return (((WORD *) a)->pos.pos > ((WORD *) b)->pos.pos) ? 1 : -1; + return res; + } + return (((WORD *) a)->len > ((WORD *) b)->len) ? 1 : -1; +} + +static int +uniqueWORD(WORD * a, int4 l) +{ + WORD *ptr, + *res; + int tmppos; + + if (l == 1) + { + tmppos = LIMITPOS(a->pos.pos); + a->alen = 2; + a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen); + a->pos.apos[0] = 1; + a->pos.apos[1] = tmppos; + return l; + } + + res = a; + ptr = a + 1; + + qsort((void *) a, l, sizeof(WORD), compareWORD); + tmppos = LIMITPOS(a->pos.pos); + a->alen = 2; + a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen); + a->pos.apos[0] = 1; + a->pos.apos[1] = tmppos; + + while (ptr - a < l) + { + if (!(ptr->len == res->len && + strncmp(ptr->word, res->word, res->len) == 0)) + { + res++; + res->len = ptr->len; + res->word = ptr->word; + tmppos = LIMITPOS(ptr->pos.pos); + res->alen = 2; + res->pos.apos = (uint16 *) palloc(sizeof(uint16) * res->alen); + res->pos.apos[0] = 1; + res->pos.apos[1] = tmppos; + } + else + { + pfree(ptr->word); + if (res->pos.apos[0] < MAXNUMPOS - 1 && res->pos.apos[res->pos.apos[0]] != MAXENTRYPOS - 1) + { + if (res->pos.apos[0] + 1 >= res->alen) + { + res->alen *= 2; + res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen); + } + res->pos.apos[res->pos.apos[0] + 1] = LIMITPOS(ptr->pos.pos); + res->pos.apos[0]++; + } + } + ptr++; + } + + return res + 1 - a; +} + +/* + * make value of tsvector + */ +static tsvector * +makevalue(PRSTEXT * prs) +{ + int4 i, + j, + lenstr = 0, + totallen; + tsvector *in; + WordEntry *ptr; + char *str, + *cur; + + prs->curwords = uniqueWORD(prs->words, prs->curwords); + for (i = 0; i < prs->curwords; i++) + { + lenstr += SHORTALIGN(prs->words[i].len); + + if (prs->words[i].alen) + lenstr += sizeof(uint16) + prs->words[i].pos.apos[0] * sizeof(WordEntryPos); + } + + totallen = CALCDATASIZE(prs->curwords, lenstr); + in = (tsvector *) palloc(totallen); + memset(in, 0, totallen); + in->len = totallen; + in->size = prs->curwords; + + ptr = ARRPTR(in); + cur = str = STRPTR(in); + for (i = 0; i < prs->curwords; i++) + { + ptr->len = prs->words[i].len; + if (cur - str > MAXSTRPOS) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("value is too big"))); + ptr->pos = cur - str; + memcpy((void *) cur, (void *) prs->words[i].word, prs->words[i].len); + pfree(prs->words[i].word); + cur += SHORTALIGN(prs->words[i].len); + if (prs->words[i].alen) + { + WordEntryPos *wptr; + + ptr->haspos = 1; + *(uint16 *) cur = prs->words[i].pos.apos[0]; + wptr = POSDATAPTR(in, ptr); + for (j = 0; j < *(uint16 *) cur; j++) + { + wptr[j].weight = 0; + wptr[j].pos = prs->words[i].pos.apos[j + 1]; + } + cur += sizeof(uint16) + prs->words[i].pos.apos[0] * sizeof(WordEntryPos); + pfree(prs->words[i].pos.apos); + } + else + ptr->haspos = 0; + ptr++; + } + pfree(prs->words); + return in; +} + + +Datum +to_tsvector(PG_FUNCTION_ARGS) +{ + text *in = PG_GETARG_TEXT_P(1); + PRSTEXT prs; + tsvector *out = NULL; + TSCfgInfo *cfg = findcfg(PG_GETARG_INT32(0)); + + prs.lenwords = 32; + prs.curwords = 0; + prs.pos = 0; + prs.words = (WORD *) palloc(sizeof(WORD) * prs.lenwords); + + parsetext_v2(cfg, &prs, VARDATA(in), VARSIZE(in) - VARHDRSZ); + PG_FREE_IF_COPY(in, 1); + + if (prs.curwords) + out = makevalue(&prs); + else + { + pfree(prs.words); + out = palloc(CALCDATASIZE(0, 0)); + out->len = CALCDATASIZE(0, 0); + out->size = 0; + } + PG_RETURN_POINTER(out); +} + +Datum +to_tsvector_name(PG_FUNCTION_ARGS) +{ + text *cfg = PG_GETARG_TEXT_P(0); + Datum res = DirectFunctionCall3( + to_tsvector, + Int32GetDatum(name2id_cfg(cfg)), + PG_GETARG_DATUM(1), + (Datum) 0 + ); + + PG_FREE_IF_COPY(cfg, 0); + PG_RETURN_DATUM(res); +} + +Datum +to_tsvector_current(PG_FUNCTION_ARGS) +{ + Datum res = DirectFunctionCall3( + to_tsvector, + Int32GetDatum(get_currcfg()), + PG_GETARG_DATUM(0), + (Datum) 0 + ); + + PG_RETURN_DATUM(res); +} + +static Oid +findFunc(char *fname) +{ + FuncCandidateList clist, + ptr; + Oid funcid = InvalidOid; + List *names = makeList1(makeString(fname)); + + ptr = clist = FuncnameGetCandidates(names, 1); + freeList(names); + + if (!ptr) + return funcid; + + while (ptr) + { + if (ptr->args[0] == TEXTOID && funcid == InvalidOid) + funcid = ptr->oid; + clist = ptr->next; + pfree(ptr); + ptr = clist; + } + + return funcid; +} + +/* + * Trigger + */ +Datum +tsearch2(PG_FUNCTION_ARGS) +{ + TriggerData *trigdata; + Trigger *trigger; + Relation rel; + HeapTuple rettuple = NULL; + TSCfgInfo *cfg = findcfg(get_currcfg()); + int numidxattr, + i; + PRSTEXT prs; + Datum datum = (Datum) 0; + Oid funcoid = InvalidOid; + + if (!CALLED_AS_TRIGGER(fcinfo)) + /* internal error */ + elog(ERROR, "TSearch: Not fired by trigger manager"); + + trigdata = (TriggerData *) fcinfo->context; + if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + /* internal error */ + elog(ERROR, "TSearch: Can't process STATEMENT events"); + if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) + /* internal error */ + elog(ERROR, "TSearch: Must be fired BEFORE event"); + + if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) + rettuple = trigdata->tg_trigtuple; + else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) + rettuple = trigdata->tg_newtuple; + else + /* internal error */ + elog(ERROR, "TSearch: Unknown event"); + + trigger = trigdata->tg_trigger; + rel = trigdata->tg_relation; + + if (trigger->tgnargs < 2) + /* internal error */ + elog(ERROR, "TSearch: format tsearch2(tsvector_field, text_field1,...)"); + + numidxattr = SPI_fnumber(rel->rd_att, trigger->tgargs[0]); + if (numidxattr == SPI_ERROR_NOATTRIBUTE) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("tsvector column \"%s\" does not exist", + trigger->tgargs[0]))); + + prs.lenwords = 32; + prs.curwords = 0; + prs.pos = 0; + prs.words = (WORD *) palloc(sizeof(WORD) * prs.lenwords); + + /* find all words in indexable column */ + for (i = 1; i < trigger->tgnargs; i++) + { + int numattr; + Oid oidtype; + Datum txt_toasted; + bool isnull; + text *txt; + + numattr = SPI_fnumber(rel->rd_att, trigger->tgargs[i]); + if (numattr == SPI_ERROR_NOATTRIBUTE) + { + funcoid = findFunc(trigger->tgargs[i]); + if (funcoid == InvalidOid) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("could not find function or field \"%s\"", + trigger->tgargs[i]))); + + continue; + } + oidtype = SPI_gettypeid(rel->rd_att, numattr); + /* We assume char() and varchar() are binary-equivalent to text */ + if (!(oidtype == TEXTOID || + oidtype == VARCHAROID || + oidtype == BPCHAROID)) + { + elog(WARNING, "TSearch: '%s' is not of character type", + trigger->tgargs[i]); + continue; + } + txt_toasted = SPI_getbinval(rettuple, rel->rd_att, numattr, &isnull); + if (isnull) + continue; + + if (funcoid != InvalidOid) + { + text *txttmp = (text *) DatumGetPointer(OidFunctionCall1( + funcoid, + PointerGetDatum(txt_toasted) + )); + + txt = (text *) DatumGetPointer(PG_DETOAST_DATUM(PointerGetDatum(txttmp))); + if (txt == txttmp) + txt_toasted = PointerGetDatum(txt); + } + else + txt = (text *) DatumGetPointer(PG_DETOAST_DATUM(PointerGetDatum(txt_toasted))); + + parsetext_v2(cfg, &prs, VARDATA(txt), VARSIZE(txt) - VARHDRSZ); + if (txt != (text *) DatumGetPointer(txt_toasted)) + pfree(txt); + } + + /* make tsvector value */ + if (prs.curwords) + { + datum = PointerGetDatum(makevalue(&prs)); + rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr, + &datum, NULL); + pfree(DatumGetPointer(datum)); + } + else + { + tsvector *out = palloc(CALCDATASIZE(0, 0)); + + out->len = CALCDATASIZE(0, 0); + out->size = 0; + datum = PointerGetDatum(out); + pfree(prs.words); + rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr, + &datum, NULL); + } + + if (rettuple == NULL) + /* internal error */ + elog(ERROR, "TSearch: %d returned by SPI_modifytuple", SPI_result); + + return PointerGetDatum(rettuple); +} diff --git a/contrib/tsearch2/tsvector.h b/contrib/tsearch2/tsvector.h new file mode 100644 index 0000000..bb69524 --- /dev/null +++ b/contrib/tsearch2/tsvector.h @@ -0,0 +1,74 @@ +#ifndef __TXTIDX_H__ +#define __TXTIDX_H__ + +/* +#define TXTIDX_DEBUG +*/ + +#include "postgres.h" + +#include "access/gist.h" +#include "access/itup.h" +#include "utils/builtins.h" +#include "storage/bufpage.h" + +typedef struct +{ + uint32 + haspos:1, + len:11, /* MAX 2Kb */ + pos:20; /* MAX 1Mb */ +} WordEntry; + +#define MAXSTRLEN ( 1<<11 ) +#define MAXSTRPOS ( 1<<20 ) + +typedef struct +{ + uint16 + weight:2, + pos:14; +} WordEntryPos; + +#define MAXENTRYPOS (1<<14) +#define MAXNUMPOS 256 +#define LIMITPOS(x) ( ( (x) >= MAXENTRYPOS ) ? (MAXENTRYPOS-1) : (x) ) + +typedef struct +{ + int4 len; + int4 size; + char data[1]; +} tsvector; + +#define DATAHDRSIZE (sizeof(int4)*2) +#define CALCDATASIZE(x, lenstr) ( x * sizeof(WordEntry) + DATAHDRSIZE + lenstr ) +#define ARRPTR(x) ( (WordEntry*) ( (char*)x + DATAHDRSIZE ) ) +#define STRPTR(x) ( (char*)x + DATAHDRSIZE + ( sizeof(WordEntry) * ((tsvector*)x)->size ) ) +#define STRSIZE(x) ( ((tsvector*)x)->len - DATAHDRSIZE - ( sizeof(WordEntry) * ((tsvector*)x)->size ) ) +#define _POSDATAPTR(x,e) (STRPTR(x)+((WordEntry*)(e))->pos+SHORTALIGN(((WordEntry*)(e))->len)) +#define POSDATALEN(x,e) ( ( ((WordEntry*)(e))->haspos ) ? (*(uint16*)_POSDATAPTR(x,e)) : 0 ) +#define POSDATAPTR(x,e) ( (WordEntryPos*)( _POSDATAPTR(x,e)+sizeof(uint16) ) ) + + +typedef struct +{ + WordEntry entry; + WordEntryPos *pos; +} WordEntryIN; + +typedef struct +{ + char *prsbuf; + char *word; + char *curpos; + int4 len; + int4 state; + int4 alen; + WordEntryPos *pos; + bool oprisdelim; +} TI_IN_STATE; + +int4 gettoken_tsvector(TI_IN_STATE * state); + +#endif diff --git a/contrib/tsearch2/tsvector_op.c b/contrib/tsearch2/tsvector_op.c new file mode 100644 index 0000000..2ffd4ca --- /dev/null +++ b/contrib/tsearch2/tsvector_op.c @@ -0,0 +1,329 @@ +/* + * Operations for tsvector type + * Teodor Sigaev + */ +#include "postgres.h" + +#include "access/gist.h" +#include "access/itup.h" +#include "utils/builtins.h" +#include "storage/bufpage.h" +#include "executor/spi.h" +#include "commands/trigger.h" +#include "nodes/pg_list.h" +#include "catalog/namespace.h" + +#include "utils/pg_locale.h" + +#include /* tolower */ +#include "tsvector.h" +#include "query.h" +#include "ts_cfg.h" +#include "common.h" + +PG_FUNCTION_INFO_V1(strip); +Datum strip(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(setweight); +Datum setweight(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(concat); +Datum concat(PG_FUNCTION_ARGS); + +Datum +strip(PG_FUNCTION_ARGS) +{ + tsvector *in = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + tsvector *out; + int i, + len = 0; + WordEntry *arrin = ARRPTR(in), + *arrout; + char *cur; + + for (i = 0; i < in->size; i++) + len += SHORTALIGN(arrin[i].len); + + len = CALCDATASIZE(in->size, len); + out = (tsvector *) palloc(len); + memset(out, 0, len); + out->len = len; + out->size = in->size; + arrout = ARRPTR(out); + cur = STRPTR(out); + for (i = 0; i < in->size; i++) + { + memcpy(cur, STRPTR(in) + arrin[i].pos, arrin[i].len); + arrout[i].haspos = 0; + arrout[i].len = arrin[i].len; + arrout[i].pos = cur - STRPTR(out); + cur += SHORTALIGN(arrout[i].len); + } + + PG_FREE_IF_COPY(in, 0); + PG_RETURN_POINTER(out); +} + +Datum +setweight(PG_FUNCTION_ARGS) +{ + tsvector *in = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char cw = PG_GETARG_CHAR(1); + tsvector *out; + int i, + j; + WordEntry *entry; + WordEntryPos *p; + int w = 0; + + switch (tolower(cw)) + { + case 'a': + w = 3; + break; + case 'b': + w = 2; + break; + case 'c': + w = 1; + break; + case 'd': + w = 0; + break; + /* internal error */ + default: + elog(ERROR, "unrecognized weight"); + } + + out = (tsvector *) palloc(in->len); + memcpy(out, in, in->len); + entry = ARRPTR(out); + i = out->size; + while (i--) + { + if ((j = POSDATALEN(out, entry)) != 0) + { + p = POSDATAPTR(out, entry); + while (j--) + { + p->weight = w; + p++; + } + } + entry++; + } + + PG_FREE_IF_COPY(in, 0); + PG_RETURN_POINTER(out); +} + +static int +compareEntry(char *ptra, WordEntry * a, char *ptrb, WordEntry * b) +{ + if (a->len == b->len) + { + return strncmp( + ptra + a->pos, + ptrb + b->pos, + a->len); + } + return (a->len > b->len) ? 1 : -1; +} + +static int4 +add_pos(tsvector * src, WordEntry * srcptr, tsvector * dest, WordEntry * destptr, int4 maxpos) +{ + uint16 *clen = (uint16 *) _POSDATAPTR(dest, destptr); + int i; + uint16 slen = POSDATALEN(src, srcptr), + startlen; + WordEntryPos *spos = POSDATAPTR(src, srcptr), + *dpos = POSDATAPTR(dest, destptr); + + if (!destptr->haspos) + *clen = 0; + + startlen = *clen; + for (i = 0; i < slen && *clen < MAXNUMPOS && (*clen == 0 || dpos[*clen - 1].pos != MAXENTRYPOS - 1); i++) + { + dpos[*clen].weight = spos[i].weight; + dpos[*clen].pos = LIMITPOS(spos[i].pos + maxpos); + (*clen)++; + } + + if (*clen != startlen) + destptr->haspos = 1; + return *clen - startlen; +} + + +Datum +concat(PG_FUNCTION_ARGS) +{ + tsvector *in1 = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + tsvector *in2 = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + tsvector *out; + WordEntry *ptr; + WordEntry *ptr1, + *ptr2; + WordEntryPos *p; + int maxpos = 0, + i, + j, + i1, + i2; + char *cur; + char *data, + *data1, + *data2; + + ptr = ARRPTR(in1); + i = in1->size; + while (i--) + { + if ((j = POSDATALEN(in1, ptr)) != 0) + { + p = POSDATAPTR(in1, ptr); + while (j--) + { + if (p->pos > maxpos) + maxpos = p->pos; + p++; + } + } + ptr++; + } + + ptr1 = ARRPTR(in1); + ptr2 = ARRPTR(in2); + data1 = STRPTR(in1); + data2 = STRPTR(in2); + i1 = in1->size; + i2 = in2->size; + out = (tsvector *) palloc(in1->len + in2->len); + memset(out, 0, in1->len + in2->len); + out->len = in1->len + in2->len; + out->size = in1->size + in2->size; + data = cur = STRPTR(out); + ptr = ARRPTR(out); + while (i1 && i2) + { + int cmp = compareEntry(data1, ptr1, data2, ptr2); + + if (cmp < 0) + { /* in1 first */ + ptr->haspos = ptr1->haspos; + ptr->len = ptr1->len; + memcpy(cur, data1 + ptr1->pos, ptr1->len); + ptr->pos = cur - data; + cur += SHORTALIGN(ptr1->len); + if (ptr->haspos) + { + memcpy(cur, _POSDATAPTR(in1, ptr1), POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16)); + cur += POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16); + } + ptr++; + ptr1++; + i1--; + } + else if (cmp > 0) + { /* in2 first */ + ptr->haspos = ptr2->haspos; + ptr->len = ptr2->len; + memcpy(cur, data2 + ptr2->pos, ptr2->len); + ptr->pos = cur - data; + cur += SHORTALIGN(ptr2->len); + if (ptr->haspos) + { + int addlen = add_pos(in2, ptr2, out, ptr, maxpos); + + if (addlen == 0) + ptr->haspos = 0; + else + cur += addlen * sizeof(WordEntryPos) + sizeof(uint16); + } + ptr++; + ptr2++; + i2--; + } + else + { + ptr->haspos = ptr1->haspos | ptr2->haspos; + ptr->len = ptr1->len; + memcpy(cur, data1 + ptr1->pos, ptr1->len); + ptr->pos = cur - data; + cur += SHORTALIGN(ptr1->len); + if (ptr->haspos) + { + if (ptr1->haspos) + { + memcpy(cur, _POSDATAPTR(in1, ptr1), POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16)); + cur += POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16); + if (ptr2->haspos) + cur += add_pos(in2, ptr2, out, ptr, maxpos) * sizeof(WordEntryPos); + } + else if (ptr2->haspos) + { + int addlen = add_pos(in2, ptr2, out, ptr, maxpos); + + if (addlen == 0) + ptr->haspos = 0; + else + cur += addlen * sizeof(WordEntryPos) + sizeof(uint16); + } + } + ptr++; + ptr1++; + ptr2++; + i1--; + i2--; + } + } + + while (i1) + { + ptr->haspos = ptr1->haspos; + ptr->len = ptr1->len; + memcpy(cur, data1 + ptr1->pos, ptr1->len); + ptr->pos = cur - data; + cur += SHORTALIGN(ptr1->len); + if (ptr->haspos) + { + memcpy(cur, _POSDATAPTR(in1, ptr1), POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16)); + cur += POSDATALEN(in1, ptr1) * sizeof(WordEntryPos) + sizeof(uint16); + } + ptr++; + ptr1++; + i1--; + } + + while (i2) + { + ptr->haspos = ptr2->haspos; + ptr->len = ptr2->len; + memcpy(cur, data2 + ptr2->pos, ptr2->len); + ptr->pos = cur - data; + cur += SHORTALIGN(ptr2->len); + if (ptr->haspos) + { + int addlen = add_pos(in2, ptr2, out, ptr, maxpos); + + if (addlen == 0) + ptr->haspos = 0; + else + cur += addlen * sizeof(WordEntryPos) + sizeof(uint16); + } + ptr++; + ptr2++; + i2--; + } + + out->size = ptr - ARRPTR(out); + out->len = CALCDATASIZE(out->size, cur - data); + if (data != STRPTR(out)) + memmove(STRPTR(out), data, cur - data); + + PG_FREE_IF_COPY(in1, 0); + PG_FREE_IF_COPY(in2, 1); + PG_RETURN_POINTER(out); +} diff --git a/contrib/tsearch2/untsearch.sql.in b/contrib/tsearch2/untsearch.sql.in new file mode 100644 index 0000000..e7cfcc6 --- /dev/null +++ b/contrib/tsearch2/untsearch.sql.in @@ -0,0 +1,65 @@ +BEGIN; + +--Be careful !!! +--script drops all indices, triggers and columns with types defined +--in tsearch2.sql + + +DROP OPERATOR CLASS gist_tsvector_ops USING gist CASCADE; + + +DROP OPERATOR || (tsvector, tsvector); +DROP OPERATOR @@ (tsvector, tsquery); +DROP OPERATOR @@ (tsquery, tsvector); + +DROP AGGREGATE stat(tsvector); + +DROP TABLE pg_ts_dict; +DROP TABLE pg_ts_parser; +DROP TABLE pg_ts_cfg; +DROP TABLE pg_ts_cfgmap; + +DROP TYPE tokentype CASCADE; +DROP TYPE tokenout CASCADE; +DROP TYPE tsvector CASCADE; +DROP TYPE tsquery CASCADE; +DROP TYPE gtsvector CASCADE; +DROP TYPE tsstat CASCADE; +DROP TYPE statinfo CASCADE; +DROP TYPE tsdebug CASCADE; + + +DROP FUNCTION lexize(oid, text) ; +DROP FUNCTION lexize(text, text); +DROP FUNCTION lexize(text); +DROP FUNCTION set_curdict(int); +DROP FUNCTION set_curdict(text); +DROP FUNCTION dex_init(text); +DROP FUNCTION dex_lexize(internal,internal,int4); +DROP FUNCTION snb_en_init(text); +DROP FUNCTION snb_lexize(internal,internal,int4); +DROP FUNCTION snb_ru_init(text); +DROP FUNCTION spell_init(text); +DROP FUNCTION spell_lexize(internal,internal,int4); +DROP FUNCTION syn_init(text); +DROP FUNCTION syn_lexize(internal,internal,int4); +DROP FUNCTION set_curprs(int); +DROP FUNCTION set_curprs(text); +DROP FUNCTION prsd_start(internal,int4); +DROP FUNCTION prsd_getlexeme(internal,internal,internal); +DROP FUNCTION prsd_end(internal); +DROP FUNCTION prsd_lextype(internal); +DROP FUNCTION prsd_headline(internal,internal,internal); +DROP FUNCTION set_curcfg(int); +DROP FUNCTION set_curcfg(text); +DROP FUNCTION show_curcfg(); +DROP FUNCTION gtsvector_compress(internal); +DROP FUNCTION gtsvector_decompress(internal); +DROP FUNCTION gtsvector_penalty(internal,internal,internal); +DROP FUNCTION gtsvector_picksplit(internal, internal); +DROP FUNCTION gtsvector_union(bytea, internal); +DROP FUNCTION reset_tsearch(); +DROP FUNCTION tsearch2() CASCADE; +DROP FUNCTION _get_parser_from_curcfg(); + +END; diff --git a/contrib/tsearch2/wordparser/deflex.c b/contrib/tsearch2/wordparser/deflex.c new file mode 100644 index 0000000..bbf3271 --- /dev/null +++ b/contrib/tsearch2/wordparser/deflex.c @@ -0,0 +1,55 @@ +#include "deflex.h" + +const char *lex_descr[] = { + "", + "Latin word", + "Non-latin word", + "Word", + "Email", + "URL", + "Host", + "Scientific notation", + "VERSION", + "Part of hyphenated word", + "Non-latin part of hyphenated word", + "Latin part of hyphenated word", + "Space symbols", + "HTML Tag", + "HTTP head", + "Hyphenated word", + "Latin hyphenated word", + "Non-latin hyphenated word", + "URI", + "File or path name", + "Decimal notation", + "Signed integer", + "Unsigned integer", + "HTML Entity" +}; + +const char *tok_alias[] = { + "", + "lword", + "nlword", + "word", + "email", + "url", + "host", + "sfloat", + "version", + "part_hword", + "nlpart_hword", + "lpart_hword", + "blank", + "tag", + "http", + "hword", + "lhword", + "nlhword", + "uri", + "file", + "float", + "int", + "uint", + "entity" +}; diff --git a/contrib/tsearch2/wordparser/deflex.h b/contrib/tsearch2/wordparser/deflex.h new file mode 100644 index 0000000..651d1f9 --- /dev/null +++ b/contrib/tsearch2/wordparser/deflex.h @@ -0,0 +1,34 @@ +#ifndef __DEFLEX_H__ +#define __DEFLEX_H__ + +/* rememder !!!! */ +#define LASTNUM 23 + +#define LATWORD 1 +#define CYRWORD 2 +#define UWORD 3 +#define EMAIL 4 +#define FURL 5 +#define HOST 6 +#define SCIENTIFIC 7 +#define VERSIONNUMBER 8 +#define PARTHYPHENWORD 9 +#define CYRPARTHYPHENWORD 10 +#define LATPARTHYPHENWORD 11 +#define SPACE 12 +#define TAG 13 +#define HTTP 14 +#define HYPHENWORD 15 +#define LATHYPHENWORD 16 +#define CYRHYPHENWORD 17 +#define URI 18 +#define FILEPATH 19 +#define DECIMAL 20 +#define SIGNEDINT 21 +#define UNSIGNEDINT 22 +#define HTMLENTITY 23 + +extern const char *lex_descr[]; +extern const char *tok_alias[]; + +#endif diff --git a/contrib/tsearch2/wparser.c b/contrib/tsearch2/wparser.c new file mode 100644 index 0000000..b7e45e5 --- /dev/null +++ b/contrib/tsearch2/wparser.c @@ -0,0 +1,581 @@ +/* + * interface functions to parser + * Teodor Sigaev + */ +#include +#include +#include +#include + +#include "postgres.h" +#include "fmgr.h" +#include "utils/array.h" +#include "catalog/pg_type.h" +#include "executor/spi.h" +#include "funcapi.h" + +#include "wparser.h" +#include "ts_cfg.h" +#include "snmap.h" +#include "common.h" + +/*********top interface**********/ + +static void *plan_getparser = NULL; +static Oid current_parser_id = InvalidOid; + +void +init_prs(Oid id, WParserInfo * prs) +{ + Oid arg[1] = {OIDOID}; + bool isnull; + Datum pars[1] = {ObjectIdGetDatum(id)}; + int stat; + + memset(prs, 0, sizeof(WParserInfo)); + SPI_connect(); + if (!plan_getparser) + { + plan_getparser = SPI_saveplan(SPI_prepare("select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from pg_ts_parser where oid = $1", 1, arg)); + if (!plan_getparser) + ts_error(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_getparser, pars, " ", 1); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + { + Oid oid = InvalidOid; + + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + fmgr_info_cxt(oid, &(prs->start_info), TopMemoryContext); + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &isnull)); + fmgr_info_cxt(oid, &(prs->getlexeme_info), TopMemoryContext); + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, &isnull)); + fmgr_info_cxt(oid, &(prs->end_info), TopMemoryContext); + prs->lextype = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 4, &isnull)); + oid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 5, &isnull)); + fmgr_info_cxt(oid, &(prs->headline_info), TopMemoryContext); + prs->prs_id = id; + } + else + ts_error(ERROR, "No parser with id %d", id); + SPI_finish(); +} + +typedef struct +{ + WParserInfo *last_prs; + int len; + int reallen; + WParserInfo *list; + SNMap name2id_map; +} PrsList; + +static PrsList PList = {NULL, 0, 0, NULL, {0, 0, NULL}}; + +void +reset_prs(void) +{ + freeSNMap(&(PList.name2id_map)); + if (PList.list) + free(PList.list); + memset(&PList, 0, sizeof(PrsList)); +} + +static int +compareprs(const void *a, const void *b) +{ + return ((WParserInfo *) a)->prs_id - ((WParserInfo *) b)->prs_id; +} + +WParserInfo * +findprs(Oid id) +{ + /* last used prs */ + if (PList.last_prs && PList.last_prs->prs_id == id) + return PList.last_prs; + + /* already used prs */ + if (PList.len != 0) + { + WParserInfo key; + + key.prs_id = id; + PList.last_prs = bsearch(&key, PList.list, PList.len, sizeof(WParserInfo), compareprs); + if (PList.last_prs != NULL) + return PList.last_prs; + } + + /* last chance */ + if (PList.len == PList.reallen) + { + WParserInfo *tmp; + int reallen = (PList.reallen) ? 2 * PList.reallen : 16; + + tmp = (WParserInfo *) realloc(PList.list, sizeof(WParserInfo) * reallen); + if (!tmp) + ts_error(ERROR, "No memory"); + PList.reallen = reallen; + PList.list = tmp; + } + PList.last_prs = &(PList.list[PList.len]); + init_prs(id, PList.last_prs); + PList.len++; + qsort(PList.list, PList.len, sizeof(WParserInfo), compareprs); + return findprs(id); /* qsort changed order!! */ ; +} + +static void *plan_name2id = NULL; + +Oid +name2id_prs(text *name) +{ + Oid arg[1] = {TEXTOID}; + bool isnull; + Datum pars[1] = {PointerGetDatum(name)}; + int stat; + Oid id = findSNMap_t(&(PList.name2id_map), name); + + if (id) + return id; + + + SPI_connect(); + if (!plan_name2id) + { + plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_parser where prs_name = $1", 1, arg)); + if (!plan_name2id) + ts_error(ERROR, "SPI_prepare() failed"); + } + + stat = SPI_execp(plan_name2id, pars, " ", 1); + if (stat < 0) + ts_error(ERROR, "SPI_execp return %d", stat); + if (SPI_processed > 0) + id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); + else + ts_error(ERROR, "No parser '%s'", text2char(name)); + SPI_finish(); + addSNMap_t(&(PList.name2id_map), name, id); + return id; +} + + +/******sql-level interface******/ +typedef struct +{ + int cur; + LexDescr *list; +} TypeStorage; + +static void +setup_firstcall(FuncCallContext *funcctx, Oid prsid) +{ + TupleDesc tupdesc; + MemoryContext oldcontext; + TypeStorage *st; + WParserInfo *prs = findprs(prsid); + + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + st = (TypeStorage *) palloc(sizeof(TypeStorage)); + st->cur = 0; + st->list = (LexDescr *) DatumGetPointer( + OidFunctionCall1(prs->lextype, PointerGetDatum(prs->prs)) + ); + funcctx->user_fctx = (void *) st; + tupdesc = RelationNameGetTupleDesc("tokentype"); + funcctx->slot = TupleDescGetSlot(tupdesc); + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + MemoryContextSwitchTo(oldcontext); +} + +static Datum +process_call(FuncCallContext *funcctx) +{ + TypeStorage *st; + + st = (TypeStorage *) funcctx->user_fctx; + if (st->list && st->list[st->cur].lexid) + { + Datum result; + char *values[3]; + char txtid[16]; + HeapTuple tuple; + + values[0] = txtid; + sprintf(txtid, "%d", st->list[st->cur].lexid); + values[1] = st->list[st->cur].alias; + values[2] = st->list[st->cur].descr; + + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + result = TupleGetDatum(funcctx->slot, tuple); + + pfree(values[1]); + pfree(values[2]); + st->cur++; + return result; + } + else + { + if (st->list) + pfree(st->list); + pfree(st); + } + return (Datum) 0; +} + +PG_FUNCTION_INFO_V1(token_type); +Datum token_type(PG_FUNCTION_ARGS); + +Datum +token_type(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + funcctx = SRF_FIRSTCALL_INIT(); + setup_firstcall(funcctx, PG_GETARG_OID(0)); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + +PG_FUNCTION_INFO_V1(token_type_byname); +Datum token_type_byname(PG_FUNCTION_ARGS); +Datum +token_type_byname(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + text *name = PG_GETARG_TEXT_P(0); + + funcctx = SRF_FIRSTCALL_INIT(); + setup_firstcall(funcctx, name2id_prs(name)); + PG_FREE_IF_COPY(name, 0); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + +PG_FUNCTION_INFO_V1(token_type_current); +Datum token_type_current(PG_FUNCTION_ARGS); +Datum +token_type_current(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + funcctx = SRF_FIRSTCALL_INIT(); + if (current_parser_id == InvalidOid) + current_parser_id = name2id_prs(char2text("default")); + setup_firstcall(funcctx, current_parser_id); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + + +PG_FUNCTION_INFO_V1(set_curprs); +Datum set_curprs(PG_FUNCTION_ARGS); +Datum +set_curprs(PG_FUNCTION_ARGS) +{ + findprs(PG_GETARG_OID(0)); + current_parser_id = PG_GETARG_OID(0); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(set_curprs_byname); +Datum set_curprs_byname(PG_FUNCTION_ARGS); +Datum +set_curprs_byname(PG_FUNCTION_ARGS) +{ + text *name = PG_GETARG_TEXT_P(0); + + DirectFunctionCall1( + set_curprs, + ObjectIdGetDatum(name2id_prs(name)) + ); + PG_FREE_IF_COPY(name, 0); + PG_RETURN_VOID(); +} + +typedef struct +{ + int type; + char *lexem; +} LexemEntry; + +typedef struct +{ + int cur; + int len; + LexemEntry *list; +} PrsStorage; + + +static void +prs_setup_firstcall(FuncCallContext *funcctx, int prsid, text *txt) +{ + TupleDesc tupdesc; + MemoryContext oldcontext; + PrsStorage *st; + WParserInfo *prs = findprs(prsid); + char *lex = NULL; + int llen = 0, + type = 0; + + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + st = (PrsStorage *) palloc(sizeof(PrsStorage)); + st->cur = 0; + st->len = 16; + st->list = (LexemEntry *) palloc(sizeof(LexemEntry) * st->len); + + prs->prs = (void *) DatumGetPointer( + FunctionCall2( + &(prs->start_info), + PointerGetDatum(VARDATA(txt)), + Int32GetDatum(VARSIZE(txt) - VARHDRSZ) + ) + ); + + while ((type = DatumGetInt32(FunctionCall3( + &(prs->getlexeme_info), + PointerGetDatum(prs->prs), + PointerGetDatum(&lex), + PointerGetDatum(&llen)))) != 0) + { + + if (st->cur >= st->len) + { + st->len = 2 * st->len; + st->list = (LexemEntry *) repalloc(st->list, sizeof(LexemEntry) * st->len); + } + st->list[st->cur].lexem = palloc(llen + 1); + memcpy(st->list[st->cur].lexem, lex, llen); + st->list[st->cur].lexem[llen] = '\0'; + st->list[st->cur].type = type; + st->cur++; + } + + FunctionCall1( + &(prs->end_info), + PointerGetDatum(prs->prs) + ); + + st->len = st->cur; + st->cur = 0; + + funcctx->user_fctx = (void *) st; + tupdesc = RelationNameGetTupleDesc("tokenout"); + funcctx->slot = TupleDescGetSlot(tupdesc); + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + MemoryContextSwitchTo(oldcontext); +} + +static Datum +prs_process_call(FuncCallContext *funcctx) +{ + PrsStorage *st; + + st = (PrsStorage *) funcctx->user_fctx; + if (st->cur < st->len) + { + Datum result; + char *values[2]; + char tid[16]; + HeapTuple tuple; + + values[0] = tid; + sprintf(tid, "%d", st->list[st->cur].type); + values[1] = st->list[st->cur].lexem; + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + result = TupleGetDatum(funcctx->slot, tuple); + + pfree(values[1]); + st->cur++; + return result; + } + else + { + if (st->list) + pfree(st->list); + pfree(st); + } + return (Datum) 0; +} + + + +PG_FUNCTION_INFO_V1(parse); +Datum parse(PG_FUNCTION_ARGS); +Datum +parse(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + text *txt = PG_GETARG_TEXT_P(1); + + funcctx = SRF_FIRSTCALL_INIT(); + prs_setup_firstcall(funcctx, PG_GETARG_OID(0), txt); + PG_FREE_IF_COPY(txt, 1); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = prs_process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + +PG_FUNCTION_INFO_V1(parse_byname); +Datum parse_byname(PG_FUNCTION_ARGS); +Datum +parse_byname(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + text *name = PG_GETARG_TEXT_P(0); + text *txt = PG_GETARG_TEXT_P(1); + + funcctx = SRF_FIRSTCALL_INIT(); + prs_setup_firstcall(funcctx, name2id_prs(name), txt); + PG_FREE_IF_COPY(name, 0); + PG_FREE_IF_COPY(txt, 1); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = prs_process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + + +PG_FUNCTION_INFO_V1(parse_current); +Datum parse_current(PG_FUNCTION_ARGS); +Datum +parse_current(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + text *txt = PG_GETARG_TEXT_P(0); + + funcctx = SRF_FIRSTCALL_INIT(); + if (current_parser_id == InvalidOid) + current_parser_id = name2id_prs(char2text("default")); + prs_setup_firstcall(funcctx, current_parser_id, txt); + PG_FREE_IF_COPY(txt, 0); + } + + funcctx = SRF_PERCALL_SETUP(); + + if ((result = prs_process_call(funcctx)) != (Datum) 0) + SRF_RETURN_NEXT(funcctx, result); + SRF_RETURN_DONE(funcctx); +} + +PG_FUNCTION_INFO_V1(headline); +Datum headline(PG_FUNCTION_ARGS); +Datum +headline(PG_FUNCTION_ARGS) +{ + TSCfgInfo *cfg = findcfg(PG_GETARG_OID(0)); + text *in = PG_GETARG_TEXT_P(1); + QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(2))); + text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL; + HLPRSTEXT prs; + text *out; + WParserInfo *prsobj = findprs(cfg->prs_id); + + memset(&prs, 0, sizeof(HLPRSTEXT)); + prs.lenwords = 32; + prs.words = (HLWORD *) palloc(sizeof(HLWORD) * prs.lenwords); + hlparsetext(cfg, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ); + + + FunctionCall3( + &(prsobj->headline_info), + PointerGetDatum(&prs), + PointerGetDatum(opt), + PointerGetDatum(query) + ); + + out = genhl(&prs); + + PG_FREE_IF_COPY(in, 1); + PG_FREE_IF_COPY(query, 2); + if (opt) + PG_FREE_IF_COPY(opt, 3); + pfree(prs.words); + pfree(prs.startsel); + pfree(prs.stopsel); + + PG_RETURN_POINTER(out); +} + + +PG_FUNCTION_INFO_V1(headline_byname); +Datum headline_byname(PG_FUNCTION_ARGS); +Datum +headline_byname(PG_FUNCTION_ARGS) +{ + text *cfg = PG_GETARG_TEXT_P(0); + + Datum out = DirectFunctionCall4( + headline, + ObjectIdGetDatum(name2id_cfg(cfg)), + PG_GETARG_DATUM(1), + PG_GETARG_DATUM(2), + (PG_NARGS() > 3) ? PG_GETARG_DATUM(3) : PointerGetDatum(NULL) + ); + + PG_FREE_IF_COPY(cfg, 0); + PG_RETURN_DATUM(out); +} + +PG_FUNCTION_INFO_V1(headline_current); +Datum headline_current(PG_FUNCTION_ARGS); +Datum +headline_current(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(DirectFunctionCall4( + headline, + ObjectIdGetDatum(get_currcfg()), + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1), + (PG_NARGS() > 2) ? PG_GETARG_DATUM(2) : PointerGetDatum(NULL) + )); +} diff --git a/contrib/tsearch2/wparser.h b/contrib/tsearch2/wparser.h new file mode 100644 index 0000000..c3c4415 --- /dev/null +++ b/contrib/tsearch2/wparser.h @@ -0,0 +1,30 @@ +#ifndef __WPARSER_H__ +#define __WPARSER_H__ +#include "postgres.h" +#include "fmgr.h" + +typedef struct +{ + Oid prs_id; + FmgrInfo start_info; + FmgrInfo getlexeme_info; + FmgrInfo end_info; + FmgrInfo headline_info; + Oid lextype; + void *prs; +} WParserInfo; + +void init_prs(Oid id, WParserInfo * prs); +WParserInfo *findprs(Oid id); +Oid name2id_prs(text *name); +void reset_prs(void); + + +typedef struct +{ + int lexid; + char *alias; + char *descr; +} LexDescr; + +#endif diff --git a/contrib/tsearch2/wparser_def.c b/contrib/tsearch2/wparser_def.c new file mode 100644 index 0000000..f0f4cde --- /dev/null +++ b/contrib/tsearch2/wparser_def.c @@ -0,0 +1,357 @@ +/* + * default word parser + * Teodor Sigaev + */ +#include +#include +#include + +#include "postgres.h" +#include "utils/builtins.h" + +#include "dict.h" +#include "wparser.h" +#include "common.h" +#include "ts_cfg.h" +#include "wordparser/parser.h" +#include "wordparser/deflex.h" + +PG_FUNCTION_INFO_V1(prsd_lextype); +Datum prsd_lextype(PG_FUNCTION_ARGS); + +Datum +prsd_lextype(PG_FUNCTION_ARGS) +{ + LexDescr *descr = (LexDescr *) palloc(sizeof(LexDescr) * (LASTNUM + 1)); + int i; + + for (i = 1; i <= LASTNUM; i++) + { + descr[i - 1].lexid = i; + descr[i - 1].alias = pstrdup(tok_alias[i]); + descr[i - 1].descr = pstrdup(lex_descr[i]); + } + + descr[LASTNUM].lexid = 0; + + PG_RETURN_POINTER(descr); +} + +PG_FUNCTION_INFO_V1(prsd_start); +Datum prsd_start(PG_FUNCTION_ARGS); +Datum +prsd_start(PG_FUNCTION_ARGS) +{ + start_parse_str((char *) PG_GETARG_POINTER(0), PG_GETARG_INT32(1)); + PG_RETURN_POINTER(NULL); +} + +PG_FUNCTION_INFO_V1(prsd_getlexeme); +Datum prsd_getlexeme(PG_FUNCTION_ARGS); +Datum +prsd_getlexeme(PG_FUNCTION_ARGS) +{ + /* ParserState *p=(ParserState*)PG_GETARG_POINTER(0); */ + char **t = (char **) PG_GETARG_POINTER(1); + int *tlen = (int *) PG_GETARG_POINTER(2); + int type = tsearch2_yylex(); + + *t = token; + *tlen = tokenlen; + PG_RETURN_INT32(type); +} + +PG_FUNCTION_INFO_V1(prsd_end); +Datum prsd_end(PG_FUNCTION_ARGS); +Datum +prsd_end(PG_FUNCTION_ARGS) +{ + /* ParserState *p=(ParserState*)PG_GETARG_POINTER(0); */ + end_parse(); + PG_RETURN_VOID(); +} + +#define LEAVETOKEN(x) ( (x)==12 ) +#define COMPLEXTOKEN(x) ( (x)==5 || (x)==15 || (x)==16 || (x)==17 ) +#define ENDPUNCTOKEN(x) ( (x)==12 ) + + +#define IDIGNORE(x) ( (x)==13 || (x)==14 || (x)==12 || (x)==23 ) +#define HLIDIGNORE(x) ( (x)==5 || (x)==13 || (x)==15 || (x)==16 || (x)==17 ) +#define NONWORDTOKEN(x) ( (x)==12 || HLIDIGNORE(x) ) +#define NOENDTOKEN(x) ( NONWORDTOKEN(x) || (x)==7 || (x)==8 || (x)==20 || (x)==21 || (x)==22 || IDIGNORE(x) ) + +typedef struct +{ + HLWORD *words; + int len; +} hlCheck; + +static bool +checkcondition_HL(void *checkval, ITEM * val) +{ + int i; + + for (i = 0; i < ((hlCheck *) checkval)->len; i++) + { + if (((hlCheck *) checkval)->words[i].item == val) + return true; + } + return false; +} + + +static bool +hlCover(HLPRSTEXT * prs, QUERYTYPE * query, int *p, int *q) +{ + int i, + j; + ITEM *item = GETQUERY(query); + int pos = *p; + + *q = 0; + *p = 0x7fffffff; + + for (j = 0; j < query->size; j++) + { + if (item->type != VAL) + { + item++; + continue; + } + for (i = pos; i < prs->curwords; i++) + { + if (prs->words[i].item == item) + { + if (i > *q) + *q = i; + break; + } + } + item++; + } + + if (*q == 0) + return false; + + item = GETQUERY(query); + for (j = 0; j < query->size; j++) + { + if (item->type != VAL) + { + item++; + continue; + } + for (i = *q; i >= pos; i--) + { + if (prs->words[i].item == item) + { + if (i < *p) + *p = i; + break; + } + } + item++; + } + + if (*p <= *q) + { + hlCheck ch = {&(prs->words[*p]), *q - *p + 1}; + + if (TS_execute(GETQUERY(query), &ch, false, checkcondition_HL)) + return true; + else + { + (*p)++; + return hlCover(prs, query, p, q); + } + } + + return false; +} + +PG_FUNCTION_INFO_V1(prsd_headline); +Datum prsd_headline(PG_FUNCTION_ARGS); +Datum +prsd_headline(PG_FUNCTION_ARGS) +{ + HLPRSTEXT *prs = (HLPRSTEXT *) PG_GETARG_POINTER(0); + text *opt = (text *) PG_GETARG_POINTER(1); /* can't be toasted */ + QUERYTYPE *query = (QUERYTYPE *) PG_GETARG_POINTER(2); /* can't be toasted */ + + /* from opt + start and and tag */ + int min_words = 15; + int max_words = 35; + int shortword = 3; + + int p = 0, + q = 0; + int bestb = -1, + beste = -1; + int bestlen = -1; + int pose = 0, posb, + poslen, + curlen; + + int i; + + /* config */ + prs->startsel = NULL; + prs->stopsel = NULL; + if (opt) + { + Map *map, + *mptr; + + parse_cfgdict(opt, &map); + mptr = map; + + while (mptr && mptr->key) + { + if (strcasecmp(mptr->key, "MaxWords") == 0) + max_words = pg_atoi(mptr->value, 4, 1); + else if (strcasecmp(mptr->key, "MinWords") == 0) + min_words = pg_atoi(mptr->value, 4, 1); + else if (strcasecmp(mptr->key, "ShortWord") == 0) + shortword = pg_atoi(mptr->value, 4, 1); + else if (strcasecmp(mptr->key, "StartSel") == 0) + prs->startsel = pstrdup(mptr->value); + else if (strcasecmp(mptr->key, "StopSel") == 0) + prs->stopsel = pstrdup(mptr->value); + + pfree(mptr->key); + pfree(mptr->value); + + mptr++; + } + pfree(map); + + if (min_words >= max_words) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("MinWords should be less than MaxWords"))); + if (min_words <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("MinWords should be positive"))); + if (shortword < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("ShortWord should be >= 0"))); + } + + while (hlCover(prs, query, &p, &q)) + { + /* find cover len in words */ + curlen = 0; + poslen = 0; + for (i = p; i <= q && curlen < max_words; i++) + { + if (!NONWORDTOKEN(prs->words[i].type)) + curlen++; + if (prs->words[i].item && !prs->words[i].repeated) + poslen++; + pose = i; + } + + if (poslen < bestlen && !(NOENDTOKEN(prs->words[beste].type) || prs->words[beste].len <= shortword)) + { + /* best already finded, so try one more cover */ + p++; + continue; + } + + posb=p; + if (curlen < max_words) + { /* find good end */ + for (i = i - 1; i < prs->curwords && curlen < max_words; i++) + { + if (i != q) + { + if (!NONWORDTOKEN(prs->words[i].type)) + curlen++; + if (prs->words[i].item && !prs->words[i].repeated) + poslen++; + } + pose = i; + if (NOENDTOKEN(prs->words[i].type) || prs->words[i].len <= shortword) + continue; + if (curlen >= min_words) + break; + } + if ( curlen < min_words && i>=prs->curwords ) { /* got end of text and our cover is shoter than min_words */ + for(i=p; i>= 0; i--) { + if (!NONWORDTOKEN(prs->words[i].type)) + curlen++; + if (prs->words[i].item && !prs->words[i].repeated) + poslen++; + if (NOENDTOKEN(prs->words[i].type) || prs->words[i].len <= shortword) + continue; + if (curlen >= min_words) + break; + } + posb=(i>=0) ? i : 0; + } + } + else + { /* shorter cover :((( */ + for (; curlen > min_words; i--) + { + if (!NONWORDTOKEN(prs->words[i].type)) + curlen--; + if (prs->words[i].item && !prs->words[i].repeated) + poslen--; + pose = i; + if (NOENDTOKEN(prs->words[i].type) || prs->words[i].len <= shortword) + continue; + break; + } + } + + if (bestlen < 0 || (poslen > bestlen && !(NOENDTOKEN(prs->words[pose].type) || prs->words[pose].len <= shortword)) || + (bestlen >= 0 && !(NOENDTOKEN(prs->words[pose].type) || prs->words[pose].len <= shortword) && + (NOENDTOKEN(prs->words[beste].type) || prs->words[beste].len <= shortword))) + { + bestb = posb; + beste = pose; + bestlen = poslen; + } + + p++; + } + + if (bestlen < 0) + { + curlen = 0; + poslen = 0; + for (i = 0; i < prs->curwords && curlen < min_words; i++) + { + if (!NONWORDTOKEN(prs->words[i].type)) + curlen++; + pose = i; + } + bestb = 0; + beste = pose; + } + + for (i = bestb; i <= beste; i++) + { + if (prs->words[i].item) + prs->words[i].selected = 1; + if (prs->words[i].repeated) + prs->words[i].skip = 1; + if (HLIDIGNORE(prs->words[i].type)) + prs->words[i].replace = 1; + + prs->words[i].in = 1; + } + + if (!prs->startsel) + prs->startsel = pstrdup(""); + if (!prs->stopsel) + prs->stopsel = pstrdup(""); + prs->startsellen = strlen(prs->startsel); + prs->stopsellen = strlen(prs->stopsel); + + PG_RETURN_POINTER(prs); +} diff --git a/doc/FAQ_AIX b/doc/FAQ_AIX index 16b70f1..744154d 100644 --- a/doc/FAQ_AIX +++ b/doc/FAQ_AIX @@ -1,5 +1,5 @@ From: Zeugswetter Andreas -$Date: 2002/11/12 20:02:32 $ +$Date$ On AIX 4.3.2 PostgreSQL compiled with the native IBM compiler xlc (vac.C 5.0.1) passes all regression tests. Other versions of OS and diff --git a/doc/FAQ_HPUX b/doc/FAQ_HPUX index 503744f..3d79585 100644 --- a/doc/FAQ_HPUX +++ b/doc/FAQ_HPUX @@ -3,7 +3,7 @@ Frequently Asked Questions (FAQ) for PostgreSQL 7.3 HP-UX Specific TO BE READ IN CONJUNCTION WITH THE NORMAL FAQ ======================================================= -last updated: $Date: 2002/11/11 20:04:05 $ +last updated: $Date$ current maintainer: Tom Lane (tgl@sss.pgh.pa.us) original author: Tom Lane (tgl@sss.pgh.pa.us) diff --git a/doc/FAQ_IRIX b/doc/FAQ_IRIX index ad2fef5..b27b7b0 100644 --- a/doc/FAQ_IRIX +++ b/doc/FAQ_IRIX @@ -3,7 +3,7 @@ Frequently Asked Questions (FAQ) for PostgreSQL IRIX Specific TO BE READ IN CONJUNCTION WITH THE NORMAL FAQ ======================================================= -last updated: $Date: 2002/11/11 20:04:05 $ +last updated: $Date$ current maintainer: Luis Amigo (lamigo@atc.unican.es) original author: Luis Amigo (lamigo@atc.unican.es) diff --git a/doc/FAQ_MSWIN b/doc/FAQ_MSWIN index c4754df..8597f4c 100644 --- a/doc/FAQ_MSWIN +++ b/doc/FAQ_MSWIN @@ -1,6 +1,6 @@ How to install PostgreSQL on Windows ==================================== -$Date: 2002/11/11 20:04:05 $ +$Date$ 1. Install the latest Cygwin package, available at http://cygwin.com/. The Cygwin package provides a UNIX-like API on top of the Win32 diff --git a/doc/FAQ_QNX4 b/doc/FAQ_QNX4 index 19ad033..3a1741e 100644 --- a/doc/FAQ_QNX4 +++ b/doc/FAQ_QNX4 @@ -1,6 +1,6 @@ PostgreSQL on QNX 4 -------------------- -last updated: $Date: 2002/07/09 04:47:07 $ +last updated: $Date$ current maintainer: Bernd Tegge (tegge@repas-aeg.de) original author: Andreas Kardos (kardos@repas-aeg.de) diff --git a/doc/FAQ_SCO b/doc/FAQ_SCO index cd299c0..805caf1 100644 --- a/doc/FAQ_SCO +++ b/doc/FAQ_SCO @@ -3,7 +3,7 @@ Frequently Asked Questions (FAQ) for PostgreSQL 7.3 SCO UnixWare and OpenServer specific to be read in conjunction with the installation instructions ============================================================ -last updated: $Date: 2002/11/08 16:49:15 $ +last updated: $Date$ current maintainer: Billy G. Allie (Bill.Allie@mug.org) original author: Andrew Merrill (andrew@compclass.com) diff --git a/doc/FAQ_Solaris b/doc/FAQ_Solaris index 9c769d5..a2d469a 100644 --- a/doc/FAQ_Solaris +++ b/doc/FAQ_Solaris @@ -3,7 +3,7 @@ Frequently Asked Questions (FAQ) for PostgreSQL Sun Solaris specific to be read in conjunction with the installation instructions ============================================================ -last updated: $Date: 2002/11/11 20:04:05 $ +last updated: $Date$ current maintainer: Peter Eisentraut diff --git a/doc/TODO.detail/inheritance b/doc/TODO.detail/inheritance index b3112d6..aebf4e8 100644 --- a/doc/TODO.detail/inheritance +++ b/doc/TODO.detail/inheritance @@ -520,7 +520,7 @@ From pgsql-general-owner+M2136@hub.org Sat Jun 3 23:31:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA28683 for ; Sat, 3 Jun 2000 22:31:01 -0400 (EDT) -Received: from news.tht.net (news.hub.org [216.126.91.242]) by renoir.op.net (o1/$Revision: 1.2 $) with ESMTP id WAA20977 for ; Sat, 3 Jun 2000 22:05:07 -0400 (EDT) +Received: from news.tht.net (news.hub.org [216.126.91.242]) by renoir.op.net (o1/$Revision$) with ESMTP id WAA20977 for ; Sat, 3 Jun 2000 22:05:07 -0400 (EDT) Received: from hub.org (majordom@hub.org [216.126.84.1]) by news.tht.net (8.9.3/8.9.3) with ESMTP id VAD35811; Sat, 3 Jun 2000 21:54:36 -0400 (EDT) diff --git a/doc/TODO.detail/optimizer b/doc/TODO.detail/optimizer index fd6324f..9095b0f 100644 --- a/doc/TODO.detail/optimizer +++ b/doc/TODO.detail/optimizer @@ -1059,7 +1059,7 @@ From owner-pgsql-hackers@hub.org Thu Jan 20 18:45:32 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA00672 for ; Thu, 20 Jan 2000 19:45:30 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.20 $) with ESMTP id TAA01989 for ; Thu, 20 Jan 2000 19:39:15 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA01989 for ; Thu, 20 Jan 2000 19:39:15 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id TAA00957; Thu, 20 Jan 2000 19:35:19 -0500 (EST) diff --git a/doc/TODO.detail/performance b/doc/TODO.detail/performance index 2fbfabe..d1baf33 100644 --- a/doc/TODO.detail/performance +++ b/doc/TODO.detail/performance @@ -345,7 +345,7 @@ From owner-pgsql-hackers@hub.org Tue Oct 19 10:31:10 1999 Received: from renoir.op.net (root@renoir.op.net [209.152.193.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id KAA29087 for ; Tue, 19 Oct 1999 10:31:08 -0400 (EDT) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.16 $) with ESMTP id KAA27535 for ; Tue, 19 Oct 1999 10:19:47 -0400 (EDT) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id KAA27535 for ; Tue, 19 Oct 1999 10:19:47 -0400 (EDT) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id KAA30328; Tue, 19 Oct 1999 10:12:10 -0400 (EDT) @@ -454,7 +454,7 @@ From owner-pgsql-hackers@hub.org Tue Oct 19 21:25:30 1999 Received: from renoir.op.net (root@renoir.op.net [209.152.193.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id VAA28130 for ; Tue, 19 Oct 1999 21:25:26 -0400 (EDT) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.16 $) with ESMTP id VAA10512 for ; Tue, 19 Oct 1999 21:15:28 -0400 (EDT) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA10512 for ; Tue, 19 Oct 1999 21:15:28 -0400 (EDT) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id VAA50745; Tue, 19 Oct 1999 21:07:23 -0400 (EDT) @@ -1006,7 +1006,7 @@ From pgsql-general-owner+M2497@hub.org Fri Jun 16 18:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id RAA04165 for ; Fri, 16 Jun 2000 17:31:01 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.16 $) with ESMTP id RAA13110 for ; Fri, 16 Jun 2000 17:20:12 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id RAA13110 for ; Fri, 16 Jun 2000 17:20:12 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5GLDaM14477; Fri, 16 Jun 2000 17:13:36 -0400 (EDT) diff --git a/doc/TODO.detail/replication b/doc/TODO.detail/replication index d4bf4b1..d75c879 100644 --- a/doc/TODO.detail/replication +++ b/doc/TODO.detail/replication @@ -43,7 +43,7 @@ From owner-pgsql-hackers@hub.org Fri Dec 24 10:01:18 1999 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA11295 for ; Fri, 24 Dec 1999 11:01:17 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id KAA20310 for ; Fri, 24 Dec 1999 10:39:18 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id KAA20310 for ; Fri, 24 Dec 1999 10:39:18 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id KAA61760; Fri, 24 Dec 1999 10:31:13 -0500 (EST) @@ -129,7 +129,7 @@ From owner-pgsql-hackers@hub.org Fri Dec 24 18:31:03 1999 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA26244 for ; Fri, 24 Dec 1999 19:31:02 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id TAA12730 for ; Fri, 24 Dec 1999 19:30:05 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA12730 for ; Fri, 24 Dec 1999 19:30:05 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id TAA57851; Fri, 24 Dec 1999 19:23:31 -0500 (EST) @@ -212,7 +212,7 @@ From owner-pgsql-hackers@hub.org Fri Dec 24 21:31:10 1999 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA02578 for ; Fri, 24 Dec 1999 22:31:09 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id WAA16641 for ; Fri, 24 Dec 1999 22:18:56 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id WAA16641 for ; Fri, 24 Dec 1999 22:18:56 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id WAA89135; Fri, 24 Dec 1999 22:11:12 -0500 (EST) @@ -486,7 +486,7 @@ From owner-pgsql-hackers@hub.org Sun Dec 26 08:31:09 1999 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id JAA17976 for ; Sun, 26 Dec 1999 09:31:07 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id JAA23337 for ; Sun, 26 Dec 1999 09:28:36 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id JAA23337 for ; Sun, 26 Dec 1999 09:28:36 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id JAA90738; Sun, 26 Dec 1999 09:21:58 -0500 (EST) @@ -909,7 +909,7 @@ From owner-pgsql-hackers@hub.org Thu Dec 30 08:01:09 1999 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id JAA10317 for ; Thu, 30 Dec 1999 09:01:08 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id IAA02365 for ; Thu, 30 Dec 1999 08:37:10 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA02365 for ; Thu, 30 Dec 1999 08:37:10 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id IAA87902; Thu, 30 Dec 1999 08:34:22 -0500 (EST) @@ -1006,7 +1006,7 @@ From owner-pgsql-patches@hub.org Sun Jan 2 23:01:38 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA16274 for ; Mon, 3 Jan 2000 00:01:28 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id XAA02655 for ; Sun, 2 Jan 2000 23:45:55 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA02655 for ; Sun, 2 Jan 2000 23:45:55 -0500 (EST) Received: from hub.org (hub.org [216.126.84.1]) by hub.org (8.9.3/8.9.3) with ESMTP id XAA13828; Sun, 2 Jan 2000 23:40:47 -0500 (EST) @@ -1424,7 +1424,7 @@ From owner-pgsql-hackers@hub.org Tue Jan 4 10:31:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA17522 for ; Tue, 4 Jan 2000 11:31:00 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.10 $) with ESMTP id LAA01541 for ; Tue, 4 Jan 2000 11:27:30 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA01541 for ; Tue, 4 Jan 2000 11:27:30 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id LAA09992; Tue, 4 Jan 2000 11:18:07 -0500 (EST) diff --git a/doc/TODO.detail/tablespaces b/doc/TODO.detail/tablespaces index 4c1351a..303fdcf 100644 --- a/doc/TODO.detail/tablespaces +++ b/doc/TODO.detail/tablespaces @@ -2,7 +2,7 @@ From pgsql-hackers-owner+M174@hub.org Sun Mar 12 22:31:11 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id XAA25886 for ; Sun, 12 Mar 2000 23:31:10 -0500 (EST) -Received: from news.tht.net (news.hub.org [216.126.91.242]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA04589 for ; Sun, 12 Mar 2000 23:19:33 -0500 (EST) +Received: from news.tht.net (news.hub.org [216.126.91.242]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA04589 for ; Sun, 12 Mar 2000 23:19:33 -0500 (EST) Received: from hub.org (hub.org [216.126.84.1]) by news.tht.net (8.9.3/8.9.3) with SMTP id XAA42854; Sun, 12 Mar 2000 23:05:05 -0500 (EST) @@ -480,7 +480,7 @@ From Inoue@tpf.co.jp Wed Mar 15 02:00:58 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA17887 for ; Wed, 15 Mar 2000 03:00:57 -0500 (EST) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id CAA02974 for ; Wed, 15 Mar 2000 02:54:44 -0500 (EST) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id CAA02974 for ; Wed, 15 Mar 2000 02:54:44 -0500 (EST) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id QAA00734; Wed, 15 Mar 2000 16:53:56 +0900 @@ -743,7 +743,7 @@ From JanWieck@t-online.de Wed Jun 14 19:01:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA21372 for ; Wed, 14 Jun 2000 19:00:59 -0400 (EDT) -Received: from mailout02.sul.t-online.com (mailout02.sul.t-online.com [194.25.134.17]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id SAA01930 for ; Wed, 14 Jun 2000 18:51:11 -0400 (EDT) +Received: from mailout02.sul.t-online.com (mailout02.sul.t-online.com [194.25.134.17]) by renoir.op.net (o1/$Revision$) with ESMTP id SAA01930 for ; Wed, 14 Jun 2000 18:51:11 -0400 (EDT) Received: from fwd01.sul.t-online.de by mailout02.sul.t-online.com with smtp id 132Lz6-0004ec-01; Thu, 15 Jun 2000 00:50:08 +0200 @@ -1336,7 +1336,7 @@ From pgsql-hackers-owner+M3400@hub.org Thu Jun 15 03:31:16 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA24604 for ; Thu, 15 Jun 2000 03:31:15 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA01191 for ; Thu, 15 Jun 2000 03:15:28 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA01191 for ; Thu, 15 Jun 2000 03:15:28 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5F7CP835301; Thu, 15 Jun 2000 03:12:25 -0400 (EDT) @@ -1396,7 +1396,7 @@ From tgl@sss.pgh.pa.us Thu Jun 15 03:31:11 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA24592 for ; Thu, 15 Jun 2000 03:31:10 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA01213 for ; Thu, 15 Jun 2000 03:15:46 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA01213 for ; Thu, 15 Jun 2000 03:15:46 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id DAA18833; Thu, 15 Jun 2000 03:14:30 -0400 (EDT) @@ -1434,7 +1434,7 @@ From pgsql-hackers-owner+M3401@hub.org Thu Jun 15 03:31:15 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA24601 for ; Thu, 15 Jun 2000 03:31:14 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA01428 for ; Thu, 15 Jun 2000 03:19:39 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA01428 for ; Thu, 15 Jun 2000 03:19:39 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5F7GP843802; Thu, 15 Jun 2000 03:16:25 -0400 (EDT) @@ -1539,7 +1539,7 @@ From ZeugswetterA@wien.spardat.at Thu Jun 15 04:31:04 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id EAA25144 for ; Thu, 15 Jun 2000 04:31:03 -0400 (EDT) -Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id EAA03225 for ; Thu, 15 Jun 2000 04:05:41 -0400 (EDT) +Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision$) with ESMTP id EAA03225 for ; Thu, 15 Jun 2000 04:05:41 -0400 (EDT) Received: from sdexcgtw01.f000.d0188.sd.spardat.at (sdgtw.sd.spardat.at [172.18.1.16]) by gandalf.it-austria.net (xxx/xxx) with ESMTP id KAA100894; Thu, 15 Jun 2000 10:04:52 +0200 @@ -1604,7 +1604,7 @@ From pgsql-hackers-owner+M3405@hub.org Thu Jun 15 04:31:09 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id EAA25151 for ; Thu, 15 Jun 2000 04:31:07 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id EAA04151 for ; Thu, 15 Jun 2000 04:30:23 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id EAA04151 for ; Thu, 15 Jun 2000 04:30:23 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5F8RI883087; Thu, 15 Jun 2000 04:27:18 -0400 (EDT) @@ -1676,7 +1676,7 @@ From pgsql-hackers-owner+M3407@hub.org Thu Jun 15 05:01:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id FAA25462 for ; Thu, 15 Jun 2000 05:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id EAA04667 for ; Thu, 15 Jun 2000 04:45:51 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id EAA04667 for ; Thu, 15 Jun 2000 04:45:51 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5F8gr817124; Thu, 15 Jun 2000 04:42:53 -0400 (EDT) @@ -1714,7 +1714,7 @@ From scrappy@hub.org Thu Jun 15 08:30:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id IAA03846 for ; Thu, 15 Jun 2000 08:30:58 -0400 (EDT) -Received: from thelab.hub.org (nat193.152.mpoweredpc.net [142.177.193.152]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id IAA14167 for ; Thu, 15 Jun 2000 08:16:58 -0400 (EDT) +Received: from thelab.hub.org (nat193.152.mpoweredpc.net [142.177.193.152]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA14167 for ; Thu, 15 Jun 2000 08:16:58 -0400 (EDT) Received: from localhost (scrappy@localhost) by thelab.hub.org (8.9.3/8.9.3) with ESMTP id JAA74856; Thu, 15 Jun 2000 09:14:29 -0300 (ADT) @@ -1769,7 +1769,7 @@ From pgsql-hackers-owner+M3412@hub.org Thu Jun 15 08:30:55 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id IAA03842 for ; Thu, 15 Jun 2000 08:30:54 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id IAA15241 for ; Thu, 15 Jun 2000 08:31:29 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA15241 for ; Thu, 15 Jun 2000 08:31:29 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5FCSM877572; Thu, 15 Jun 2000 08:28:22 -0400 (EDT) @@ -1932,7 +1932,7 @@ From dhogaza@pacifier.com Thu Jun 15 09:31:05 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id JAA04418 for ; Thu, 15 Jun 2000 09:31:04 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id JAA20080 for ; Thu, 15 Jun 2000 09:22:36 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id JAA20080 for ; Thu, 15 Jun 2000 09:22:36 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id GAA05755; Thu, 15 Jun 2000 06:21:54 -0700 (PDT) @@ -1983,7 +1983,7 @@ From pgsql-hackers-owner+M3440@hub.org Thu Jun 15 14:46:22 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA04607 for ; Thu, 15 Jun 2000 14:46:21 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA12695 for ; Thu, 15 Jun 2000 12:48:58 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA12695 for ; Thu, 15 Jun 2000 12:48:58 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5FGjXI40370; Thu, 15 Jun 2000 12:45:33 -0400 (EDT) @@ -2167,7 +2167,7 @@ From pgsql-hackers-owner+M3448@hub.org Thu Jun 15 19:01:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA00764 for ; Thu, 15 Jun 2000 19:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id SAA17328 for ; Thu, 15 Jun 2000 18:57:32 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id SAA17328 for ; Thu, 15 Jun 2000 18:57:32 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5FMsMI97744; Thu, 15 Jun 2000 18:54:22 -0400 (EDT) @@ -2233,7 +2233,7 @@ From pgsql-hackers-owner+M3451@hub.org Thu Jun 15 20:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id UAA01651 for ; Thu, 15 Jun 2000 20:00:59 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA20985 for ; Thu, 15 Jun 2000 19:57:49 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA20985 for ; Thu, 15 Jun 2000 19:57:49 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5FNsgI25402; Thu, 15 Jun 2000 19:54:42 -0400 (EDT) @@ -2309,7 +2309,7 @@ From tgl@sss.pgh.pa.us Thu Jun 15 20:00:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id UAA01647 for ; Thu, 15 Jun 2000 20:00:58 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA21034 for ; Thu, 15 Jun 2000 19:58:30 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA21034 for ; Thu, 15 Jun 2000 19:58:30 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id TAA02283; Thu, 15 Jun 2000 19:57:05 -0400 (EDT) @@ -2350,7 +2350,7 @@ From pgsql-hackers-owner+M3453@hub.org Thu Jun 15 21:01:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id VAA02731 for ; Thu, 15 Jun 2000 21:01:01 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA23469 for ; Thu, 15 Jun 2000 20:36:36 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA23469 for ; Thu, 15 Jun 2000 20:36:36 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5G0WDI97134; Thu, 15 Jun 2000 20:32:13 -0400 (EDT) @@ -2426,7 +2426,7 @@ From tgl@sss.pgh.pa.us Thu Jun 15 22:01:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA03637 for ; Thu, 15 Jun 2000 22:01:01 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id VAA28521 for ; Thu, 15 Jun 2000 21:58:46 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA28521 for ; Thu, 15 Jun 2000 21:58:46 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id VAA02730; Thu, 15 Jun 2000 21:57:27 -0400 (EDT) @@ -2629,7 +2629,7 @@ From Inoue@tpf.co.jp Thu Jun 15 23:31:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id XAA06634; Thu, 15 Jun 2000 23:30:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA03227; Thu, 15 Jun 2000 23:18:54 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA03227; Thu, 15 Jun 2000 23:18:54 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id MAA07544; Fri, 16 Jun 2000 12:18:06 +0900 @@ -2700,7 +2700,7 @@ From pgsql-hackers-owner+M3465@hub.org Fri Jun 16 00:01:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA06924 for ; Fri, 16 Jun 2000 00:01:00 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA05470 for ; Thu, 15 Jun 2000 23:59:46 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA05470 for ; Thu, 15 Jun 2000 23:59:46 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5G3uaI10809; Thu, 15 Jun 2000 23:56:36 -0400 (EDT) @@ -2761,7 +2761,7 @@ From Inoue@tpf.co.jp Fri Jun 16 02:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA08093 for ; Fri, 16 Jun 2000 02:00:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA10174 for ; Fri, 16 Jun 2000 01:34:44 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA10174 for ; Fri, 16 Jun 2000 01:34:44 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id OAA07656; Fri, 16 Jun 2000 14:33:12 +0900 @@ -2847,7 +2847,7 @@ From pgsql-hackers-owner+M3469@hub.org Fri Jun 16 02:01:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA08109 for ; Fri, 16 Jun 2000 02:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA11218 for ; Fri, 16 Jun 2000 01:57:33 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA11218 for ; Fri, 16 Jun 2000 01:57:33 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5G5tLI49492; Fri, 16 Jun 2000 01:55:21 -0400 (EDT) @@ -2919,7 +2919,7 @@ From pgsql-hackers-owner+M3471@hub.org Fri Jun 16 03:31:05 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA12816 for ; Fri, 16 Jun 2000 03:31:04 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA14405 for ; Fri, 16 Jun 2000 03:03:38 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA14405 for ; Fri, 16 Jun 2000 03:03:38 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5G71YI83633; Fri, 16 Jun 2000 03:01:34 -0400 (EDT) @@ -3023,7 +3023,7 @@ From pgsql-hackers-owner+M3473@hub.org Fri Jun 16 04:01:12 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id EAA13087 for ; Fri, 16 Jun 2000 04:01:11 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA16002 for ; Fri, 16 Jun 2000 03:37:24 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA16002 for ; Fri, 16 Jun 2000 03:37:24 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5G7ZZI51521; Fri, 16 Jun 2000 03:35:35 -0400 (EDT) @@ -3078,7 +3078,7 @@ From JanWieck@t-online.de Fri Jun 16 11:01:06 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA28913 for ; Fri, 16 Jun 2000 11:01:05 -0400 (EDT) -Received: from mailout05.sul.t-online.com (mailout05.sul.t-online.com [194.25.134.82]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id KAA01818 for ; Fri, 16 Jun 2000 10:46:42 -0400 (EDT) +Received: from mailout05.sul.t-online.com (mailout05.sul.t-online.com [194.25.134.82]) by renoir.op.net (o1/$Revision$) with ESMTP id KAA01818 for ; Fri, 16 Jun 2000 10:46:42 -0400 (EDT) Received: from fwd06.sul.t-online.de by mailout05.sul.t-online.com with smtp id 132xN9-0006ze-03; Fri, 16 Jun 2000 16:45:27 +0200 @@ -3216,7 +3216,7 @@ From tgl@sss.pgh.pa.us Fri Jun 16 12:01:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA29853 for ; Fri, 16 Jun 2000 12:01:02 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA08255 for ; Fri, 16 Jun 2000 11:48:10 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA08255 for ; Fri, 16 Jun 2000 11:48:10 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id LAA07461; Fri, 16 Jun 2000 11:46:41 -0400 (EDT) @@ -3299,7 +3299,7 @@ From lockhart@alumni.caltech.edu Fri Jun 16 12:31:50 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA00649 for ; Fri, 16 Jun 2000 12:31:49 -0400 (EDT) -Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA13118 for ; Fri, 16 Jun 2000 12:31:52 -0400 (EDT) +Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA13118 for ; Fri, 16 Jun 2000 12:31:52 -0400 (EDT) Received: from golem.jpl.nasa.gov (hectic-1 [128.149.68.203]) by huey.jpl.nasa.gov (8.8.8+Sun/8.8.8) with ESMTP id JAA15007; Fri, 16 Jun 2000 09:27:18 -0700 (PDT) @@ -3358,7 +3358,7 @@ From scrappy@hub.org Fri Jun 16 13:01:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id NAA01191; Fri, 16 Jun 2000 13:01:01 -0400 (EDT) -Received: from thelab.hub.org (nat193.152.mpoweredpc.net [142.177.193.152]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA15282; Fri, 16 Jun 2000 12:53:23 -0400 (EDT) +Received: from thelab.hub.org (nat193.152.mpoweredpc.net [142.177.193.152]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA15282; Fri, 16 Jun 2000 12:53:23 -0400 (EDT) Received: from localhost (scrappy@localhost) by thelab.hub.org (8.9.3/8.9.3) with ESMTP id NAA28326; Fri, 16 Jun 2000 13:50:37 -0300 (ADT) @@ -3418,7 +3418,7 @@ From tgl@sss.pgh.pa.us Fri Jun 16 13:01:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id NAA01188 for ; Fri, 16 Jun 2000 13:01:01 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA15530 for ; Fri, 16 Jun 2000 12:55:38 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA15530 for ; Fri, 16 Jun 2000 12:55:38 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id MAA07750; Fri, 16 Jun 2000 12:54:00 -0400 (EDT) @@ -3459,7 +3459,7 @@ From dhogaza@pacifier.com Fri Jun 16 14:55:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA02086 for ; Fri, 16 Jun 2000 14:54:59 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id OAA26430 for ; Fri, 16 Jun 2000 14:40:00 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id OAA26430 for ; Fri, 16 Jun 2000 14:40:00 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id LAA08661; Fri, 16 Jun 2000 11:38:36 -0700 (PDT) @@ -3565,7 +3565,7 @@ From pgsql-hackers-owner+M3500@hub.org Fri Jun 16 14:55:10 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA02107 for ; Fri, 16 Jun 2000 14:55:09 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id OAA26943 for ; Fri, 16 Jun 2000 14:44:12 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id OAA26943 for ; Fri, 16 Jun 2000 14:44:12 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5GIelM05972; Fri, 16 Jun 2000 14:40:47 -0400 (EDT) @@ -3695,7 +3695,7 @@ From reedstrm@rice.edu Fri Jun 16 16:51:50 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id QAA03689 for ; Fri, 16 Jun 2000 16:51:49 -0400 (EDT) -Received: from wallace.ece.rice.edu (wallace.ece.rice.edu [128.42.12.154]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id PAA03409 for ; Fri, 16 Jun 2000 15:48:40 -0400 (EDT) +Received: from wallace.ece.rice.edu (wallace.ece.rice.edu [128.42.12.154]) by renoir.op.net (o1/$Revision$) with ESMTP id PAA03409 for ; Fri, 16 Jun 2000 15:48:40 -0400 (EDT) Received: by rice.edu via sendmail from stdin id (Debian Smail3.2.0.102) @@ -3808,7 +3808,7 @@ From dhogaza@pacifier.com Fri Jun 16 16:51:51 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id QAA03692 for ; Fri, 16 Jun 2000 16:51:50 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id PAA02911 for ; Fri, 16 Jun 2000 15:43:13 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id PAA02911 for ; Fri, 16 Jun 2000 15:43:13 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id MAA11003; Fri, 16 Jun 2000 12:41:50 -0700 (PDT) @@ -3874,7 +3874,7 @@ From pgsql-hackers-owner+M3512@hub.org Fri Jun 16 17:31:04 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id RAA04168 for ; Fri, 16 Jun 2000 17:31:03 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id RAA12122 for ; Fri, 16 Jun 2000 17:09:28 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id RAA12122 for ; Fri, 16 Jun 2000 17:09:28 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5GL7WM02231; Fri, 16 Jun 2000 17:07:32 -0400 (EDT) @@ -4003,7 +4003,7 @@ From Inoue@tpf.co.jp Fri Jun 16 19:31:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA05334 for ; Fri, 16 Jun 2000 19:30:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA19834 for ; Fri, 16 Jun 2000 19:09:59 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA19834 for ; Fri, 16 Jun 2000 19:09:59 -0400 (EDT) Received: from mcadnote1 (ppm122.noc.fukui.nsk.ne.jp [210.161.188.41]) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id IAA08210; Sat, 17 Jun 2000 08:08:15 +0900 @@ -4061,7 +4061,7 @@ From tgl@sss.pgh.pa.us Fri Jun 16 19:31:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id TAA05337 for ; Fri, 16 Jun 2000 19:31:00 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA20335 for ; Fri, 16 Jun 2000 19:18:26 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA20335 for ; Fri, 16 Jun 2000 19:18:26 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id TAA09274; Fri, 16 Jun 2000 19:16:37 -0400 (EDT) @@ -4174,7 +4174,7 @@ From chris@bitmead.com Fri Jun 16 21:01:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id VAA07578; Fri, 16 Jun 2000 21:01:00 -0400 (EDT) -Received: from tech.com.au (IDENT:root@techpt.lnk.telstra.net [139.130.75.122]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA24724; Fri, 16 Jun 2000 20:39:30 -0400 (EDT) +Received: from tech.com.au (IDENT:root@techpt.lnk.telstra.net [139.130.75.122]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA24724; Fri, 16 Jun 2000 20:39:30 -0400 (EDT) Received: from bitmead.com (IDENT:chris@tardis [203.41.180.243]) by tech.com.au (8.9.3/8.9.3) with ESMTP id KAA21388; Sat, 17 Jun 2000 10:39:21 +1000 @@ -4208,7 +4208,7 @@ From Inoue@tpf.co.jp Sat Jun 17 06:00:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id GAA22177; Sat, 17 Jun 2000 06:00:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id FAA21759; Sat, 17 Jun 2000 05:36:27 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id FAA21759; Sat, 17 Jun 2000 05:36:27 -0400 (EDT) Received: from mcadnote1 (ppm130.noc.fukui.nsk.ne.jp [210.161.188.49]) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id SAA08383; Sat, 17 Jun 2000 18:35:36 +0900 @@ -4260,7 +4260,7 @@ From tgl@sss.pgh.pa.us Sat Jun 17 12:31:08 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA02794; Sat, 17 Jun 2000 12:31:07 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA07194; Sat, 17 Jun 2000 12:12:53 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA07194; Sat, 17 Jun 2000 12:12:53 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id MAA18824; Sat, 17 Jun 2000 12:11:18 -0400 (EDT) @@ -4296,7 +4296,7 @@ From tgl@sss.pgh.pa.us Sun Jun 18 12:30:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA06514 for ; Sun, 18 Jun 2000 12:30:58 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA04979 for ; Sun, 18 Jun 2000 12:07:44 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA04979 for ; Sun, 18 Jun 2000 12:07:44 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id MAA12163; Sun, 18 Jun 2000 12:06:29 -0400 (EDT) @@ -4365,7 +4365,7 @@ From dhogaza@pacifier.com Sun Jun 18 20:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id UAA19951 for ; Sun, 18 Jun 2000 20:00:59 -0400 (EDT) -Received: from smtp.pacifier.com (asteroid.pacifier.com [199.2.117.154]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA24345 for ; Sun, 18 Jun 2000 19:50:06 -0400 (EDT) +Received: from smtp.pacifier.com (asteroid.pacifier.com [199.2.117.154]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA24345 for ; Sun, 18 Jun 2000 19:50:06 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id QAA05302; Sun, 18 Jun 2000 16:49:27 -0700 (PDT) @@ -4414,7 +4414,7 @@ From pgsql-hackers-owner+M3571@hub.org Sun Jun 18 23:28:13 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id XAA23880 for ; Sun, 18 Jun 2000 23:28:12 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA04627 for ; Sun, 18 Jun 2000 23:24:37 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA04627 for ; Sun, 18 Jun 2000 23:24:37 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5J3GQM78526; Sun, 18 Jun 2000 23:16:26 -0400 (EDT) @@ -4462,7 +4462,7 @@ From dhogaza@pacifier.com Mon Jun 19 00:31:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA01941 for ; Mon, 19 Jun 2000 00:31:00 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA06881 for ; Mon, 19 Jun 2000 00:11:39 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA06881 for ; Mon, 19 Jun 2000 00:11:39 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id VAA29138; Sun, 18 Jun 2000 21:11:01 -0700 (PDT) @@ -4505,7 +4505,7 @@ From pgsql-hackers-owner+M3573@hub.org Mon Jun 19 01:31:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA01981 for ; Mon, 19 Jun 2000 01:31:01 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA09569 for ; Mon, 19 Jun 2000 01:13:53 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA09569 for ; Mon, 19 Jun 2000 01:13:53 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5J4T3M86960; Mon, 19 Jun 2000 00:29:04 -0400 (EDT) @@ -4552,7 +4552,7 @@ From tgl@sss.pgh.pa.us Mon Jun 19 00:30:58 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA01934 for ; Mon, 19 Jun 2000 00:30:58 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA07814 for ; Mon, 19 Jun 2000 00:29:36 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA07814 for ; Mon, 19 Jun 2000 00:29:36 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id AAA09535; Mon, 19 Jun 2000 00:28:14 -0400 (EDT) @@ -4588,7 +4588,7 @@ From pgsql-hackers-owner+M3574@hub.org Mon Jun 19 01:31:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA01977 for ; Mon, 19 Jun 2000 01:31:00 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA09374 for ; Mon, 19 Jun 2000 01:07:50 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA09374 for ; Mon, 19 Jun 2000 01:07:50 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5J4VkM95901; Mon, 19 Jun 2000 00:31:46 -0400 (EDT) @@ -4633,7 +4633,7 @@ From dhogaza@pacifier.com Mon Jun 19 00:58:39 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA00799 for ; Mon, 19 Jun 2000 00:58:38 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA08143 for ; Mon, 19 Jun 2000 00:37:39 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA08143 for ; Mon, 19 Jun 2000 00:37:39 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id VAA00259; Sun, 18 Jun 2000 21:36:25 -0700 (PDT) @@ -4692,7 +4692,7 @@ From Inoue@tpf.co.jp Mon Jun 19 12:31:17 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA29988 for ; Mon, 19 Jun 2000 12:31:16 -0400 (EDT) -Received: from sd.tpf.co.jp (mail.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA21005 for ; Mon, 19 Jun 2000 12:15:22 -0400 (EDT) +Received: from sd.tpf.co.jp (mail.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA21005 for ; Mon, 19 Jun 2000 12:15:22 -0400 (EDT) Received: from mcadnote1 (ppm127.noc.fukui.nsk.ne.jp [210.161.188.46]) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id BAA09828; Tue, 20 Jun 2000 01:14:19 +0900 @@ -4747,7 +4747,7 @@ From Inoue@tpf.co.jp Tue Jun 20 02:01:04 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA24419 for ; Tue, 20 Jun 2000 02:00:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA26090 for ; Tue, 20 Jun 2000 01:51:00 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA26090 for ; Tue, 20 Jun 2000 01:51:00 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id OAA10171; Tue, 20 Jun 2000 14:50:03 +0900 @@ -4821,7 +4821,7 @@ From tgl@sss.pgh.pa.us Tue Jun 20 10:51:32 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id KAA15181 for ; Tue, 20 Jun 2000 10:51:31 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id KAA26466 for ; Tue, 20 Jun 2000 10:37:20 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id KAA26466 for ; Tue, 20 Jun 2000 10:37:20 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id KAA29689; Tue, 20 Jun 2000 10:36:04 -0400 (EDT) @@ -4903,7 +4903,7 @@ From pgsql-hackers-owner+M3615@hub.org Tue Jun 20 12:55:05 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA25768 for ; Tue, 20 Jun 2000 12:55:04 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA09949 for ; Tue, 20 Jun 2000 12:41:15 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA09949 for ; Tue, 20 Jun 2000 12:41:15 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5KGcCM19112; Tue, 20 Jun 2000 12:38:12 -0400 (EDT) @@ -5012,7 +5012,7 @@ From Inoue@tpf.co.jp Tue Jun 20 17:10:56 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id RAA10307 for ; Tue, 20 Jun 2000 17:10:55 -0400 (EDT) -Received: from sd.tpf.co.jp (mail.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id QAA08017 for ; Tue, 20 Jun 2000 16:57:44 -0400 (EDT) +Received: from sd.tpf.co.jp (mail.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id QAA08017 for ; Tue, 20 Jun 2000 16:57:44 -0400 (EDT) Received: from mcadnote1 (ppm127.noc.fukui.nsk.ne.jp [210.161.188.46]) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id FAA00867; Wed, 21 Jun 2000 05:56:44 +0900 @@ -5078,7 +5078,7 @@ From Inoue@tpf.co.jp Tue Jun 20 20:00:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id UAA12668; Tue, 20 Jun 2000 20:00:58 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA21016; Tue, 20 Jun 2000 19:54:18 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA21016; Tue, 20 Jun 2000 19:54:18 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id IAA00974; Wed, 21 Jun 2000 08:52:38 +0900 @@ -5143,7 +5143,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 00:23:48 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id AAA18016; Wed, 21 Jun 2000 00:23:47 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA05207; Wed, 21 Jun 2000 00:07:58 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA05207; Wed, 21 Jun 2000 00:07:58 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id AAA03002; Wed, 21 Jun 2000 00:06:42 -0400 (EDT) @@ -5270,7 +5270,7 @@ From pgsql-hackers-owner+M3636@hub.org Wed Jun 21 01:31:12 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA20523 for ; Wed, 21 Jun 2000 01:31:12 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA08982 for ; Wed, 21 Jun 2000 01:15:17 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA08982 for ; Wed, 21 Jun 2000 01:15:17 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5L5Bp151546; Wed, 21 Jun 2000 01:11:51 -0400 (EDT) @@ -5328,7 +5328,7 @@ From dhogaza@pacifier.com Wed Jun 21 01:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA20492 for ; Wed, 21 Jun 2000 01:30:58 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA09401 for ; Wed, 21 Jun 2000 01:22:50 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA09401 for ; Wed, 21 Jun 2000 01:22:50 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id WAA22395; Tue, 20 Jun 2000 22:21:47 -0700 (PDT) @@ -5377,7 +5377,7 @@ From lockhart@alumni.caltech.edu Wed Jun 21 01:31:07 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA20508; Wed, 21 Jun 2000 01:31:06 -0400 (EDT) -Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA09355; Wed, 21 Jun 2000 01:22:03 -0400 (EDT) +Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA09355; Wed, 21 Jun 2000 01:22:03 -0400 (EDT) Received: from golem.jpl.nasa.gov (hectic-1 [128.149.68.203]) by huey.jpl.nasa.gov (8.8.8+Sun/8.8.8) with ESMTP id WAA00821; Tue, 20 Jun 2000 22:18:38 -0700 (PDT) @@ -5431,7 +5431,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 01:31:05 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA20503 for ; Wed, 21 Jun 2000 01:31:05 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA09513 for ; Wed, 21 Jun 2000 01:25:18 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA09513 for ; Wed, 21 Jun 2000 01:25:18 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id BAA03557; Wed, 21 Jun 2000 01:23:58 -0400 (EDT) @@ -5487,7 +5487,7 @@ From pgsql-hackers-owner+M3641@hub.org Wed Jun 21 02:31:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA25698 for ; Wed, 21 Jun 2000 02:31:00 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id CAA11423 for ; Wed, 21 Jun 2000 02:09:13 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id CAA11423 for ; Wed, 21 Jun 2000 02:09:13 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5L5we151226; Wed, 21 Jun 2000 01:58:40 -0400 (EDT) @@ -5555,7 +5555,7 @@ From pgsql-hackers-owner+M3644@hub.org Wed Jun 21 02:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA25704 for ; Wed, 21 Jun 2000 02:31:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id CAA11923 for ; Wed, 21 Jun 2000 02:22:41 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id CAA11923 for ; Wed, 21 Jun 2000 02:22:41 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5L6JO196109; Wed, 21 Jun 2000 02:19:24 -0400 (EDT) @@ -5612,7 +5612,7 @@ From pgsql-hackers-owner+M3648@hub.org Wed Jun 21 09:01:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id JAA06055 for ; Wed, 21 Jun 2000 09:01:00 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id IAA29647 for ; Wed, 21 Jun 2000 08:52:25 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA29647 for ; Wed, 21 Jun 2000 08:52:25 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5LCo0112103; Wed, 21 Jun 2000 08:50:00 -0400 (EDT) @@ -5668,7 +5668,7 @@ From e99re41@DoCS.UU.SE Wed Jun 21 10:01:10 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id KAA06585; Wed, 21 Jun 2000 10:01:09 -0400 (EDT) -Received: from meryl.it.uu.se (root@meryl.it.uu.se [130.238.12.42]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id JAA03592; Wed, 21 Jun 2000 09:38:34 -0400 (EDT) +Received: from meryl.it.uu.se (root@meryl.it.uu.se [130.238.12.42]) by renoir.op.net (o1/$Revision$) with ESMTP id JAA03592; Wed, 21 Jun 2000 09:38:34 -0400 (EDT) Received: from Ulv.DoCS.UU.SE (e99re41@Ulv.DoCS.UU.SE [130.238.9.167]) by meryl.it.uu.se (8.8.5/8.8.5) with ESMTP id PAA20520; Wed, 21 Jun 2000 15:34:34 +0200 (MET DST) @@ -5741,7 +5741,7 @@ From e99re41@DoCS.UU.SE Wed Jun 21 10:01:09 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id KAA06582; Wed, 21 Jun 2000 10:01:08 -0400 (EDT) -Received: from meryl.it.uu.se (root@meryl.it.uu.se [130.238.12.42]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id JAA04510; Wed, 21 Jun 2000 09:43:48 -0400 (EDT) +Received: from meryl.it.uu.se (root@meryl.it.uu.se [130.238.12.42]) by renoir.op.net (o1/$Revision$) with ESMTP id JAA04510; Wed, 21 Jun 2000 09:43:48 -0400 (EDT) Received: from Ulv.DoCS.UU.SE (e99re41@Ulv.DoCS.UU.SE [130.238.9.167]) by meryl.it.uu.se (8.8.5/8.8.5) with ESMTP id PAA20730; Wed, 21 Jun 2000 15:39:23 +0200 (MET DST) @@ -5785,7 +5785,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 11:31:09 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA08120; Wed, 21 Jun 2000 11:31:08 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA13232; Wed, 21 Jun 2000 11:08:38 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA13232; Wed, 21 Jun 2000 11:08:38 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id LAA04286; Wed, 21 Jun 2000 11:07:20 -0400 (EDT) @@ -5840,7 +5840,7 @@ From lockhart@alumni.caltech.edu Wed Jun 21 11:31:10 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA08135; Wed, 21 Jun 2000 11:31:09 -0400 (EDT) -Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA15864; Wed, 21 Jun 2000 11:30:06 -0400 (EDT) +Received: from huey.jpl.nasa.gov (huey.jpl.nasa.gov [128.149.68.100]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA15864; Wed, 21 Jun 2000 11:30:06 -0400 (EDT) Received: from golem.jpl.nasa.gov (hectic-1 [128.149.68.203]) by huey.jpl.nasa.gov (8.8.8+Sun/8.8.8) with ESMTP id IAA02881; Wed, 21 Jun 2000 08:26:40 -0700 (PDT) @@ -5898,7 +5898,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 11:31:18 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA08164; Wed, 21 Jun 2000 11:31:12 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA15786; Wed, 21 Jun 2000 11:29:30 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA15786; Wed, 21 Jun 2000 11:29:30 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id LAA04451; Wed, 21 Jun 2000 11:28:09 -0400 (EDT) @@ -5977,7 +5977,7 @@ From lamar.owen@wgcr.org Wed Jun 21 11:51:39 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA09021; Wed, 21 Jun 2000 11:51:38 -0400 (EDT) -Received: from www.wgcr.org (IDENT:root@www.wgcr.org [206.74.232.194]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA18613; Wed, 21 Jun 2000 11:51:48 -0400 (EDT) +Received: from www.wgcr.org (IDENT:root@www.wgcr.org [206.74.232.194]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA18613; Wed, 21 Jun 2000 11:51:48 -0400 (EDT) Received: from wgcr.org ([206.74.232.197]) by www.wgcr.org (8.9.3/8.9.3/WGCR) with ESMTP id LAA19124; Wed, 21 Jun 2000 11:48:25 -0400 @@ -6089,7 +6089,7 @@ From pgsql-hackers-owner+M3670@hub.org Wed Jun 21 12:30:42 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA10371 for ; Wed, 21 Jun 2000 12:30:41 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA22315 for ; Wed, 21 Jun 2000 12:23:18 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA22315 for ; Wed, 21 Jun 2000 12:23:18 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5LGJU175424; Wed, 21 Jun 2000 12:19:30 -0400 (EDT) @@ -6146,7 +6146,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 12:30:40 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA10364 for ; Wed, 21 Jun 2000 12:30:38 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA22593 for ; Wed, 21 Jun 2000 12:25:58 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA22593 for ; Wed, 21 Jun 2000 12:25:58 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id MAA04944; Wed, 21 Jun 2000 12:24:44 -0400 (EDT) @@ -6198,7 +6198,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 13:01:06 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id NAA11366 for ; Wed, 21 Jun 2000 13:01:05 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA24726 for ; Wed, 21 Jun 2000 12:47:50 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA24726 for ; Wed, 21 Jun 2000 12:47:50 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id MAA05112; Wed, 21 Jun 2000 12:46:34 -0400 (EDT) @@ -6249,7 +6249,7 @@ From peter@localhost.its.uu.se Wed Jun 21 14:31:13 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA13233 for ; Wed, 21 Jun 2000 14:31:13 -0400 (EDT) -Received: from merganser.its.uu.se (merganser.its.uu.se [130.238.6.236]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id OAA04201 for ; Wed, 21 Jun 2000 14:11:42 -0400 (EDT) +Received: from merganser.its.uu.se (merganser.its.uu.se [130.238.6.236]) by renoir.op.net (o1/$Revision$) with ESMTP id OAA04201 for ; Wed, 21 Jun 2000 14:11:42 -0400 (EDT) Received: from regulus.student.UU.SE ([130.238.5.2]:34923 "EHLO regulus.its.uu.se") by merganser.its.uu.se with ESMTP id ; Wed, 21 Jun 2000 20:09:46 +0200 @@ -6303,7 +6303,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 18:14:19 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id SAA24147 for ; Wed, 21 Jun 2000 18:14:18 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id RAA24649 for ; Wed, 21 Jun 2000 17:40:59 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id RAA24649 for ; Wed, 21 Jun 2000 17:40:59 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id RAA06031; Wed, 21 Jun 2000 17:39:38 -0400 (EDT) @@ -6351,7 +6351,7 @@ From vmikheev@SECTORBASE.COM Wed Jun 21 22:18:38 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07570; Wed, 21 Jun 2000 22:18:36 -0400 (EDT) -Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA29965; Wed, 21 Jun 2000 19:07:37 -0400 (EDT) +Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA29965; Wed, 21 Jun 2000 19:07:37 -0400 (EDT) Received: by SECTORBASE2 with Internet Mail Service (5.5.2650.21) id ; Wed, 21 Jun 2000 15:58:30 -0700 Message-ID: <8F4C99C66D04D4118F580090272A7A23018C2B@SECTORBASE1> @@ -6406,7 +6406,7 @@ From Inoue@tpf.co.jp Wed Jun 21 22:18:39 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07573; Wed, 21 Jun 2000 22:18:38 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id TAA01857; Wed, 21 Jun 2000 19:37:04 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id TAA01857; Wed, 21 Jun 2000 19:37:04 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id IAA02627; Thu, 22 Jun 2000 08:35:27 +0900 @@ -6474,7 +6474,7 @@ From Inoue@tpf.co.jp Wed Jun 21 22:18:15 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07540; Wed, 21 Jun 2000 22:18:11 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA04100; Wed, 21 Jun 2000 20:15:09 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA04100; Wed, 21 Jun 2000 20:15:09 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id JAA02691; Thu, 22 Jun 2000 09:14:15 +0900 @@ -6533,7 +6533,7 @@ From Inoue@tpf.co.jp Wed Jun 21 22:18:16 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07553; Wed, 21 Jun 2000 22:18:15 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA05872; Wed, 21 Jun 2000 20:44:21 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA05872; Wed, 21 Jun 2000 20:44:21 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id JAA02750; Thu, 22 Jun 2000 09:43:31 +0900 @@ -6594,7 +6594,7 @@ From pgsql-hackers-owner+M3700@hub.org Wed Jun 21 22:17:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07504 for ; Wed, 21 Jun 2000 22:17:58 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id VAA07914 for ; Wed, 21 Jun 2000 21:23:22 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA07914 for ; Wed, 21 Jun 2000 21:23:22 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M1It194420; Wed, 21 Jun 2000 21:18:55 -0400 (EDT) @@ -6654,7 +6654,7 @@ From pgsql-hackers-owner+M3701@hub.org Wed Jun 21 22:18:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07513 for ; Wed, 21 Jun 2000 22:18:01 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id VAA08502 for ; Wed, 21 Jun 2000 21:33:13 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA08502 for ; Wed, 21 Jun 2000 21:33:13 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M1QS107400; Wed, 21 Jun 2000 21:26:28 -0400 (EDT) @@ -6716,7 +6716,7 @@ From vmikheev@SECTORBASE.COM Wed Jun 21 22:17:52 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id WAA07492; Wed, 21 Jun 2000 22:17:51 -0400 (EDT) -Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id VAA08730; Wed, 21 Jun 2000 21:37:44 -0400 (EDT) +Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA08730; Wed, 21 Jun 2000 21:37:44 -0400 (EDT) Received: by SECTORBASE2 with Internet Mail Service (5.5.2650.21) id ; Wed, 21 Jun 2000 18:28:36 -0700 Message-ID: <8F4C99C66D04D4118F580090272A7A23018C2F@SECTORBASE1> @@ -6768,7 +6768,7 @@ From Inoue@tpf.co.jp Wed Jun 21 23:22:36 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id XAA10350 for ; Wed, 21 Jun 2000 23:22:35 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA13743 for ; Wed, 21 Jun 2000 23:07:50 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA13743 for ; Wed, 21 Jun 2000 23:07:50 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id MAA03008; Thu, 22 Jun 2000 12:07:00 +0900 @@ -6831,7 +6831,7 @@ From tgl@sss.pgh.pa.us Wed Jun 21 23:22:38 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id XAA10353 for ; Wed, 21 Jun 2000 23:22:36 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id XAA14206 for ; Wed, 21 Jun 2000 23:16:26 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id XAA14206 for ; Wed, 21 Jun 2000 23:16:26 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id XAA07099; Wed, 21 Jun 2000 23:14:50 -0400 (EDT) @@ -6895,7 +6895,7 @@ From pgsql-hackers-owner+M3711@hub.org Thu Jun 22 01:01:06 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA22245 for ; Thu, 22 Jun 2000 01:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA18310 for ; Thu, 22 Jun 2000 00:43:00 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA18310 for ; Thu, 22 Jun 2000 00:43:00 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M3US167109; Wed, 21 Jun 2000 23:30:28 -0400 (EDT) @@ -6954,7 +6954,7 @@ From tgl@sss.pgh.pa.us Thu Jun 22 01:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id BAA22232; Thu, 22 Jun 2000 01:00:59 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id AAA17842; Thu, 22 Jun 2000 00:31:06 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id AAA17842; Thu, 22 Jun 2000 00:31:06 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id AAA07254; Thu, 22 Jun 2000 00:29:42 -0400 (EDT) @@ -7004,7 +7004,7 @@ From pgsql-hackers-owner+M3720@hub.org Thu Jun 22 02:01:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA24025 for ; Thu, 22 Jun 2000 02:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA21392 for ; Thu, 22 Jun 2000 01:56:49 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA21392 for ; Thu, 22 Jun 2000 01:56:49 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M5jp143149; Thu, 22 Jun 2000 01:45:51 -0400 (EDT) @@ -7059,7 +7059,7 @@ From dhogaza@pacifier.com Thu Jun 22 02:00:58 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA24005 for ; Thu, 22 Jun 2000 02:00:58 -0400 (EDT) -Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA21369 for ; Thu, 22 Jun 2000 01:56:18 -0400 (EDT) +Received: from smtp.pacifier.com (comet.pacifier.com [199.2.117.155]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA21369 for ; Thu, 22 Jun 2000 01:56:18 -0400 (EDT) Received: from desktop (dsl-dhogaza.pacifier.net [207.202.226.68]) by smtp.pacifier.com (8.9.3/8.9.3pop) with SMTP id WAA12121; Wed, 21 Jun 2000 22:55:39 -0700 (PDT) @@ -7096,7 +7096,7 @@ From Inoue@tpf.co.jp Thu Jun 22 02:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id CAA24009 for ; Thu, 22 Jun 2000 02:00:59 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id BAA21277 for ; Thu, 22 Jun 2000 01:54:44 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id BAA21277 for ; Thu, 22 Jun 2000 01:54:44 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id OAA03303; Thu, 22 Jun 2000 14:53:52 +0900 @@ -7168,7 +7168,7 @@ From tgl@sss.pgh.pa.us Thu Jun 22 03:31:04 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA28813 for ; Thu, 22 Jun 2000 03:31:03 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA23901 for ; Thu, 22 Jun 2000 03:06:47 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA23901 for ; Thu, 22 Jun 2000 03:06:47 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id DAA07725; Thu, 22 Jun 2000 03:05:00 -0400 (EDT) @@ -7207,7 +7207,7 @@ From pgsql-hackers-owner+M3727@hub.org Thu Jun 22 03:31:06 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA28819 for ; Thu, 22 Jun 2000 03:31:05 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA24751 for ; Thu, 22 Jun 2000 03:29:00 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA24751 for ; Thu, 22 Jun 2000 03:29:00 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M7KP140211; Thu, 22 Jun 2000 03:20:25 -0400 (EDT) @@ -7269,7 +7269,7 @@ From zeugswettera@wien.spardat.at Thu Jun 22 05:01:11 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id FAA29525 for ; Thu, 22 Jun 2000 05:01:09 -0400 (EDT) -Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id EAA27070 for ; Thu, 22 Jun 2000 04:38:32 -0400 (EDT) +Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision$) with ESMTP id EAA27070 for ; Thu, 22 Jun 2000 04:38:32 -0400 (EDT) Received: from peligor.server.lan.at (peligor.server.lan.at [10.8.32.84]) by gandalf.it-austria.net (xxx/xxx) with ESMTP id KAA23252; Thu, 22 Jun 2000 10:37:45 +0200 @@ -7330,7 +7330,7 @@ From pjw@rhyme.com.au Thu Jun 22 04:01:05 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id EAA29060 for ; Thu, 22 Jun 2000 04:01:03 -0400 (EDT) -Received: from acheron.rime.com.au (root@albatr.lnk.telstra.net [139.130.54.222]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id DAA25604 for ; Thu, 22 Jun 2000 03:50:30 -0400 (EDT) +Received: from acheron.rime.com.au (root@albatr.lnk.telstra.net [139.130.54.222]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA25604 for ; Thu, 22 Jun 2000 03:50:30 -0400 (EDT) Received: from oberon (Oberon.rime.com.au [203.8.195.100]) by acheron.rime.com.au (8.9.3/8.9.3) with SMTP id RAA08811; Thu, 22 Jun 2000 17:43:22 +1000 @@ -7407,7 +7407,7 @@ From pgsql-hackers-owner+M3730@hub.org Thu Jun 22 05:31:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id FAA29741 for ; Thu, 22 Jun 2000 05:31:00 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id FAA28478 for ; Thu, 22 Jun 2000 05:18:37 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id FAA28478 for ; Thu, 22 Jun 2000 05:18:37 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5M96W171286; Thu, 22 Jun 2000 05:06:32 -0400 (EDT) @@ -7467,7 +7467,7 @@ From Inoue@tpf.co.jp Thu Jun 22 07:31:01 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id HAA07559 for ; Thu, 22 Jun 2000 07:31:00 -0400 (EDT) -Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id HAA02741 for ; Thu, 22 Jun 2000 07:08:29 -0400 (EDT) +Received: from sd.tpf.co.jp (sd.tpf.co.jp [210.161.239.34]) by renoir.op.net (o1/$Revision$) with ESMTP id HAA02741 for ; Thu, 22 Jun 2000 07:08:29 -0400 (EDT) Received: from cadzone ([126.0.1.40] (may be forged)) by sd.tpf.co.jp (2.5 Build 2640 (Berkeley 8.8.6)/8.8.4) with SMTP id UAA03834; Thu, 22 Jun 2000 20:06:51 +0900 @@ -7519,7 +7519,7 @@ From tgl@sss.pgh.pa.us Thu Jun 22 11:31:06 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA10544 for ; Thu, 22 Jun 2000 11:31:05 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id LAA23513 for ; Thu, 22 Jun 2000 11:28:53 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA23513 for ; Thu, 22 Jun 2000 11:28:53 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id LAA08851; Thu, 22 Jun 2000 11:27:30 -0400 (EDT) @@ -7560,7 +7560,7 @@ From vmikheev@SECTORBASE.COM Thu Jun 22 14:31:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA11892 for ; Thu, 22 Jun 2000 14:30:59 -0400 (EDT) -Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id OAA10107 for ; Thu, 22 Jun 2000 14:17:04 -0400 (EDT) +Received: from sectorbase2.sectorbase.com ([208.48.122.131]) by renoir.op.net (o1/$Revision$) with ESMTP id OAA10107 for ; Thu, 22 Jun 2000 14:17:04 -0400 (EDT) Received: by SECTORBASE2 with Internet Mail Service (5.5.2650.21) id ; Thu, 22 Jun 2000 11:07:59 -0700 Message-ID: <8F4C99C66D04D4118F580090272A7A23018C31@SECTORBASE1> @@ -7625,7 +7625,7 @@ From peter@localhost.its.uu.se Thu Jun 22 18:37:35 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id SAA19684 for ; Thu, 22 Jun 2000 18:37:34 -0400 (EDT) -Received: from merganser.its.uu.se (merganser.its.uu.se [130.238.6.236]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id SAA02841 for ; Thu, 22 Jun 2000 18:31:53 -0400 (EDT) +Received: from merganser.its.uu.se (merganser.its.uu.se [130.238.6.236]) by renoir.op.net (o1/$Revision$) with ESMTP id SAA02841 for ; Thu, 22 Jun 2000 18:31:53 -0400 (EDT) Received: from regulus.student.UU.SE ([130.238.5.2]:37596 "EHLO regulus.its.uu.se") by merganser.its.uu.se with ESMTP id ; Fri, 23 Jun 2000 00:29:48 +0200 @@ -9198,7 +9198,7 @@ From ZeugswetterA@wien.spardat.at Thu Jun 29 06:34:49 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id GAA25201 for ; Thu, 29 Jun 2000 06:34:44 -0400 (EDT) -Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id GAA00379 for ; Thu, 29 Jun 2000 06:35:30 -0400 (EDT) +Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision$) with ESMTP id GAA00379 for ; Thu, 29 Jun 2000 06:35:30 -0400 (EDT) Received: from sdexcgtw01.f000.d0188.sd.spardat.at (sdgtw.sd.spardat.at [172.18.1.16]) by gandalf.it-austria.net (xxx/xxx) with ESMTP id MAA33950; Thu, 29 Jun 2000 12:33:42 +0200 @@ -9751,7 +9751,7 @@ From ZeugswetterA@wien.spardat.at Mon Jul 3 04:30:07 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id EAA16088 for ; Mon, 3 Jul 2000 04:30:05 -0400 (EDT) -Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id EAA19031 for ; Mon, 3 Jul 2000 04:30:07 -0400 (EDT) +Received: from gandalf.it-austria.net (gandalf.it-austria.net [213.150.1.65]) by renoir.op.net (o1/$Revision$) with ESMTP id EAA19031 for ; Mon, 3 Jul 2000 04:30:07 -0400 (EDT) Received: from sdexcgtw01.f000.d0188.sd.spardat.at (sdgtw.sd.spardat.at [172.18.1.16]) by gandalf.it-austria.net (xxx/xxx) with ESMTP id KAA28416; Mon, 3 Jul 2000 10:28:06 +0200 @@ -9808,7 +9808,7 @@ From pgsql-hackers-owner+M3496@hub.org Fri Jun 16 15:55:14 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id OAA02116 for ; Fri, 16 Jun 2000 14:55:13 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id NAA21581 for ; Fri, 16 Jun 2000 13:53:58 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id NAA21581 for ; Fri, 16 Jun 2000 13:53:58 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5GHpqN06086; Fri, 16 Jun 2000 13:51:52 -0400 (EDT) @@ -9920,7 +9920,7 @@ From pgsql-hackers-owner+M3524@hub.org Fri Jun 16 22:30:59 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id VAA07796 for ; Fri, 16 Jun 2000 21:30:58 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id VAA26393 for ; Fri, 16 Jun 2000 21:16:37 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id VAA26393 for ; Fri, 16 Jun 2000 21:16:37 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5H1EeM94683; Fri, 16 Jun 2000 21:14:40 -0400 (EDT) @@ -9964,7 +9964,7 @@ From pgsql-hackers-owner+M3525@hub.org Sat Jun 17 07:01:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id GAA22194 for ; Sat, 17 Jun 2000 06:01:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id FAA21836 for ; Sat, 17 Jun 2000 05:39:21 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id FAA21836 for ; Sat, 17 Jun 2000 05:39:21 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5H9bSM88777; Sat, 17 Jun 2000 05:37:28 -0400 (EDT) @@ -10074,7 +10074,7 @@ From pgsql-hackers-owner+M3529@hub.org Sat Jun 17 10:01:24 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id JAA24004 for ; Sat, 17 Jun 2000 09:01:23 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id IAA28633 for ; Sat, 17 Jun 2000 08:57:47 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA28633 for ; Sat, 17 Jun 2000 08:57:47 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5HCtxM77095; Sat, 17 Jun 2000 08:55:59 -0400 (EDT) @@ -10146,7 +10146,7 @@ From pgsql-hackers-owner+M3534@hub.org Sat Jun 17 13:31:11 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id MAA02801 for ; Sat, 17 Jun 2000 12:31:10 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id MAA07848 for ; Sat, 17 Jun 2000 12:27:14 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id MAA07848 for ; Sat, 17 Jun 2000 12:27:14 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5HGPJM95074; Sat, 17 Jun 2000 12:25:19 -0400 (EDT) @@ -10206,7 +10206,7 @@ From pgsql-hackers-owner+M3553@hub.org Sun Jun 18 18:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id RAA08740 for ; Sun, 18 Jun 2000 17:31:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id RAA18332 for ; Sun, 18 Jun 2000 17:21:51 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id RAA18332 for ; Sun, 18 Jun 2000 17:21:51 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5ILJcM11720; Sun, 18 Jun 2000 17:19:38 -0400 (EDT) @@ -10297,7 +10297,7 @@ From pgsql-hackers-owner+M3561@hub.org Sun Jun 18 21:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id UAA20523 for ; Sun, 18 Jun 2000 20:31:02 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA25719 for ; Sun, 18 Jun 2000 20:26:49 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA25719 for ; Sun, 18 Jun 2000 20:26:49 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5J0OLM53050; Sun, 18 Jun 2000 20:24:21 -0400 (EDT) @@ -10368,7 +10368,7 @@ From pgsql-hackers-owner+M3523@hub.org Fri Jun 16 22:01:00 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id VAA07568 for ; Fri, 16 Jun 2000 21:00:59 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id UAA25354 for ; Fri, 16 Jun 2000 20:54:02 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id UAA25354 for ; Fri, 16 Jun 2000 20:54:02 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5H0q3M53458; Fri, 16 Jun 2000 20:52:03 -0400 (EDT) @@ -10493,7 +10493,7 @@ From pgsql-hackers-owner+M3591@hub.org Mon Jun 19 11:01:19 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id KAA21409 for ; Mon, 19 Jun 2000 10:01:18 -0400 (EDT) -Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.12 $) with ESMTP id JAA05383 for ; Mon, 19 Jun 2000 09:56:59 -0400 (EDT) +Received: from hub.org (root@hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id JAA05383 for ; Mon, 19 Jun 2000 09:56:59 -0400 (EDT) Received: from hub.org (majordom@localhost [127.0.0.1]) by hub.org (8.10.1/8.10.1) with SMTP id e5JDsVM91574; Mon, 19 Jun 2000 09:54:31 -0400 (EDT) diff --git a/doc/TODO.detail/typeconv b/doc/TODO.detail/typeconv index 52cc1ff..ff55a17 100644 --- a/doc/TODO.detail/typeconv +++ b/doc/TODO.detail/typeconv @@ -122,7 +122,7 @@ From tgl@sss.pgh.pa.us Sun May 14 17:30:56 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id RAA05808 for ; Sun, 14 May 2000 17:30:52 -0400 (EDT) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.4 $) with ESMTP id RAA16657 for ; Sun, 14 May 2000 17:29:52 -0400 (EDT) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id RAA16657 for ; Sun, 14 May 2000 17:29:52 -0400 (EDT) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id RAA20914; Sun, 14 May 2000 17:29:30 -0400 (EDT) diff --git a/doc/TODO.detail/vacuum b/doc/TODO.detail/vacuum index 58839ac..f75ffeb 100644 --- a/doc/TODO.detail/vacuum +++ b/doc/TODO.detail/vacuum @@ -1403,7 +1403,7 @@ From owner-pgsql-hackers@hub.org Sat Jan 22 02:31:03 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id DAA06743 for ; Sat, 22 Jan 2000 03:31:02 -0500 (EST) -Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision: 1.7 $) with ESMTP id DAA07529 for ; Sat, 22 Jan 2000 03:25:13 -0500 (EST) +Received: from hub.org (hub.org [216.126.84.1]) by renoir.op.net (o1/$Revision$) with ESMTP id DAA07529 for ; Sat, 22 Jan 2000 03:25:13 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.9.3/8.9.3) with SMTP id DAA31900; Sat, 22 Jan 2000 03:19:53 -0500 (EST) @@ -1475,7 +1475,7 @@ From tgl@sss.pgh.pa.us Sat Jan 22 10:31:02 2000 Received: from renoir.op.net (root@renoir.op.net [207.29.195.4]) by candle.pha.pa.us (8.9.0/8.9.0) with ESMTP id LAA20882 for ; Sat, 22 Jan 2000 11:31:00 -0500 (EST) -Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision: 1.7 $) with ESMTP id LAA26612 for ; Sat, 22 Jan 2000 11:12:44 -0500 (EST) +Received: from sss2.sss.pgh.pa.us (sss.pgh.pa.us [209.114.166.2]) by renoir.op.net (o1/$Revision$) with ESMTP id LAA26612 for ; Sat, 22 Jan 2000 11:12:44 -0500 (EST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss2.sss.pgh.pa.us (8.9.3/8.9.3) with ESMTP id LAA20569; Sat, 22 Jan 2000 11:11:26 -0500 (EST) diff --git a/src/backend/optimizer/plan/README b/src/backend/optimizer/plan/README index d3a5168..a63596f 100644 --- a/src/backend/optimizer/plan/README +++ b/src/backend/optimizer/plan/README @@ -6,7 +6,7 @@ From owner-pgsql-hackers@hub.org Fri Feb 13 09:01:19 1998 Received: from renoir.op.net (root@renoir.op.net [209.152.193.4]) by candle.pha.pa.us (8.8.5/8.8.5) with ESMTP id JAA11576 for ; Fri, 13 Feb 1998 09:01:17 -0500 (EST) -Received: from hub.org (hub.org [209.47.148.200]) by renoir.op.net (o1/$Revision: 1.1 $) with ESMTP id IAA09761 for ; Fri, 13 Feb 1998 08:41:22 -0500 (EST) +Received: from hub.org (hub.org [209.47.148.200]) by renoir.op.net (o1/$Revision$) with ESMTP id IAA09761 for ; Fri, 13 Feb 1998 08:41:22 -0500 (EST) Received: from localhost (majordom@localhost) by hub.org (8.8.8/8.7.5) with SMTP id IAA08135; Fri, 13 Feb 1998 08:40:17 -0500 (EST) Received: by hub.org (TLB v0.10a (1.23 tibbs 1997/01/09 00:29:32)); Fri, 13 Feb 1998 08:38:42 -0500 (EST) Received: (from majordom@localhost) by hub.org (8.8.8/8.7.5) id IAA06646 for pgsql-hackers-outgoing; Fri, 13 Feb 1998 08:38:35 -0500 (EST) diff --git a/src/backend/port/darwin/system.c b/src/backend/port/darwin/system.c index d2c2726..a0c0801 100644 --- a/src/backend/port/darwin/system.c +++ b/src/backend/port/darwin/system.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: src/lib/libc/stdlib/system.c,v 1.6 2000/03/16 02:14:41 jasone Exp $ */ #if defined(LIBC_SCCS) && !defined(lint) diff --git a/src/backend/port/tas/hpux_hppa.s b/src/backend/port/tas/hpux_hppa.s new file mode 100644 index 0000000..d978a7c --- /dev/null +++ b/src/backend/port/tas/hpux_hppa.s @@ -0,0 +1,28 @@ + + .SPACE $TEXT$,SORT=8 + .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24 +tas + .PROC + .CALLINFO CALLER,FRAME=0,ENTRY_SR=3 + .ENTRY + LDO 15(%r26),%r31 ;offset 0x0 + DEPI 0,31,4,%r31 ;offset 0x4 + LDCWX 0(0,%r31),%r23 ;offset 0x8 + COMICLR,= 0,%r23,%r0 ;offset 0xc + DEP,TR %r0,31,32,%r28 ;offset 0x10 +$00000001 + LDI 1,%r28 ;offset 0x14 +$L0 + .EXIT + BV,N %r0(%r2) ;offset 0x18 + .PROCEND ;in=26;out=28; + + + .SPACE $TEXT$ + .SUBSPA $CODE$ + .SPACE $PRIVATE$,SORT=16 + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31,SORT=16 + .SPACE $TEXT$ + .SUBSPA $CODE$ + .EXPORT tas,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR + .END diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ce53efb..3202d04 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2657,7 +2657,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.360.2.1 $ $Date: 2003/09/07 04:36:53 $\n"); + puts("$Revision$ $Date$\n"); } /* diff --git a/src/backend/utils/misc/help_config.c b/src/backend/utils/misc/help_config.c new file mode 100644 index 0000000..95e3416 --- /dev/null +++ b/src/backend/utils/misc/help_config.c @@ -0,0 +1,448 @@ +/*------------------------------------------------------------------------- + * help_config.c + * + * Displays available options under grand unified configuration scheme + * + * The purpose of this option is to list, sort, and make searchable, all + * runtime options available to Postgresql, by their description and grouping. + * + * Valid command-line options to this program: + * + * none : All available variables are sorted by group and name + * and formatted nicely. ( for human consumption ) + * : list all the variables whose name matches this string + * -g : list all the variables whose group matches this string + * -l : lists all currently defined groups and terminates + * -G : no sort by groups (you get strict name order, instead) + * -m : output the list in Machine friendly format, with a header row + * -M : same as m, except no header + * -h : help + * + * Options whose flag bits are set to GUC_NO_SHOW_ALL, GUC_NOT_IN_SAMPLE, + * or GUC_DISALLOW_IN_FILE are not displayed, unless the user specifically + * requests that variable by name + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $Header$ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include +#include +#include + +#include "utils/guc.h" +#include "utils/guc_tables.h" +#include "utils/help_config.h" + +extern int optind; +extern char *optarg; + + +/* + * The following char constructs provide the different formats the variables + * can be outputted in. + */ +enum outputFormat +{ + HUMAN_OUTPUT, + MACHINE_OUTPUT +}; + +static const char *const GENERIC_FORMAT[] = { + gettext_noop("Name : %-20s \nContext : %-20s \nGroup : %-20s\n"), + gettext_noop("%s\t%s\t%s\t") +}; +static const char *const GENERIC_DESC[] = { + gettext_noop("Description: %s\n%s\n"), + gettext_noop("%s %s\n") +}; +static const char *const BOOL_FORMAT[] = { + gettext_noop("Type : BOOL\nReset Value: %-s \n"), + gettext_noop("BOOL\t%s\t\t\t") +}; +static const char *const INT_FORMAT[] = { + gettext_noop("Type : INT\nReset Value: %-20d \nMin Value : %-20d \nMax Value : %-20d \n"), + gettext_noop("INT\t%d\t%d\t%d\t") +}; +static const char *const REAL_FORMAT[] = { + gettext_noop("Type : REAL\nReset Value: %-20g \nMin Value : %-20g \nMax Value : %-20g \n"), + gettext_noop("REAL\t%g\t%g\t%g\t") +}; +static const char *const STRING_FORMAT[] = { + gettext_noop("Type : STRING\nReset Value: %-s \n"), + gettext_noop("STRING\t%s\t\t\t") +}; +static const char *const COLUMN_HEADER[] = { + "", + gettext_noop("NAME\tCONTEXT\tGROUP\tTYPE\tRESET_VALUE\tMIN\tMAX\tSHORT_DESCRIPTION\tLONG_DESCRIPTION\n") +}; +static const char *const ROW_SEPARATOR[] = { + "------------------------------------------------------------\n", + "" +}; + +/* + * Variables loaded from the command line + */ +static char *nameString = NULL; /* The var name pattern to match */ +static bool nameRegexBool = false; /* Match the name pattern as a + * regex */ +static char *groupString = NULL; /* The var group pattern to match */ +static bool groupRegexBool = false; /* Match the group pattern as a + * regex */ +static enum outputFormat outFormat = HUMAN_OUTPUT; +static bool suppressAllHeaders = false; /* MACHINE_OUTPUT output, no + * column headers */ +static bool groupResults = true; /* sort result list by groups */ + + +/* + * This union allows us to mix the numerous different types of structs + * that we are organizing. + */ +typedef union +{ + struct config_generic generic; + struct config_bool bool; + struct config_real real; + struct config_int integer; + struct config_string string; +} mixedStruct; + + +/* function prototypes */ +static bool varMatches(mixedStruct *structToTest); +static int compareMixedStructs(const void *, const void *); +static mixedStruct **varsToDisplay(int *resultListSize); +static const char *usageErrMsg(void); +static void helpMessage(void); +static void listAllGroups(void); +static void printGenericHead(struct config_generic structToPrint); +static void printGenericFoot(struct config_generic structToPrint); +static void printMixedStruct(mixedStruct *structToPrint); +static bool displayStruct(mixedStruct *structToDisplay); + + +/* + * Reads in the the command line options and sets the state of the program + * accordingly. Initializes the result list and sorts it. + */ +int +GucInfoMain(int argc, char *argv[]) +{ + mixedStruct **varList; + int resultListSize; + int c; + int i; + + while ((c = getopt(argc, argv, "g:rGmMlh")) != -1) + { + switch (c) + { + case 'g': + groupString = optarg; + break; + case 'r': /* not actually implemented yet */ + nameRegexBool = true; + break; + case 'G': + groupResults = false; + break; + case 'm': + outFormat = MACHINE_OUTPUT; + break; + case 'M': + outFormat = MACHINE_OUTPUT; + suppressAllHeaders = true; + break; + case 'l': + listAllGroups(); + exit(0); + case 'h': + helpMessage(); + exit(0); + + default: + fprintf(stderr, gettext("%s \n Try -h for further details\n"), usageErrMsg()); + exit(1); + } + } + + if (optind < argc) + nameString = argv[optind]; + + /* get the list of variables that match the user's specs. */ + varList = varsToDisplay(&resultListSize); + + /* sort them by group if desired */ + /* (without this, we get the original sort by name from guc.c) */ + if (groupResults) + qsort(varList, resultListSize, + sizeof(mixedStruct *), compareMixedStructs); + + /* output the results */ + if (!suppressAllHeaders) + printf(gettext(COLUMN_HEADER[outFormat])); + + for (i = 0; varList[i] != NULL; i++) + { + printf(gettext(ROW_SEPARATOR[outFormat])); + printMixedStruct(varList[i]); + } + + return 0; +} + + +/* + * This function is used to compare two mixedStruct types. It compares based + * on the value of the 'group' field, and then the name of the variable. + * Each void* is expected to be a pointer to a pointer to a struct. + * (This is because it is used by qsort to sort an array of struct pointers) + * + * Returns an integer less than, equal to, or greater than zero if the first + * argument (struct1) is considered to be respectively less than, equal to, + * or greater than the second (struct2). The comparison is made frist on the + * value of struct{1,2}.generic.group and then struct{1,2}.generic.name. The + * groups will display in the order they are defined in enum config_group + */ +static int +compareMixedStructs(const void *struct1, const void *struct2) +{ + mixedStruct *structVar1 = *(mixedStruct **) struct1; + mixedStruct *structVar2 = *(mixedStruct **) struct2; + + if (structVar1->generic.group > structVar2->generic.group) + return 1; + else if (structVar1->generic.group < structVar2->generic.group) + return -1; + else + return strcmp(structVar1->generic.name, structVar2->generic.name); +} + + +/* + * This function returns a complete list of all the variables to display, + * according to what the user wants to see. + */ +static mixedStruct ** +varsToDisplay(int *resultListSize) +{ + mixedStruct **resultList; + int arrayIndex; + int i; + + /* Initialize the guc_variables[] array */ + build_guc_variables(); + + /* Extract just the ones we want to display */ + resultList = malloc((num_guc_variables + 1) * sizeof(mixedStruct *)); + arrayIndex = 0; + + for (i = 0; i < num_guc_variables; i++) + { + mixedStruct *var = (mixedStruct *) guc_variables[i]; + + if (varMatches(var)) + resultList[arrayIndex++] = var; + } + + /* add an end marker */ + resultList[arrayIndex] = NULL; + + *resultListSize = arrayIndex; + return resultList; +} + + +/* + * This function will return true if the struct passed to it + * should be displayed to the user. + * + * The criteria to determine if the struct should not be displayed is: + * + It's flag bits are set to GUC_NO_SHOW_ALL + * + It's flag bits are set to GUC_NOT_IN_SAMPLE + * + It's flag bits are set to GUC_DISALLOW_IN_FILE + */ +static bool +displayStruct(mixedStruct *structToDisplay) +{ + if (structToDisplay->generic.flags & (GUC_NO_SHOW_ALL | + GUC_NOT_IN_SAMPLE | + GUC_DISALLOW_IN_FILE)) + return false; + else + return true; +} + + +/* + * Used to determine if a variable matches the user's specifications (stored in + * global variables). Returns true if this particular variable information should + * be returned to the user. + */ +static bool +varMatches(mixedStruct *structToTest) +{ + bool matches = false; + bool specificSearch = false; /* This is true if the user + * searched for a variable in + * particular. */ + + if (nameString != NULL && !nameRegexBool) + { + if (strstr(structToTest->generic.name, nameString) != NULL) + { + matches = true; + specificSearch = true; + } + } + + if (nameString != NULL && nameRegexBool) + { + /* We do not support this option yet */ + } + + if (groupString != NULL && !groupRegexBool) + { + if (strstr(config_group_names[structToTest->generic.group], groupString) != NULL) + { + if (nameString != NULL) + matches = (matches && true); + else + matches = true; + } + else + matches = false; + } + + if (groupString != NULL && groupRegexBool) + { + /* We do not support this option yet */ + } + + /* return all variables */ + if (nameString == NULL && groupString == NULL) + matches = true; + + if (specificSearch) + return matches; + else + return matches && displayStruct(structToTest); +} + + +/* + * This function prints out the generic struct passed to it. It will print out + * a different format, depending on what the user wants to see. + */ +static void +printMixedStruct(mixedStruct *structToPrint) +{ + printGenericHead(structToPrint->generic); + + switch (structToPrint->generic.vartype) + { + + case PGC_BOOL: + printf(gettext(BOOL_FORMAT[outFormat]), + (structToPrint->bool.reset_val == 0) ? + gettext("FALSE") : gettext("TRUE")); + break; + + case PGC_INT: + printf(gettext(INT_FORMAT[outFormat]), + structToPrint->integer.reset_val, + structToPrint->integer.min, + structToPrint->integer.max); + break; + + case PGC_REAL: + printf(gettext(REAL_FORMAT[outFormat]), + structToPrint->real.reset_val, + structToPrint->real.min, + structToPrint->real.max); + break; + + case PGC_STRING: + printf(gettext(STRING_FORMAT[outFormat]), + structToPrint->string.boot_val); + break; + + default: + printf(gettext("Unrecognized variable type!\n")); + break; + } + + printGenericFoot(structToPrint->generic); +} + +static void +printGenericHead(struct config_generic structToPrint) +{ + printf(gettext(GENERIC_FORMAT[outFormat]), + structToPrint.name, + GucContext_Names[structToPrint.context], + gettext(config_group_names[structToPrint.group])); +} + +static void +printGenericFoot(struct config_generic sPrint) +{ + printf(gettext(GENERIC_DESC[outFormat]), + (sPrint.short_desc == NULL) ? "" : gettext(sPrint.short_desc), + (sPrint.long_desc == NULL) ? "" : gettext(sPrint.long_desc)); +} + +static void +listAllGroups(void) +{ + int i; + + printf(gettext("All currently defined groups\n")); + printf(gettext("----------------------------\n")); + for (i = 0; config_group_names[i] != NULL; i++) + printf(gettext("%s\n"), gettext(config_group_names[i])); +} + +static const char * +usageErrMsg(void) +{ + return gettext("Usage for --help-config option: [-h] [-g ] [-l] [-G] [-m] [-M] [string]\n"); +} + +static void +helpMessage(void) +{ + printf(gettext("Description:\n" + "--help-config displays all the runtime options available in PostgreSQL.\n" + "It groups them by category and sorts them by name. If available, it will\n" + "present a short description, default, max and min values as well as other\n" + "information about each option.\n\n" + "With no options specified, it will output all available runtime options\n" + "in human friendly format, grouped by category and sorted by name.\n\n" + + "%s\n" + + "General Options:\n" + " [string] All options with names that match this string\n" + " -g GROUP All options in categories that match GROUP\n" + " -l Prints list of all groups / subgroups\n" + " -h Prints this help message\n" + "\nOutput Options:\n" + " -G Do not group by category\n" + " -m Machine friendly format: tab separated fields\n" + " -M Same as m, except header with column names is suppressed\n"), + usageErrMsg() + ); +} diff --git a/src/bin/pg_controldata/po/cs.po b/src/bin/pg_controldata/po/cs.po new file mode 100644 index 0000000..8883fb8 --- /dev/null +++ b/src/bin/pg_controldata/po/cs.po @@ -0,0 +1,230 @@ +# Czech translation of pg_controldata messages. +# Karel Zak , 2003. +# +# $Id$ +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 7.4\n" +"POT-Creation-Date: 2003-06-29 12:25+0200\n" +"PO-Revision-Date: 2003-07-12 23:20-0000\n" +"Last-Translator: Karel Zak \n" +"Language-Team: Karel Zak \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#: pg_controldata.c:31 +#, c-format +msgid "" +"Usage:\n" +" %s [OPTION]\n" +"\n" +"Options:\n" +" DATADIR show cluster control information for DATADIR\n" +" -?, --help display this help and exit\n" +" -V, --version display pg_controldata's version and exit\n" +"\n" +msgstr "" +"Pou¾ití:\n" +" %s [PØEPÍNAÈ]\n" +"\n" +"Pøepínaèe:\n" +" ADRESÁØ uká¾e kontrolní informace pro ADRESÁØ\n" +" -?, --help uká¾e tuto nápovìdu a skonèí\n" +" -V, --version uká¾e verzi tohoto programu a skonèí\n" +"\n" + +#: pg_controldata.c:40 +#, c-format +msgid "%s displays PostgreSQL database cluster control information.\n" +msgstr "%s uká¾e kontrolní informace o PostgreSQL databázi.\n" + +#: pg_controldata.c:41 +msgid "" +"If no data directory is specified, the environment variable PGDATA\n" +"is used.\n" +"\n" +msgstr "" +"Není-li specifikován datový adresáø je pou¾ita promìnná prostøedí\n" +"PGDATA.\n" +"\n" + +#: pg_controldata.c:42 +msgid "Report bugs to .\n" +msgstr "Chyby posílejte do .\n" + +#: pg_controldata.c:52 +msgid "starting up" +msgstr "startování" + +#: pg_controldata.c:54 +msgid "shut down" +msgstr "ukonèení" + +#: pg_controldata.c:56 +msgid "shutting down" +msgstr "ukonèování" + +#: pg_controldata.c:58 +msgid "in recovery" +msgstr "obnovuje se" + +#: pg_controldata.c:60 +msgid "in production" +msgstr "v provozu" + +#: pg_controldata.c:62 +msgid "unrecognized status code" +msgstr "neoèekávaný stavový kód" + +#: pg_controldata.c:107 +#, c-format +msgid "%s: no data directory specified\n" +msgstr "%s: není specifikován datový adresáø\n" + +#: pg_controldata.c:108 +#, c-format +msgid "Try '%s --help' for more information.\n" +msgstr "Zkuste '%s --help' pro více informací.\n" + +#: pg_controldata.c:116 +#, c-format +msgid "%s: could not open file \"%s\" for reading (%s)\n" +msgstr "%s: nelze otevøít soubor \"%s\" pro ètení (%s)\n" + +#: pg_controldata.c:123 +#, c-format +msgid "%s: could not read file \"%s\" (%s)\n" +msgstr "%s: nelze èíst soubor \"%s\" (%s)\n" + +#: pg_controldata.c:137 +msgid "" +"WARNING: Calculated CRC checksum does not match value stored in file.\n" +"Either the file is corrupt, or it has a different layout than this program\n" +"is expecting. The results below are untrustworthy.\n" +"\n" +msgstr "" +"UPOZORNÌNÍ: Spoèítaný CRC kontrolní souèet nesouhlasí s hodnotou ulo¾enou v souboru.\n" +"Buï je soubor po¹kozen nebo má jinou úpravu ne¾ tento program\n" +"oèekává. Ní¾e uvedené výsledky jsou nedùvìryhodné.\n" +"\n" + +#: pg_controldata.c:150 +#, c-format +msgid "pg_control version number: %u\n" +msgstr "Èíslo verze pg_controlu: %u\n" + +#: pg_controldata.c:151 +#, c-format +msgid "Catalog version number: %u\n" +msgstr "Èíslo verze katalogu: %u\n" + +#: pg_controldata.c:152 +#, c-format +msgid "Database cluster state: %s\n" +msgstr "Status seskupení databáze: %s\n" + +#: pg_controldata.c:153 +#, c-format +msgid "pg_control last modified: %s\n" +msgstr "Poslední modifikace pg_controlu: %s\n" + +#: pg_controldata.c:154 +#, c-format +msgid "Current log file ID: %u\n" +msgstr "ID souèasného log souboru: %u\n" + +#: pg_controldata.c:155 +#, c-format +msgid "Next log file segment: %u\n" +msgstr "Následující segment log souboru: %u\n" + +#: pg_controldata.c:156 +#, c-format +msgid "Latest checkpoint location: %X/%X\n" +msgstr "Poslední umístìní kontrolního bodu: %X/%X\n" + +#: pg_controldata.c:158 +#, c-format +msgid "Prior checkpoint location: %X/%X\n" +msgstr "Pøede¹lé umístìní kontrolního bodu: %X/%X\n" + +#: pg_controldata.c:160 +#, c-format +msgid "Latest checkpoint's REDO location: %X/%X\n" +msgstr "Poslednìj¹í umístìní REDO kontrolního bodu: %X/%X\n" + +#: pg_controldata.c:162 +#, c-format +msgid "Latest checkpoint's UNDO location: %X/%X\n" +msgstr "Poslední umístìní UNDO kontrolního bodu: %X/%X\n" + +#: pg_controldata.c:164 +#, c-format +msgid "Latest checkpoint's StartUpID: %u\n" +msgstr "Poslední umístìní StartUpID kontrolního bodu: %u\n" + +#: pg_controldata.c:165 +#, c-format +msgid "Latest checkpoint's NextXID: %u\n" +msgstr "Poslední umístìní NextXID kontrolního bodu: %u\n" + +#: pg_controldata.c:166 +#, c-format +msgid "Latest checkpoint's NextOID: %u\n" +msgstr "Poslední umístìní NextOID kontrolního bodu: %u\n" + +#: pg_controldata.c:167 +#, c-format +msgid "Time of latest checkpoint: %s\n" +msgstr "Èas posledního kontrolního bodu: %s\n" + +#: pg_controldata.c:168 +#, c-format +msgid "Database block size: %u\n" +msgstr "Velikost databázového bloku: %u\n" + +#: pg_controldata.c:169 +#, c-format +msgid "Blocks per segment of large relation: %u\n" +msgstr "Blokù v segmentu velké relace: %u\n" + +#: pg_controldata.c:170 +#, c-format +msgid "Maximum length of identifiers: %u\n" +msgstr "Maximální délka identifikátorù: %u\n" + +#: pg_controldata.c:171 +#, c-format +msgid "Maximum number of function arguments: %u\n" +msgstr "Maximální poèet argumentù funkcí: %u\n" + +#: pg_controldata.c:172 +#, c-format +msgid "Date/time type storage: %s\n" +msgstr "Zpùsob ulo¾ení typu date/time: %s\n" + +#: pg_controldata.c:173 +msgid "64-bit integers" +msgstr "64-bitová èísla" + +#: pg_controldata.c:173 +msgid "Floating point" +msgstr "Plovoucí èárka" + +#: pg_controldata.c:174 +#, c-format +msgid "Maximum length of locale name: %u\n" +msgstr "Maximální délka jména locale: %u\n" + +#: pg_controldata.c:175 +#, c-format +msgid "LC_COLLATE: %s\n" +msgstr "LC_COLLATE (porovnávání øetìzcù): %s\n" + +#: pg_controldata.c:176 +#, c-format +msgid "LC_CTYPE: %s\n" +msgstr "LC_CTYPE (typy znakù): %s\n" + diff --git a/src/bin/pg_resetxlog/po/cs.po b/src/bin/pg_resetxlog/po/cs.po new file mode 100644 index 0000000..b73bdc5 --- /dev/null +++ b/src/bin/pg_resetxlog/po/cs.po @@ -0,0 +1,336 @@ +# Czech translation of pg_resetxlog messages +# Karel Zak , 2003. +# +# $Id$ +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 7.4\n" +"POT-Creation-Date: 2003-06-29 12:25+0200\n" +"PO-Revision-Date: 2003-07-13 00:04-0000\n" +"Last-Translator: Karel Zak \n" +"Language-Team: Karel ®ák \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#: pg_resetxlog.c:141 +#, c-format +msgid "%s: invalid argument for -x option\n" +msgstr "%s: neplatný parametr pro -x pøepínaè\n" + +#: pg_resetxlog.c:142 +#: pg_resetxlog.c:157 +#: pg_resetxlog.c:172 +#: pg_resetxlog.c:179 +#: pg_resetxlog.c:185 +#: pg_resetxlog.c:193 +#, c-format +msgid "Try '%s --help' for more information.\n" +msgstr "Zkuste '%s --help' pro více informací.\n" + +#: pg_resetxlog.c:147 +#, c-format +msgid "%s: transaction ID (-x) must not be 0\n" +msgstr "%s: ID transakce (-x) nesmí být 0\n" + +#: pg_resetxlog.c:156 +#, c-format +msgid "%s: invalid argument for -o option\n" +msgstr "%s: neplatný parametr pro -o pøepínaè\n" + +#: pg_resetxlog.c:162 +#, c-format +msgid "%s: OID (-o) must not be 0\n" +msgstr "%s: OID (-o) nesmí být 0\n" + +#: pg_resetxlog.c:171 +#: pg_resetxlog.c:178 +#, c-format +msgid "%s: invalid argument for -l option\n" +msgstr "%s: neplatný parametr pro -l pøepínaè\n" + +#: pg_resetxlog.c:192 +#, c-format +msgid "%s: no data directory specified\n" +msgstr "%s: není specifikován datový adresáø\n" + +#: pg_resetxlog.c:212 +#: pg_resetxlog.c:308 +#, c-format +msgid "%s: could not open %s for reading: %s\n" +msgstr "%s: nelze otevøít %s pro ètení: %s\n" + +#: pg_resetxlog.c:218 +#, c-format +msgid "" +"%s: lock file %s exists\n" +"Is a server running? If not, delete the lock file and try again.\n" +msgstr "" +"%s: soubor se zámkem %s existuje\n" +"Nebì¾í ji¾ server? Jestli¾e ne sma¾te soubor se zámkem a zkuste to znova.\n" + +#: pg_resetxlog.c:257 +msgid "" +"\n" +"If these values seem acceptable, use -f to force reset.\n" +msgstr "" +"\n" +"Jestli¾e tyto hodnoty vypadají akceptovatelnì, pou¾ijte -f pro vynucený reset.\n" + +#: pg_resetxlog.c:269 +msgid "" +"The database server was not shut down cleanly.\n" +"Resetting the transaction log may cause data to be lost.\n" +"If you want to proceed anyway, use -f to force reset.\n" +msgstr "" +"Databázový server nebyl ukonèen standardnì.\n" +"Resetování transakèního logu mù¾e být dùvodem ke ztrátì dat.\n" +"Jestli¾e to chcete i tak provést pou¾ijte -f pro vynucený reset.\n" + +#: pg_resetxlog.c:282 +msgid "Transaction log reset\n" +msgstr "Transakèní log resetován\n" + +#: pg_resetxlog.c:311 +#, c-format +msgid "" +"If you are sure the data directory path is correct, do\n" +" touch %s\n" +"and try again.\n" +msgstr "" +"Máte-li jistotu, ¾e jsou data v adresáøi korektní, proveïte\n" +" touch %s\n" +"a zkuste to znovu.\n" + +#: pg_resetxlog.c:324 +#, c-format +msgid "%s: could not read %s: %s\n" +msgstr "%s: nelze èíst %s: %s\n" + +#: pg_resetxlog.c:347 +#, c-format +msgid "%s: pg_control exists but has invalid CRC; proceed with caution\n" +msgstr "%s: pg_control existuje, ale s neplatným kontrolním souètem CRC; postupujte opatrnì\n" + +#: pg_resetxlog.c:356 +#, c-format +msgid "%s: pg_control exists but is broken or unknown version; ignoring it\n" +msgstr "%s: pg_control existuje, ale je po¹kozen nebo neznáme verze; ignoruji to\n" + +#: pg_resetxlog.c:407 +#, c-format +msgid "%s: invalid LC_COLLATE setting\n" +msgstr "%s: neplatné LC_COLLATE nastavení\n" + +#: pg_resetxlog.c:414 +#, c-format +msgid "%s: invalid LC_CTYPE setting\n" +msgstr "%s: neplatné LC_CTYPE nastavení\n" + +#: pg_resetxlog.c:436 +msgid "" +"Guessed pg_control values:\n" +"\n" +msgstr "" +"Odhadnuté hodnoty pg_controlu:\n" +"\n" + +#: pg_resetxlog.c:438 +msgid "" +"pg_control values:\n" +"\n" +msgstr "" +"Hodnoty pg_controlu:\n" +"\n" + +#: pg_resetxlog.c:440 +#, c-format +msgid "pg_control version number: %u\n" +msgstr "Èíslo verze pg_controlu: %u\n" + +#: pg_resetxlog.c:441 +#, c-format +msgid "Catalog version number: %u\n" +msgstr "Èíslo verze katalogu: %u\n" + +#: pg_resetxlog.c:442 +#, c-format +msgid "Current log file ID: %u\n" +msgstr "Souèasné ID log souboru: %u\n" + +#: pg_resetxlog.c:443 +#, c-format +msgid "Next log file segment: %u\n" +msgstr "Následující segment log souboru: %u\n" + +#: pg_resetxlog.c:444 +#, c-format +msgid "Latest checkpoint's StartUpID: %u\n" +msgstr "Poslední umístìní StartUpID kontrolního bodu: %u\n" + +#: pg_resetxlog.c:445 +#, c-format +msgid "Latest checkpoint's NextXID: %u\n" +msgstr "Poslední umístìní NextXID kontrolního bodu: %u\n" + +#: pg_resetxlog.c:446 +#, c-format +msgid "Latest checkpoint's NextOID: %u\n" +msgstr "Poslední umístìní NextOID kontrolního bodu: %u\n" + +#: pg_resetxlog.c:447 +#, c-format +msgid "Database block size: %u\n" +msgstr "Velikost databázového bloku: %u\n" + +#: pg_resetxlog.c:448 +#, c-format +msgid "Blocks per segment of large relation: %u\n" +msgstr "Blokù v segmentu velké relace: %u\n" + +#: pg_resetxlog.c:449 +#, c-format +msgid "Maximum length of identifiers: %u\n" +msgstr "Maximální délka identifikátorù: %u\n" + +#: pg_resetxlog.c:450 +#, c-format +msgid "Maximum number of function arguments: %u\n" +msgstr "Maximální poèet argumentù funkcí: %u\n" + +#: pg_resetxlog.c:451 +#, c-format +msgid "Date/time type storage: %s\n" +msgstr "Zpùsob ulo¾ení typu date/time: %s\n" + +#: pg_resetxlog.c:452 +msgid "64-bit integers" +msgstr "64-bitová èísla" + +#: pg_resetxlog.c:452 +msgid "Floating point" +msgstr "Plovoucí èárka" + +#: pg_resetxlog.c:453 +#, c-format +msgid "Maximum length of locale name: %u\n" +msgstr "Maximální délka jména locale: %u\n" + +#: pg_resetxlog.c:454 +#, c-format +msgid "LC_COLLATE: %s\n" +msgstr "LC_COLLATE (porovnávání øetìzcù): %s\n" + +#: pg_resetxlog.c:455 +#, c-format +msgid "LC_CTYPE: %s\n" +msgstr "LC_CTYPE (typy znakù): %s\n" + +#: pg_resetxlog.c:508 +#, c-format +msgid "%s: internal error -- sizeof(ControlFileData) is too large ... fix xlog.c\n" +msgstr "%s: interní chyba -- sizeof(ControlFileData) je pøíli¹ velký ... opravte xlog.c\n" + +#: pg_resetxlog.c:521 +#, c-format +msgid "%s: could not create pg_control file: %s\n" +msgstr "%s: nelze vytvoøit pg_control soubor: %s\n" + +#: pg_resetxlog.c:532 +#, c-format +msgid "%s: could not write pg_control file: %s\n" +msgstr "%s: nelze zapsat pg_control soubor: %s\n" + +#: pg_resetxlog.c:539 +#: pg_resetxlog.c:680 +#, c-format +msgid "%s: fsync error: %s\n" +msgstr "%s: fsync chyba: %s\n" + +#: pg_resetxlog.c:560 +#, c-format +msgid "%s: could not open directory %s: %s\n" +msgstr "%s: nelze otevøít adresáø %s: %s\n" + +#: pg_resetxlog.c:574 +#, c-format +msgid "%s: could not delete file %s: %s\n" +msgstr "%s: nelze smazat soubor %s: %s\n" + +#: pg_resetxlog.c:584 +#, c-format +msgid "%s: could not read from directory %s: %s\n" +msgstr "%s: nelze èíst z adresáøe %s: %s\n" + +#: pg_resetxlog.c:647 +#, c-format +msgid "%s: could not open %s: %s\n" +msgstr "%s: nelze otevøít %s: %s\n" + +#: pg_resetxlog.c:658 +#: pg_resetxlog.c:672 +#, c-format +msgid "%s: could not write %s: %s\n" +msgstr "%s: nelze zapsat %s: %s\n" + +#: pg_resetxlog.c:691 +#, c-format +msgid "" +"%s resets the PostgreSQL transaction log.\n" +"\n" +msgstr "" +"%s resetuji PostgreSQL transakèní log.\n" +"\n" + +#: pg_resetxlog.c:692 +#, c-format +msgid "" +"Usage:\n" +" %s [OPTION]... DATADIR\n" +"\n" +msgstr "" +"Pou¾ití:\n" +" %s [PØEPÍNAÈ]... ADRESÁØ\n" +"\n" + +#: pg_resetxlog.c:693 +msgid "Options:\n" +msgstr "Pøepínaèe:\n" + +#: pg_resetxlog.c:694 +msgid " -f force update to be done\n" +msgstr " -f provede vynucený update\n" + +#: pg_resetxlog.c:695 +msgid " -l FILEID,SEG force minimum WAL starting location for new transaction log\n" +msgstr " -l FILEID,SEG vynutí minimální poèáteèní WAL pozici pro novou transakèní log\n" + +#: pg_resetxlog.c:696 +msgid " -n no update, just show extracted control values (for testing)\n" +msgstr " -n bez zmìny, jen uká¾e získané kontrolní hodnoty (pro testování)\n" + +#: pg_resetxlog.c:697 +msgid " -o OID set next OID\n" +msgstr " -o OID nastaví následující OID\n" + +#: pg_resetxlog.c:698 +msgid " -x XID set next transaction ID\n" +msgstr " -x XID nastaví následující ID transakce\n" + +#: pg_resetxlog.c:699 +msgid " --help show this help, then exit\n" +msgstr " --help uká¾e tuto nápovìdu a skonèí\n" + +#: pg_resetxlog.c:700 +msgid " --version output version information, then exit\n" +msgstr " --version uká¾e informace o verzi a skonèí\n" + +#: pg_resetxlog.c:701 +msgid "" +"\n" +"Report bugs to .\n" +msgstr "" +"\n" +"Chybová hlá¹ení posílejte do .\n" + diff --git a/src/bin/scripts/po/cs.po b/src/bin/scripts/po/cs.po new file mode 100644 index 0000000..b79dd0f --- /dev/null +++ b/src/bin/scripts/po/cs.po @@ -0,0 +1,680 @@ +# Czech translation of pg_scripts messages. +# Karel Zak , 2003. +# +# $Id$ +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 7.4\n" +"POT-Creation-Date: 2003-06-29 12:25+0200\n" +"PO-Revision-Date: 2003-07-22 13:44+0100\n" +"Last-Translator: Karel Zak \n" +"Language-Team: Karel Zak \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#: createdb.c:101 +#: createdb.c:120 +#: createlang.c:94 +#: createlang.c:115 +#: createlang.c:157 +#: createuser.c:116 +#: createuser.c:131 +#: dropdb.c:83 +#: dropdb.c:92 +#: dropdb.c:100 +#: droplang.c:88 +#: droplang.c:109 +#: droplang.c:151 +#: dropuser.c:83 +#: dropuser.c:98 +#: clusterdb.c:94 +#: clusterdb.c:109 +#: vacuumdb.c:110 +#: vacuumdb.c:125 +#, c-format +msgid "Try '%s --help' for more information.\n" +msgstr "Zkuste '%s --help' pro více informací.\n" + +#: createdb.c:118 +#: createlang.c:113 +#: createuser.c:129 +#: dropdb.c:98 +#: dropuser.c:96 +#: clusterdb.c:107 +#: vacuumdb.c:123 +#, c-format +msgid "%s: too many command-line arguments (first is '%s')\n" +msgstr "%s: pøíli¹ mnoho parametrù pøíkazové øádky (první je '%s')\n" + +#: createdb.c:128 +#, c-format +msgid "%s: \"%s\" is not a valid encoding name\n" +msgstr "%s: \"%s\" není platné jméno kódování\n" + +#: createdb.c:170 +#, c-format +msgid "%s: database creation failed: %s" +msgstr "%s: tvorba databáze selhala: %s" + +#: createdb.c:195 +#, c-format +msgid "%s: comment creation failed (database was created): %s" +msgstr "%s: tvorba komentáøe selhala (databáze byla vytvoøena): %s" + +#: createdb.c:213 +#, c-format +msgid "" +"%s creates a PostgreSQL database.\n" +"\n" +msgstr "" +"%s tvoøí PostgreSQL databázi.\n" +"\n" + +#: createdb.c:214 +#: createlang.c:272 +#: createuser.c:235 +#: dropdb.c:143 +#: droplang.c:241 +#: dropuser.c:143 +#: clusterdb.c:228 +#: vacuumdb.c:252 +msgid "Usage:\n" +msgstr "Pou¾ití:\n" + +#: createdb.c:215 +#, c-format +msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" +msgstr " %s [PØEPÍNAÈ]... [DATABÁZE] [POPISKA]\n" + +#: createdb.c:216 +#: createlang.c:274 +#: createuser.c:237 +#: dropdb.c:145 +#: droplang.c:243 +#: dropuser.c:145 +#: clusterdb.c:230 +#: vacuumdb.c:254 +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Pøepínaè:\n" + +#: createdb.c:217 +msgid " -D, --location=PATH alternative place to store the database\n" +msgstr " -D, --location=CESTA alternativní místo na ulo¾ení databáze\n" + +#: createdb.c:218 +msgid " -E, --encoding=ENCODING encoding for the database\n" +msgstr " -E, --encoding=KÓDOVÁNÍ kódování databáze\n" + +#: createdb.c:219 +msgid " -O, --owner=OWNER database user to own the new database\n" +msgstr " -O, --owner=VLASTNÍK u¾ivatel databáze, který má být vlastníkem nové databáze\n" + +#: createdb.c:220 +msgid " -T, --template=TEMPLATE template database to copy\n" +msgstr " -T, --template=©ABLONA ¹ablona databáze ke kopírování\n" + +#: createdb.c:221 +#: createlang.c:276 +#: createuser.c:246 +#: dropdb.c:146 +#: droplang.c:245 +#: dropuser.c:146 +#: clusterdb.c:234 +msgid " -e, --echo show the commands being sent to the server\n" +msgstr " -e, --echo ukazovat pøíkazy posílané na server\n" + +#: createdb.c:222 +#: createuser.c:247 +#: dropdb.c:148 +#: dropuser.c:148 +#: clusterdb.c:235 +msgid " -q, --quiet don't write any messages\n" +msgstr " -q, --quiet tichý mód\n" + +#: createdb.c:223 +#: createlang.c:283 +#: createuser.c:248 +#: dropdb.c:153 +#: droplang.c:251 +#: dropuser.c:153 +#: clusterdb.c:236 +msgid " --help show this help, then exit\n" +msgstr " --help uká¾e tuto nápovìdu a skonèí\n" + +#: createdb.c:224 +#: createlang.c:284 +#: createuser.c:249 +#: dropdb.c:154 +#: droplang.c:252 +#: dropuser.c:154 +#: clusterdb.c:237 +msgid " --version output version information, then exit\n" +msgstr " --version uká¾e informaci o verzi a skonèí\n" + +#: createdb.c:225 +#: createuser.c:250 +#: clusterdb.c:238 +#: vacuumdb.c:265 +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Parametry spojení:\n" + +#: createdb.c:226 +#: createlang.c:279 +#: createuser.c:251 +#: dropdb.c:149 +#: droplang.c:247 +#: dropuser.c:149 +#: clusterdb.c:239 +#: vacuumdb.c:266 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME jméno databázového serveru nebo adresáøe se soketem\n" + +#: createdb.c:227 +#: createlang.c:280 +#: createuser.c:252 +#: dropdb.c:150 +#: droplang.c:248 +#: dropuser.c:150 +#: clusterdb.c:240 +#: vacuumdb.c:267 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PORT port databázového serveru\n" + +#: createdb.c:228 +#: createlang.c:281 +#: dropdb.c:151 +#: droplang.c:249 +#: clusterdb.c:241 +#: vacuumdb.c:268 +msgid " -U, --username=USERNAME user name to connect as\n" +msgstr " -U, --username=U®IVATEL jméno u¾ivatele pro spojení se serverem\n" + +#: createdb.c:229 +#: createlang.c:282 +#: dropdb.c:152 +#: droplang.c:250 +#: clusterdb.c:242 +#: vacuumdb.c:269 +msgid " -W, --password prompt for password\n" +msgstr " -W, --password dotaz na heslo\n" + +#: createdb.c:230 +msgid "" +"\n" +"By default, a database with the same name as the current user is created.\n" +msgstr "" +"\n" +"Implicitnì je vytvoøena databáze stejného jména jako je jméno aktuálního u¾ivatele.\n" + +#: createdb.c:231 +#: createlang.c:285 +#: createuser.c:257 +#: dropdb.c:155 +#: droplang.c:253 +#: dropuser.c:155 +#: clusterdb.c:244 +#: vacuumdb.c:271 +msgid "" +"\n" +"Report bugs to .\n" +msgstr "" +"\n" +"Chyby posílejte do .\n" + +#: createlang.c:140 +#: droplang.c:134 +msgid "Name" +msgstr "Jméno" + +#: createlang.c:140 +#: droplang.c:134 +msgid "yes" +msgstr "ano" + +#: createlang.c:140 +#: droplang.c:134 +msgid "no" +msgstr "ne" + +#: createlang.c:140 +#: droplang.c:134 +msgid "Trusted?" +msgstr "Dùvìrný?" + +#: createlang.c:147 +#: droplang.c:141 +msgid "Procedural Languages" +msgstr "Procedurální jazyky" + +#: createlang.c:156 +#: droplang.c:150 +#, c-format +msgid "%s: missing required argument language name\n" +msgstr "%s: chybí povinný parametr jméno jazyka\n" + +#: createlang.c:206 +#, c-format +msgid "%s: unsupported language \"%s\"\n" +msgstr "%s: nepodporovaný jazyk \"%s\"\n" + +#: createlang.c:207 +msgid "Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and plpythonu.\n" +msgstr "Podporované jazyky jsou plpgsql, pltcl, pltclu, plperl, plperlu a plpythonu.\n" + +#: createlang.c:222 +#, c-format +msgid "%s: language \"%s\" is already installed in database \"%s\"\n" +msgstr "%s: jazyk \"%s\" je ji¾ v databázi \"%s\" instalován\n" + +#: createlang.c:256 +#, c-format +msgid "%s: language installation failed: %s" +msgstr "%s: instalace jazyka selhala: %s" + +#: createlang.c:271 +#, c-format +msgid "" +"%s installs a procedural language into a PostgreSQL database.\n" +"\n" +msgstr "" +"%s instaluji procedurální jazyk do PostgreSQL databáze.\n" +"\n" + +#: createlang.c:273 +#: droplang.c:242 +#, c-format +msgid " %s [OPTION]... LANGNAME [DBNAME]\n" +msgstr " %s [PØEPÍNAÈ]... JAZYK [DATABÁZE]\n" + +#: createlang.c:275 +#: droplang.c:244 +msgid " -d, --dbname=DBNAME database to install language in\n" +msgstr " -d, --dbname=DATABÁZE databáze do které bude instalován jazyka\n" + +#: createlang.c:277 +#: droplang.c:246 +msgid " -l, --list show a list of currently installed languages\n" +msgstr " -l, --list uká¾e seznam ji¾ nainstalovaných jazykù\n" + +#: createlang.c:278 +msgid " -L, --pglib=DIRECTORY find language interpreter file in DIRECTORY\n" +msgstr " -L, --pglib=ADRESÁØ adresáø s interpretrem jazyka\n" + +#: createuser.c:141 +#, c-format +msgid "%s: user ID must be a positive number\n" +msgstr "%s: ID u¾ivatele musí být kladné èíslo\n" + +#: createuser.c:147 +msgid "Enter name of user to add: " +msgstr "Vlo¾te jméno nového u¾ivatele: " + +#: createuser.c:153 +msgid "Enter password for new user: " +msgstr "Vlo¾te heslo nového u¾ivatele: " + +#: createuser.c:154 +msgid "Enter it again: " +msgstr "Zadejte znova: " + +#: createuser.c:157 +msgid "Passwords didn't match.\n" +msgstr "Heslo se neshoduje.\n" + +#: createuser.c:168 +msgid "Shall the new user be allowed to create databases? (y/n) " +msgstr "Mìl by mít nový u¾ivatel právo vytváøet databáze? (y/n) " + +#: createuser.c:179 +msgid "Shall the new user be allowed to create more new users? (y/n) " +msgstr "Mìl by mít nový u¾ivatel právo vytváøet dal¹í nové u¾ivatele? (y/n) " + +#: createuser.c:218 +#, c-format +msgid "%s: creation of new user failed: %s" +msgstr "%s: tvorba nového u¾ivatele selhala: %s" + +#: createuser.c:234 +#, c-format +msgid "" +"%s creates a new PostgreSQL user.\n" +"\n" +msgstr "" +"%s tvoøí nového PostgreSQL u¾ivatele.\n" +"\n" + +#: createuser.c:236 +#: dropuser.c:144 +#, c-format +msgid " %s [OPTION]... [USERNAME]\n" +msgstr " %s [PØEPÍNAÈ]... [U®IVATELSKÉ_JMÉNO]\n" + +#: createuser.c:238 +msgid " -a, --adduser user can add new users\n" +msgstr " -a, --adduser u¾ivatel mù¾e pøidávat dal¹í u¾ivatele\n" + +#: createuser.c:239 +msgid " -A, --no-adduser user cannot add new users\n" +msgstr " -A, --no-adduser u¾ivatel nemù¾e pøidávat dal¹í u¾ivatele\n" + +#: createuser.c:240 +msgid " -d, --createdb user can create new databases\n" +msgstr " -d, --createdb u¾ivatel mù¾e vytváøet nové databáze\n" + +#: createuser.c:241 +msgid " -D, --no-createdb user cannot create databases\n" +msgstr " -D, --no-createdb u¾ivatel nemù¾e vytváøet nové databáze\n" + +#: createuser.c:242 +msgid " -P, --pwprompt assign a password to new user\n" +msgstr " -P, --pwprompt nastavit heslo pro nového u¾ivatele\n" + +#: createuser.c:243 +msgid " -E, --encrypted encrypt stored password\n" +msgstr " -E, --encrypted ulo¾it heslo v za¹ifrované podobì\n" + +#: createuser.c:244 +msgid " -N, --unencrypted do no encrypt stored password\n" +msgstr " -N, --unencrypted ulo¾it heslo v otevøeném tvaru\n" + +#: createuser.c:245 +msgid " -i, --sysid=SYSID select sysid for new user\n" +msgstr " -i, --sysid=SYSID nastavit systémové ID nového u¾ivatele\n" + +#: createuser.c:253 +msgid " -U, --username=USERNAME user name to connect as (not the one to create)\n" +msgstr " -U, --username=U®IVATEL jméno u¾ivatele pro spojení (ne pro tvorbu)\n" + +#: createuser.c:254 +#: dropuser.c:152 +msgid " -W, --password prompt for password to connect\n" +msgstr " -W, --password dotázat se na heslo pro spojení\n" + +#: createuser.c:255 +msgid "" +"\n" +"If one of -a, -A, -d, -D, and USERNAME is not specified, you will\n" +"be prompted interactively.\n" +msgstr "" +"\n" +"Je-li -a, -A, -d nebo -D specifikováno a u¾ivatelské jméno ne, bude\n" +"dotázán interaktivnì.\n" + +#: dropdb.c:91 +#, c-format +msgid "%s: missing required argument database name\n" +msgstr "%s: chybí vy¾adovaný parametr databázové jméno\n" + +#: dropdb.c:108 +#, c-format +msgid "Database \"%s\" will be permanently deleted.\n" +msgstr "Databáze \"%s\" bude odstranìna.\n" + +#: dropdb.c:109 +#: dropuser.c:110 +msgid "Are you sure? (y/n) " +msgstr "Urèitì? (a/n) " + +#: dropdb.c:126 +#, c-format +msgid "%s: database removal failed: %s" +msgstr "%s: odstraòování databáze selhalo: %s" + +#: dropdb.c:142 +#, c-format +msgid "" +"%s removes a PostgreSQL database.\n" +"\n" +msgstr "" +"%s odstraòuje PostgreSQL databázi.\n" +"\n" + +#: dropdb.c:144 +#, c-format +msgid " %s [OPTION]... DBNAME\n" +msgstr " %s [PØEPÍNAÈ]... DATABÁZE\n" + +#: dropdb.c:147 +#: dropuser.c:147 +msgid " -i, --interactive prompt before deleting anything\n" +msgstr " -i, --interactive interaktivní mód\n" + +#: droplang.c:107 +#, c-format +msgid "%s: too many command line options (first is '%s')\n" +msgstr "%s: pøíli¹ mnoho pøepínaèù pøíkazové øádky (první je '%s')\n" + +#: droplang.c:169 +#, c-format +msgid "%s: language \"%s\" is not installed in database \"%s\"\n" +msgstr "%s: jazyk \"%s\" není instalován v databázi \"%s\"\n" + +#: droplang.c:185 +#, c-format +msgid "%s: There are %s functions declared in language \"%s\". Language not removed.\n" +msgstr "%s: Je definována funkce %s v jazyce \"%s\". Jazyk nemù¾e být odstranìn.\n" + +#: droplang.c:226 +#, c-format +msgid "%s: language removal failed: %s" +msgstr "%s: odstraòování jazyka selhalo: %s" + +#: droplang.c:240 +#, c-format +msgid "" +"%s removes a procedural language from a database.\n" +"\n" +msgstr "" +"%s odstraòuje procedurální jazyk z databáze.\n" +"\n" + +#: dropuser.c:103 +msgid "Enter name of user to drop: " +msgstr "Vlo¾te u¾ivatelské jméno pro odstranìní: " + +#: dropuser.c:109 +#, c-format +msgid "User \"%s\" will be permanently deleted.\n" +msgstr "U¾ivatel \"%s\" bude odstranìn.\n" + +#: dropuser.c:126 +#, c-format +msgid "%s: deletion of user %s failed: %s" +msgstr "%s: odstraòování u¾ivatele %s selhalo: %s" + +#: dropuser.c:142 +#, c-format +msgid "" +"%s removes a PostgreSQL user.\n" +"\n" +msgstr "" +"%s odstraòuje PostgreSQL u¾ivatele.\n" +"\n" + +#: dropuser.c:151 +msgid " -U, --username=USERNAME user name to connect as (not the one to drop)\n" +msgstr " -U, --username=U®IVATEL jméno u¾ivatele pro spojení (ne pro odstranìní)\n" + +#: clusterdb.c:117 +#, c-format +msgid "%s: cannot cluster all databases and a specific one at the same time\n" +msgstr "%s: nelze vytvoøit cluster ve v¹ech databázích a zároveò specifikovat jen jednu\n" + +#: clusterdb.c:123 +#, c-format +msgid "%s: cannot cluster a specific table in all databases\n" +msgstr "%s: nelze vytvoøit cluster pro po¾adovanou tabulku ve v¹ech databázích\n" + +#: clusterdb.c:178 +#, c-format +msgid "%s: clustering of table \"%s\" in database \"%s\" failed: %s" +msgstr "%s: vytváøení clusteru tabulky \"%s\" v databázi \"%s\" selhalo: %s" + +#: clusterdb.c:181 +#, c-format +msgid "%s: clustering of database \"%s\" failed: %s" +msgstr "%s: vytváøení clusterù databáze \"%s\" selhalo: %s" + +#: clusterdb.c:213 +#, c-format +msgid "%s: clustering database \"%s\"\n" +msgstr "%s: provádí se cluster databáze \"%s\"\n" + +#: clusterdb.c:227 +#, c-format +msgid "%s clusters all previously clustered tables in a database.\n" +msgstr "%s vytváøí cluster v¹ech ji¾ døíve clusterovaných tabulek v databázi.\n" + +#: clusterdb.c:229 +#: vacuumdb.c:253 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [PØEPÍNAÈ]... [DATABÁZE]\n" + +#: clusterdb.c:231 +msgid " -a, --all cluster all databases\n" +msgstr " -a, --all clusterovat v¹echny databáze\n" + +#: clusterdb.c:232 +msgid " -d, --dbname=DBNAME database to cluster\n" +msgstr " -d, --dbname=DATABÁZE databáze pro cluster\n" + +#: clusterdb.c:233 +msgid " -t, --table=TABLE cluster specific table only" +msgstr " -t, --table=TABULKA vytvoøit cluster pro danou tabulku" + +#: clusterdb.c:243 +msgid "" +"\n" +"Read the description of the SQL command CLUSTER for details.\n" +msgstr "" +"\n" +"Pro detaily ètìte popis SQL pøíkazu CLUSTER.\n" + +#: vacuumdb.c:133 +#, c-format +msgid "%s: cannot vacuum all databases and a specific one at the same time\n" +msgstr "%s: nelze provádìt vacuum u v¹ech databází a zároveò specifikovat jen jednu\n" + +#: vacuumdb.c:139 +#, c-format +msgid "%s: cannot vacuum a specific table in all databases\n" +msgstr "%s: nelze provést vacuum specifikované tabulky ve v¹ech databázích\n" + +#: vacuumdb.c:201 +#, c-format +msgid "%s: vacuuming of table \"%s\" in database \"%s\" failed: %s" +msgstr "%s: provádìné vacuum tabulky \"%s\" v databázi \"%s\" selhalo: %s" + +#: vacuumdb.c:204 +#, c-format +msgid "%s: vacuuming of database \"%s\" failed: %s" +msgstr "%s: provádìné vacuum databáze \"%s\" selhalo: %s" + +#: vacuumdb.c:237 +#, c-format +msgid "%s: vacuuming database \"%s\"\n" +msgstr "%s: provádí se vacuum databáze \"%s\"\n" + +#: vacuumdb.c:251 +#, c-format +msgid "" +"%s cleans and analyzes a PostgreSQL database.\n" +"\n" +msgstr "" +"%s proèi¹»uje a analyzuje a PostgreSQL databáze.\n" +"\n" + +#: vacuumdb.c:255 +msgid " -a, --all vacuum all databases\n" +msgstr " -a, --all provést vacuum u v¹ech databází\n" + +#: vacuumdb.c:256 +msgid " -d, --dbname=DBNAME database to vacuum\n" +msgstr " -d, --dbname=DATABÁZE jméno databáze k provedení pøíkazu vacuum\n" + +#: vacuumdb.c:257 +msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n" +msgstr " -t, --table='TABULKA[(SLOUPCE)]' provést vacuum pouze u specifikované tabulky\n" + +#: vacuumdb.c:258 +msgid " -f, --full do full vacuuming\n" +msgstr " -f, --full provést plné vacuum\n" + +#: vacuumdb.c:259 +msgid " -z, --analyze update optimizer hints\n" +msgstr " -z, --analyze update informací pou¾ívaných pro optimalizaci dotazù\n" + +#: vacuumdb.c:260 +msgid " -e, --echo show the commands being sent to the server\n" +msgstr " -e, --echo ukázat pøíkazy posílané na server\n" + +#: vacuumdb.c:261 +msgid " -q, --quiet don't write any messages\n" +msgstr " -q, --quiet tichý mód\n" + +#: vacuumdb.c:262 +msgid " -v, --verbose write a lot of output\n" +msgstr " -v, --verbose vypisovat více informací\n" + +#: vacuumdb.c:263 +msgid " --help show this help, then exit\n" +msgstr " --help uká¾e tento text a skonèí\n" + +#: vacuumdb.c:264 +msgid " --version output version information, then exit\n" +msgstr " --version uká¾e informace o verzi a skonèí\n" + +#: vacuumdb.c:270 +msgid "" +"\n" +"Read the description of the SQL command VACUUM for details.\n" +msgstr "" +"\n" +"Pro detaily ètìte popis SQL pøíkazu VACUUM.\n" + +#: common.c:88 +#: common.c:114 +msgid "Password: " +msgstr "Heslo: " + +#: common.c:101 +#, c-format +msgid "%s: could not connect to database %s\n" +msgstr "%s: nelze navázat spojení s databází %s\n" + +#: common.c:124 +#, c-format +msgid "%s: could not connect to database %s: %s" +msgstr "%s: nelze navázat spojení s databází %s: %s" + +#: common.c:148 +#, c-format +msgid "%s: query failed: %s" +msgstr "%s: dotaz selhal: %s" + +#: common.c:149 +#, c-format +msgid "%s: query was: %s\n" +msgstr "%s: dotaz byls: %s\n" + +#. translator: Make sure the (y/n) prompts match the translation of this. +#: common.c:163 +msgid "y" +msgstr "a" + +#. translator: Make sure the (y/n) prompts match the translation of this. +#: common.c:165 +msgid "n" +msgstr "n" + diff --git a/src/bin/scripts/po/sv.po b/src/bin/scripts/po/sv.po new file mode 100644 index 0000000..1d5b86d --- /dev/null +++ b/src/bin/scripts/po/sv.po @@ -0,0 +1,577 @@ +# Swedish message translation file for postgresql +# Dennis Björklund , 2003. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 7.4\n" +"POT-Creation-Date: 2003-08-09 04:49-0300\n" +"PO-Revision-Date: 2003-08-09 15:47+0200\n" +"Last-Translator: Dennis Björklund \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: clusterdb.c:96 clusterdb.c:111 createdb.c:101 createdb.c:120 +#: createlang.c:94 createlang.c:115 createlang.c:157 createuser.c:116 +#: createuser.c:131 dropdb.c:83 dropdb.c:92 dropdb.c:100 droplang.c:88 +#: droplang.c:109 droplang.c:151 dropuser.c:83 dropuser.c:98 vacuumdb.c:112 +#: vacuumdb.c:127 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Försök med \"%s --help\" för mer information.\n" + +#: clusterdb.c:109 createdb.c:118 createlang.c:113 createuser.c:129 +#: dropdb.c:98 droplang.c:107 dropuser.c:96 vacuumdb.c:125 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: för många kommandoradsargument (första är \"%s\")\n" + +#: createdb.c:128 +#, c-format +msgid "%s: \"%s\" is not a valid encoding name\n" +msgstr "%s: \"%s\" är inte ett giltigt kodningsnamn\n" + +#: createdb.c:170 +#, c-format +msgid "%s: database creation failed: %s" +msgstr "%s: skapande av databas misslyckades: %s" + +#: createdb.c:195 +#, c-format +msgid "%s: comment creation failed (database was created): %s" +msgstr "%s: skapande av kommentar misslyckades (databasen skapades): %s" + +#: createdb.c:213 +#, c-format +msgid "" +"%s creates a PostgreSQL database.\n" +"\n" +msgstr "%s skapar en PostgreSQL-databas.\n\n" + +#: clusterdb.c:232 createdb.c:214 createlang.c:272 createuser.c:236 +#: dropdb.c:143 droplang.c:242 dropuser.c:143 vacuumdb.c:256 +msgid "Usage:\n" +msgstr "Användning:\n" + +#: createdb.c:215 +#, c-format +msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" +msgstr " %s [FLAGGA]... [DBNAMN] [BESKRIVNING]\n" + +#: clusterdb.c:234 createdb.c:216 createlang.c:274 createuser.c:238 +#: dropdb.c:145 droplang.c:244 dropuser.c:145 vacuumdb.c:258 +msgid "" +"\n" +"Options:\n" +msgstr "\nFlaggor:\n" + +#: createdb.c:217 +msgid " -D, --location=PATH alternative place to store the database\n" +msgstr " -D, --location=SÖKVÄG alternativ plats att lagra databasen på\n" + +#: createdb.c:218 +msgid " -E, --encoding=ENCODING encoding for the database\n" +msgstr " -E, --encoding=ENCODING teckenkodning för databasen\n" + +#: createdb.c:219 +msgid " -O, --owner=OWNER database user to own the new database\n" +msgstr " -O, --owner=ÄGARE databasanvändare som blir ägare till databasen\n" + +#: createdb.c:220 +msgid " -T, --template=TEMPLATE template database to copy\n" +msgstr " -T, --template=MALL databasmall att kopiera från\n" + +#: clusterdb.c:238 createdb.c:221 createlang.c:276 createuser.c:247 +#: dropdb.c:146 droplang.c:246 dropuser.c:146 +msgid "" +" -e, --echo show the commands being sent to the server\n" +msgstr " -e, --echo visa kommandon som skickas till servern\n" + +#: clusterdb.c:239 createdb.c:222 createuser.c:248 dropdb.c:148 dropuser.c:148 +msgid " -q, --quiet don't write any messages\n" +msgstr " -q, --quiet skriv inte ut några meddelanden\n" + +#: clusterdb.c:240 createdb.c:223 createlang.c:283 createuser.c:249 +#: dropdb.c:153 droplang.c:252 dropuser.c:153 +msgid " --help show this help, then exit\n" +msgstr " --help visa denna hjälpen, avsluta sedan\n" + +#: clusterdb.c:241 createdb.c:224 createlang.c:284 createuser.c:250 +#: dropdb.c:154 droplang.c:253 dropuser.c:154 +msgid " --version output version information, then exit\n" +msgstr " --version visa versionsinformation, avsluta sedan\n" + +#: clusterdb.c:242 createdb.c:225 createuser.c:251 vacuumdb.c:269 +msgid "" +"\n" +"Connection options:\n" +msgstr "\nAnslutningsflaggor:\n" + +#: clusterdb.c:243 createdb.c:226 createlang.c:279 createuser.c:252 +#: dropdb.c:149 droplang.c:248 dropuser.c:149 vacuumdb.c:270 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller uttag(socket)-katalog\n" + +#: clusterdb.c:244 createdb.c:227 createlang.c:280 createuser.c:253 +#: dropdb.c:150 droplang.c:249 dropuser.c:150 vacuumdb.c:271 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PORT databasens serverport\n" + +#: clusterdb.c:245 createdb.c:228 createlang.c:281 dropdb.c:151 droplang.c:250 +#: vacuumdb.c:272 +msgid " -U, --username=USERNAME user name to connect as\n" +msgstr " -U, --username=ANVÄNDARE användarnamn att koppla upp som\n" + +#: clusterdb.c:246 createdb.c:229 createlang.c:282 dropdb.c:152 droplang.c:251 +#: vacuumdb.c:273 +msgid " -W, --password prompt for password\n" +msgstr " -W, --password fråga efter lösenord\n" + +#: createdb.c:230 +msgid "" +"\n" +"By default, a database with the same name as the current user is created.\n" +msgstr "\nSom standard så skapas en databas med samma namn som det aktuella användarnamnet.\n" + +#: clusterdb.c:248 createdb.c:231 createlang.c:285 createuser.c:258 +#: dropdb.c:155 droplang.c:254 dropuser.c:155 vacuumdb.c:275 +msgid "" +"\n" +"Report bugs to .\n" +msgstr "\nRapportera buggar till .\n" + +#: createlang.c:140 droplang.c:134 +msgid "Name" +msgstr "Namn" + +#: createlang.c:140 droplang.c:134 +msgid "yes" +msgstr "ja" + +#: createlang.c:140 droplang.c:134 +msgid "no" +msgstr "nej" + +#: createlang.c:140 droplang.c:134 +msgid "Trusted?" +msgstr "Litas på?" + +#: createlang.c:147 droplang.c:141 +msgid "Procedural Languages" +msgstr "Procedurspråk" + +#: createlang.c:156 droplang.c:150 +#, c-format +msgid "%s: missing required argument language name\n" +msgstr "%s: saknar språknamnsargument som krävs\n" + +#: createlang.c:206 +#, c-format +msgid "%s: unsupported language \"%s\"\n" +msgstr "%s: stödjer inte språk \"%s\"\n" + +#: createlang.c:207 +msgid "" +"Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and " +"plpythonu.\n" +msgstr "Språk som stöds är plpgsql, pltcl, plperl, plperlu och plpythonu.\n" + +#: createlang.c:222 +#, c-format +msgid "%s: language \"%s\" is already installed in database \"%s\"\n" +msgstr "%s: språket \"%s\" är redan installerat i databasen \"%s\"\n" + +#: createlang.c:256 +#, c-format +msgid "%s: language installation failed: %s" +msgstr "%s: språkinstallation misslyckades: %s" + +#: createlang.c:271 +#, c-format +msgid "" +"%s installs a procedural language into a PostgreSQL database.\n" +"\n" +msgstr "%s installerar ett procedurspråk i en PostgreSQL-databas.\n\n" + +#: createlang.c:273 droplang.c:243 +#, c-format +msgid " %s [OPTION]... LANGNAME [DBNAME]\n" +msgstr " %s [FLAGGA]... SPRÅK [DBNAMN]\n" + +#: createlang.c:275 +msgid " -d, --dbname=DBNAME database to install language in\n" +msgstr " -d, --dbname=DBNAMN databas att installera språk i\n" + +#: createlang.c:277 droplang.c:247 +msgid "" +" -l, --list show a list of currently installed languages\n" +msgstr " -l, --list lista språk som är installerade nu\n" + +#: createlang.c:278 +msgid "" +" -L, --pglib=DIRECTORY find language interpreter file in DIRECTORY\n" +msgstr " -L, --pglib=KATALOG hitta språkinterpretator i KATALOG\n" + +#: createuser.c:141 +#, c-format +msgid "%s: user ID must be a positive number\n" +msgstr "%s: användar-ID måste vara ett positivt nummer\n" + +#: createuser.c:147 +msgid "Enter name of user to add: " +msgstr "Mata in namn på användare att lägga till: " + +#: createuser.c:154 +msgid "Enter password for new user: " +msgstr "Mata in lösenord för ny användare: " + +#: createuser.c:155 +msgid "Enter it again: " +msgstr "Mata in det igen: " + +#: createuser.c:158 +msgid "Passwords didn't match.\n" +msgstr "Lösenorden matchade inte.\n" + +#: createuser.c:169 +msgid "Shall the new user be allowed to create databases? (y/n) " +msgstr "Skall den nya användaren tillåtas skapa databaser? (j/n) " + +#: createuser.c:180 +msgid "Shall the new user be allowed to create more new users? (y/n) " +msgstr "Skall den nya användaren tillåtas skapa fler nya användare? (j/n) " + +#: createuser.c:219 +#, c-format +msgid "%s: creation of new user failed: %s" +msgstr "%s: skapande av ny användare misslyckades: %s" + +#: createuser.c:235 +#, c-format +msgid "" +"%s creates a new PostgreSQL user.\n" +"\n" +msgstr "%s skapar en ny PostgreSQL-användare.\n\n" + +#: createuser.c:237 dropuser.c:144 +#, c-format +msgid " %s [OPTION]... [USERNAME]\n" +msgstr " %s [FLAGGA]... [ANVÄNDARNAMN]\n" + +#: createuser.c:239 +msgid " -a, --adduser user can add new users\n" +msgstr " -a, --adduser användare kan lägga till nya användare\n" + +#: createuser.c:240 +msgid " -A, --no-adduser user cannot add new users\n" +msgstr " -A, --no-adduser användare kan inte lägga till nya användare\n" + +#: createuser.c:241 +msgid " -d, --createdb user can create new databases\n" +msgstr " -d, --createdb användare kan skapa nya databaser\n" + +#: createuser.c:242 +msgid " -D, --no-createdb user cannot create databases\n" +msgstr " -D, --no-createdb användare kan inte skapa nya databaser\n" + +#: createuser.c:243 +msgid " -P, --pwprompt assign a password to new user\n" +msgstr " -P, --pwprompt sätt ett lösenord på den nya användaren\n" + +#: createuser.c:244 +msgid " -E, --encrypted encrypt stored password\n" +msgstr " -E, --encrypted spara lösenordet krypterat\n" + +#: createuser.c:245 +msgid " -N, --unencrypted do no encrypt stored password\n" +msgstr " -N, --unencrypted spara lösenordet okrypterat\n" + +#: createuser.c:246 +msgid " -i, --sysid=SYSID select sysid for new user\n" +msgstr " -i, --sysid=SYSID välj system-id för nya användaren\n" + +#: createuser.c:254 +msgid "" +" -U, --username=USERNAME user name to connect as (not the one to create)\n" +msgstr "" +" -U, --username=ANVÄNDARNAMN\n" +" användarnamn att koppla upp som\n" +" (inte den som skall skapas)\n" + +#: createuser.c:255 dropuser.c:152 +msgid " -W, --password prompt for password to connect\n" +msgstr " -W, --password fråga efter lösenord för att koppla upp\n" + +#: createuser.c:256 +msgid "" +"\n" +"If one of -a, -A, -d, -D, and USERNAME is not specified, you will\n" +"be prompted interactively.\n" +msgstr "" +"\n" +"Om någon av -a, -A, -d, -D, resp. ANVÄNDARNAMN inte angivits så\n" +"kommer du att få frågor om dem vid körning.\n" + +#: dropdb.c:91 +#, c-format +msgid "%s: missing required argument database name\n" +msgstr "%s: saknar databasnamn vilket krävs\n" + +#: dropdb.c:108 +#, c-format +msgid "Database \"%s\" will be permanently removed.\n" +msgstr "Databasen \"%s\" kommer att bli permanent borttagen.\n" + +#: dropdb.c:109 dropuser.c:110 +msgid "Are you sure? (y/n) " +msgstr "Är du säker? (j/n) " + +#: dropdb.c:126 +#, c-format +msgid "%s: database removal failed: %s" +msgstr "%s: borttagning av databas misslyckades: %s" + +#: dropdb.c:142 +#, c-format +msgid "" +"%s removes a PostgreSQL database.\n" +"\n" +msgstr "%s tar bort en PostgreSQL-databas.\n\n" + +#: dropdb.c:144 +#, c-format +msgid " %s [OPTION]... DBNAME\n" +msgstr " %s [FLAGGA]... DBNAMN\n" + +#: dropdb.c:147 dropuser.c:147 +msgid " -i, --interactive prompt before deleting anything\n" +msgstr " -i, --interactive fråga innan något tas bort\n" + +#: droplang.c:170 +#, c-format +msgid "%s: language \"%s\" is not installed in database \"%s\"\n" +msgstr "%s: språk \"%s\" är inte installerat i databas \"%s\"\n" + +#: droplang.c:186 +#, c-format +msgid "" +"%s: still %s functions declared in language \"%s\"; language not removed\n" +msgstr "%s: fortfarande %s funktioner deklarerade i språket \"%s\"; språket inte borttaget\n" + +#: droplang.c:227 +#, c-format +msgid "%s: language removal failed: %s" +msgstr "%s: borttagning av språk misslyckades: %s" + +#: droplang.c:241 +#, c-format +msgid "" +"%s removes a procedural language from a database.\n" +"\n" +msgstr "%s tar bort ett procedurspråk från en databas.\n\n" + +#: droplang.c:245 +msgid "" +" -d, --dbname=DBNAME database from which to remove the language\n" +msgstr " -d, --dbname=DBNAMN databasen som vi skall ta bort språket från\n" + +#: dropuser.c:103 +msgid "Enter name of user to drop: " +msgstr "Mata in namn på användaren som skall tas bort: " + +#: dropuser.c:109 +#, c-format +msgid "User \"%s\" will be permanently removed.\n" +msgstr "Användaren \"%s\" kommer ett bli permanent borttagen.\n" + +#: dropuser.c:126 +#, c-format +msgid "%s: removal of user \"%s\" failed: %s" +msgstr "%s: borttagning av användare \"%s\" misslyckades: %s" + +#: dropuser.c:142 +#, c-format +msgid "" +"%s removes a PostgreSQL user.\n" +"\n" +msgstr "%s tar bort en PostgreSQL-användare.\n\n" + +#: dropuser.c:151 +msgid "" +" -U, --username=USERNAME user name to connect as (not the one to drop)\n" +msgstr "" +" -U, --username=USERNAMN användare att koppla upp som\n" +" (inte den som tas bort)\n" + +#: clusterdb.c:119 +#, c-format +msgid "%s: cannot cluster all databases and a specific one at the same time\n" +msgstr "%s: kan inte klustra alla databaser och en specifik på en gång\n" + +#: clusterdb.c:125 +#, c-format +msgid "%s: cannot cluster a specific table in all databases\n" +msgstr "%s: kan inte klustra en specifik tabell i alla databaser\n" + +#: clusterdb.c:181 +#, c-format +msgid "%s: clustering of table \"%s\" in database \"%s\" failed: %s" +msgstr "%s: klustring av tabell \"%s\" i databas \"%s\" misslyckades: %s" + +#: clusterdb.c:184 +#, c-format +msgid "%s: clustering of database \"%s\" failed: %s" +msgstr "%s: klustring av databas \"%s\" misslyckades: %s" + +#: clusterdb.c:217 +#, c-format +msgid "%s: clustering database \"%s\"\n" +msgstr "%s: klustring av databas \"%s\"\n" + +#: clusterdb.c:231 +#, c-format +msgid "" +"%s clusters all previously clustered tables in a database.\n" +"\n" +msgstr "%s klustrar alla tidigare klustrade tabeller i en database.\n\n" + +#: clusterdb.c:233 vacuumdb.c:257 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [FLAGGA]... [DBNAMN]\n" + +#: clusterdb.c:235 +msgid " -a, --all cluster all databases\n" +msgstr " -a, --all klustra alla databaser\n" + +#: clusterdb.c:236 +msgid " -d, --dbname=DBNAME database to cluster\n" +msgstr " -d, --dbname=DBNAME databas att klustra\n" + +#: clusterdb.c:237 +msgid " -t, --table=TABLE cluster specific table only\n" +msgstr " -t, --table=TABLE klustra enbart specifik tabell\n" + +#: clusterdb.c:247 +msgid "" +"\n" +"Read the description of the SQL command CLUSTER for details.\n" +msgstr "\nLäs beskrivningen av SQL-kommandot CLUSTER för detaljer.\n" + +#: vacuumdb.c:135 +#, c-format +msgid "%s: cannot vacuum all databases and a specific one at the same time\n" +msgstr "%s: kan inte köra vacuum på alla tabeller och en specifik på en gång\n" + +#: vacuumdb.c:141 +#, c-format +msgid "%s: cannot vacuum a specific table in all databases\n" +msgstr "%s: kan inte köra vacuum på en specifik tabell i alla databaser\n" + +#: vacuumdb.c:204 +#, c-format +msgid "%s: vacuuming of table \"%s\" in database \"%s\" failed: %s" +msgstr "%s: vaccum på tabell \"%s\" i databas \"%s\" misslyckades: %s" + +#: vacuumdb.c:207 +#, c-format +msgid "%s: vacuuming of database \"%s\" failed: %s" +msgstr "%s: vacuum av databas \"%s\" misslyckades: %s" + +#: vacuumdb.c:241 +#, c-format +msgid "%s: vacuuming database \"%s\"\n" +msgstr "%s: kör vacuum på databas \"%s\"\n" + +#: vacuumdb.c:255 +#, c-format +msgid "" +"%s cleans and analyzes a PostgreSQL database.\n" +"\n" +msgstr "%s städar upp och analyserar en PostgreSQL-databas.\n\n" + +#: vacuumdb.c:259 +msgid " -a, --all vacuum all databases\n" +msgstr " -a, --all kör vacuum på alla databaser\n" + +#: vacuumdb.c:260 +msgid " -d, --dbname=DBNAME database to vacuum\n" +msgstr " -d, --dbname=DBNAMN databas att köra vacuum på\n" + +#: vacuumdb.c:261 +msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n" +msgstr "" +" -t, --table='TABELL[(KOLUMNER)]'\n" +" kör vakum enbart på specifik tabell\n" + +#: vacuumdb.c:262 +msgid " -f, --full do full vacuuming\n" +msgstr " -f, --full kör full vacuum\n" + +#: vacuumdb.c:263 +msgid " -z, --analyze update optimizer hints\n" +msgstr " -z, --analyze updatera optimeringsstatistik\n" + +#: vacuumdb.c:264 +msgid "" +" -e, --echo show the commands being sent to the " +"server\n" +msgstr " -e, --echo visa kommandon som skickas till servern\n" + +#: vacuumdb.c:265 +msgid " -q, --quiet don't write any messages\n" +msgstr " -q, --quiet skriv inte ut några meddelanden\n" + +#: vacuumdb.c:266 +msgid " -v, --verbose write a lot of output\n" +msgstr " -v, --verbose skriv massor med utdata\n" + +#: vacuumdb.c:267 +msgid " --help show this help, then exit\n" +msgstr " --help visa denna hjälp, avsluta sedan\n" + +#: vacuumdb.c:268 +msgid "" +" --version output version information, then exit\n" +msgstr " --version visa versionsinformation, avsluta sedan\n" + +#: vacuumdb.c:274 +msgid "" +"\n" +"Read the description of the SQL command VACUUM for details.\n" +msgstr "\nLäs beskrivningen på SQL-kommandot VACUUM för detaljer.\n" + +#: common.c:88 common.c:114 +msgid "Password: " +msgstr "Lösenord: " + +#: common.c:101 +#, c-format +msgid "%s: could not connect to database %s\n" +msgstr "%s: kunde inte koppla upp mot databas %s\n" + +#: common.c:124 +#, c-format +msgid "%s: could not connect to database %s: %s" +msgstr "%s: kunde inte kopppla upp mot databas %s: %s" + +#: common.c:148 +#, c-format +msgid "%s: query failed: %s" +msgstr "%s: fråga misslyckades: %s" + +#: common.c:149 +#, c-format +msgid "%s: query was: %s\n" +msgstr "%s: fråga var: %s\n" + +#. translator: Make sure the (y/n) prompts match the translation of this. +#: common.c:163 +msgid "y" +msgstr "j" + +#. translator: Make sure the (y/n) prompts match the translation of this. +#: common.c:165 +msgid "n" +msgstr "n" diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h new file mode 100644 index 0000000..faac94b --- /dev/null +++ b/src/include/utils/guc_tables.h @@ -0,0 +1,181 @@ +/*------------------------------------------------------------------------- + * + * guc_tables.h + * Declarations of tables used by GUC. + * + * See src/backend/utils/misc/README for design notes. + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * + * $Id$ + * + *------------------------------------------------------------------------- + */ +#ifndef GUC_TABLES +#define GUC_TABLES 1 + +/* + * Groupings to help organize all the run-time options for display + */ +enum config_group +{ + UNGROUPED, + CONN_AUTH, + CONN_AUTH_SETTINGS, + CONN_AUTH_SECURITY, + RESOURCES, + RESOURCES_MEM, + RESOURCES_FSM, + RESOURCES_KERNEL, + WAL, + WAL_SETTINGS, + WAL_CHECKPOINTS, + QUERY_TUNING, + QUERY_TUNING_METHOD, + QUERY_TUNING_COST, + QUERY_TUNING_GEQO, + QUERY_TUNING_OTHER, + LOGGING, + LOGGING_SYSLOG, + LOGGING_WHEN, + LOGGING_WHAT, + STATS, + STATS_MONITORING, + STATS_COLLECTOR, + CLIENT_CONN, + CLIENT_CONN_STATEMENT, + CLIENT_CONN_LOCALE, + CLIENT_CONN_OTHER, + LOCK_MANAGEMENT, + COMPAT_OPTIONS, + COMPAT_OPTIONS_PREVIOUS, + COMPAT_OPTIONS_CLIENT, + DEVELOPER_OPTIONS +}; + +/* + * GUC supports these types of variables: + */ +enum config_type +{ + PGC_BOOL, + PGC_INT, + PGC_REAL, + PGC_STRING +}; + +/* + * Generic fields applicable to all types of variables + * + * The short description should be less than 80 chars in length. Some + * applications may use the long description as well, and will append + * it to the short description. (separated by a newline or '. ') + */ +struct config_generic +{ + /* constant fields, must be set correctly in initial value: */ + const char *name; /* name of variable - MUST BE FIRST */ + GucContext context; /* context required to set the variable */ + enum config_group group; /* to help organize variables by function */ + const char *short_desc; /* short desc. of this variable's purpose */ + const char *long_desc; /* long desc. of this variable's purpose */ + int flags; /* flag bits, see below */ + /* variable fields, initialized at runtime: */ + enum config_type vartype; /* type of variable (set only at startup) */ + int status; /* status bits, see below */ + GucSource reset_source; /* source of the reset_value */ + GucSource session_source; /* source of the session_value */ + GucSource tentative_source; /* source of the tentative_value */ + GucSource source; /* source of the current actual value */ +}; + +/* bit values in flags field */ +#define GUC_LIST_INPUT 0x0001 /* input can be list format */ +#define GUC_LIST_QUOTE 0x0002 /* double-quote list elements */ +#define GUC_NO_SHOW_ALL 0x0004 /* exclude from SHOW ALL */ +#define GUC_NO_RESET_ALL 0x0008 /* exclude from RESET ALL */ +#define GUC_REPORT 0x0010 /* auto-report changes to client */ +#define GUC_NOT_IN_SAMPLE 0x0020 /* not in postgresql.conf.sample */ +#define GUC_DISALLOW_IN_FILE 0x0040 /* can't set in postgresql.conf */ + +/* bit values in status field */ +#define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */ +#define GUC_HAVE_LOCAL 0x0002 /* a SET LOCAL has been executed */ + + +/* GUC records for specific variable types */ + +struct config_bool +{ + struct config_generic gen; + /* these fields must be set correctly in initial value: */ + /* (all but reset_val are constants) */ + bool *variable; + bool reset_val; + bool (*assign_hook) (bool newval, bool doit, bool interactive); + const char *(*show_hook) (void); + /* variable fields, initialized at runtime: */ + bool session_val; + bool tentative_val; +}; + +struct config_int +{ + struct config_generic gen; + /* these fields must be set correctly in initial value: */ + /* (all but reset_val are constants) */ + int *variable; + int reset_val; + int min; + int max; + bool (*assign_hook) (int newval, bool doit, bool interactive); + const char *(*show_hook) (void); + /* variable fields, initialized at runtime: */ + int session_val; + int tentative_val; +}; + +struct config_real +{ + struct config_generic gen; + /* these fields must be set correctly in initial value: */ + /* (all but reset_val are constants) */ + double *variable; + double reset_val; + double min; + double max; + bool (*assign_hook) (double newval, bool doit, bool interactive); + const char *(*show_hook) (void); + /* variable fields, initialized at runtime: */ + double session_val; + double tentative_val; +}; + +struct config_string +{ + struct config_generic gen; + /* these fields must be set correctly in initial value: */ + /* (all are constants) */ + char **variable; + const char *boot_val; + const char *(*assign_hook) (const char *newval, bool doit, bool interactive); + const char *(*show_hook) (void); + /* variable fields, initialized at runtime: */ + char *reset_val; + char *session_val; + char *tentative_val; +}; + +/* constant tables corresponding to enums above and in guc.h */ +extern const char *const config_group_names[]; +extern const char *const config_type_names[]; +extern const char *const GucContext_Names[]; +extern const char *const GucSource_Names[]; + +/* the current set of variables */ +extern struct config_generic **guc_variables; +extern int num_guc_variables; + +extern void build_guc_variables(void); + +#endif diff --git a/src/include/utils/help_config.h b/src/include/utils/help_config.h new file mode 100644 index 0000000..88e6edf --- /dev/null +++ b/src/include/utils/help_config.h @@ -0,0 +1,17 @@ +/*------------------------------------------------------------------------- + * + * help_config.h + * Interface to the --help-config option of main.c + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * + * $Id$ + * + *------------------------------------------------------------------------- + */ +#ifndef HELP_CONFIG_H +#define HELP_CONFIG_H 1 + +extern int GucInfoMain(int argc, char *argv[]); + +#endif diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java index 417cf87..fc75d5d 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java @@ -8,7 +8,7 @@ import java.sql.*; * Base class for data sources and related classes. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ + * @version $Revision$ */ public abstract class BaseDataSource implements Referenceable { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java index f770069..4935679 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java @@ -21,7 +21,7 @@ import java.io.Serializable; *

This implementation supports JDK 1.3 and higher.

* * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.2 $ + * @version $Revision$ */ public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java index 48778e0..5c944bc 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java @@ -13,7 +13,7 @@ import java.util.Hashtable; * consistent. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ + * @version $Revision$ */ public class PGObjectFactory implements ObjectFactory { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java index 2a5190e..4e7ed71 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java @@ -14,7 +14,7 @@ import org.postgresql.PGConnection; * * @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Csaba Nagy (ncsaba@yahoo.com) - * @version $Revision: 1.7 $ + * @version $Revision$ */ public class PooledConnectionImpl implements PooledConnection { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java index 1d6c7da..a84aa0c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java @@ -33,7 +33,7 @@ import java.sql.SQLException; *

This implementation supports JDK 1.3 and higher.

* * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ + * @version $Revision$ */ public class PoolingDataSource extends BaseDataSource implements DataSource { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java index 6d9ef39..0bb53c8 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java @@ -10,7 +10,7 @@ import java.io.Serializable; * are declared in the superclass. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.2 $ + * @version $Revision$ */ public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java index 1f739d5..7d4628f 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java @@ -15,7 +15,7 @@ import java.sql.SQLException; * commit protocol). * * @author Aaron Mulder (ammulder@alumni.princeton.edu) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3ConnectionPool extends ConnectionPool { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java index 53151b8..759ab44 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java @@ -9,7 +9,7 @@ import org.postgresql.jdbc2.optional.PGObjectFactory; * from their JNDI references. * * @author Aaron Mulder (ammulder@alumni.princeton.edu) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3ObjectFactory extends PGObjectFactory { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java index cac966d..aae7640 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java @@ -9,7 +9,7 @@ import java.sql.Connection; * a connection in a connection pool. * * @author Aaron Mulder (ammulder@alumni.princeton.edu) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3PooledConnection extends PooledConnectionImpl { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java index df3e50a..9730b64 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java @@ -14,7 +14,7 @@ import javax.naming.Reference; * (not available for PostgreSQL). * * @author Aaron Mulder (ammulder@alumni.princeton.edu) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3PoolingDataSource extends PoolingDataSource { diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java index d8dff03..8d10e2e 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java @@ -8,7 +8,7 @@ import javax.naming.Reference; * JDBC3 implementation of a non-pooling DataSource. * * @author Aaron Mulder (ammulder@alumni.princeton.edu) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3SimpleDataSource extends SimpleDataSource { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java index 75157a8..fb363ea 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java @@ -17,7 +17,7 @@ import javax.naming.*; * tests. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.6 $ + * @version $Revision$ */ public abstract class BaseDataSourceTest extends TestCase { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java index 8f84193..4d9afe1 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java @@ -11,7 +11,7 @@ import java.sql.*; * interface to the PooledConnection is through the CPDS. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.6 $ + * @version $Revision$ */ public class ConnectionPoolTest extends BaseDataSourceTest { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java index 58e47bb..d740a5a 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java @@ -8,7 +8,7 @@ import junit.framework.TestSuite; * PooledConnection implementations. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.4 $ + * @version $Revision$ */ public class OptionalTestSuite extends TestSuite { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java index 9b08eca..1a3e800 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java @@ -9,7 +9,7 @@ import org.postgresql.jdbc2.optional.BaseDataSource; * Minimal tests for pooling DataSource. Needs many more. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class PoolingDataSourceTest extends BaseDataSourceTest { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java index b5c3e10..29c022d 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java @@ -8,7 +8,7 @@ import org.postgresql.jdbc2.optional.SimpleDataSource; * configuration logic. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ + * @version $Revision$ */ public class SimpleDataSourceTest extends BaseDataSourceTest { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java index f679c48..b224134 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java @@ -12,7 +12,7 @@ import javax.sql.PooledConnection; * Tests JDBC3 implementation of ConnectionPoolDataSource. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.2 $ + * @version $Revision$ */ public class Jdbc3ConnectionPoolTest extends ConnectionPoolTest { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java index 55374cb..196d36d 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java @@ -13,7 +13,7 @@ import org.postgresql.jdbc2.optional.PoolingDataSource; * Minimal tests for JDBC3 pooling DataSource. Needs many more. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3PoolingDataSourceTest extends PoolingDataSourceTest { diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java index cef4c83..bb0fa00 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java @@ -10,7 +10,7 @@ import org.postgresql.jdbc3.*; * Tests JDBC3 non-pooling DataSource. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class Jdbc3SimpleDataSourceTest extends SimpleDataSourceTest { /** diff --git a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java index 4caf241..095da98 100644 --- a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java +++ b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java @@ -12,7 +12,7 @@ import javax.naming.spi.ObjectFactory; * pools. It is not a complete JNDI implementations. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class MiniJndiContext implements Context { diff --git a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java index 58cc533..46051fd 100644 --- a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java +++ b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java @@ -10,7 +10,7 @@ import javax.naming.spi.InitialContextFactory; * pools. * * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.1 $ + * @version $Revision$ */ public class MiniJndiContextFactory implements InitialContextFactory { diff --git a/src/port/crypt.c b/src/port/crypt.c index a184063..caa8d82 100644 --- a/src/port/crypt.c +++ b/src/port/crypt.c @@ -1,4 +1,4 @@ -/* $NetBSD$ */ +/* $NetBSD: crypt.c,v 1.18 2001/03/01 14:37:35 wiz Exp $ */ /* * Copyright (c) 1989, 1993 @@ -41,7 +41,7 @@ static char sccsid[] = "@(#)crypt.c 8.1.1.1 (Berkeley) 8/18/93"; #else -__RCSID("$NetBSD$"); +__RCSID("$NetBSD: crypt.c,v 1.18 2001/03/01 14:37:35 wiz Exp $"); #endif #endif /* not lint */ diff --git a/src/port/qsort.c b/src/port/qsort.c index 4f2487e..fe6e1a8 100644 --- a/src/port/qsort.c +++ b/src/port/qsort.c @@ -6,7 +6,7 @@ * $Header$ */ -/* $NetBSD$ */ +/* $NetBSD: qsort.c,v 1.12 1999/09/20 04:39:40 lukem Exp $ */ /*- * Copyright (c) 1992, 1993 diff --git a/src/port/sprompt.c b/src/port/sprompt.c new file mode 100644 index 0000000..3610aa7 --- /dev/null +++ b/src/port/sprompt.c @@ -0,0 +1,158 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright 2000 by PostgreSQL Global Development Group + * + * $Header$ + */ + + +/* + * simple_prompt + * + * Generalized function especially intended for reading in usernames and + * password interactively. Reads from /dev/tty or stdin/stderr. + * + * prompt: The prompt to print + * maxlen: How many characters to accept + * echo: Set to false if you want to hide what is entered (for passwords) + * + * Returns a malloc()'ed string with the input (w/o trailing newline). + */ +#include "postgres.h" + +#ifdef HAVE_TERMIOS_H +#include +#else +#ifdef WIN32 +#include +#endif +#endif + +bool prompt_state = false; +extern char *simple_prompt(const char *prompt, int maxlen, bool echo); + +char * +simple_prompt(const char *prompt, int maxlen, bool echo) +{ + int length; + char *destination; + FILE *termin, + *termout; + +#ifdef HAVE_TERMIOS_H + struct termios t_orig, + t; + +#else +#ifdef WIN32 + HANDLE t; + LPDWORD t_orig; +#endif +#endif + + destination = (char *) malloc(maxlen + 1); + if (!destination) + return NULL; + + prompt_state = true; /* disable SIGINT */ + + /* + * Do not try to collapse these into one "w+" mode file. Doesn't work + * on some platforms (eg, HPUX 10.20). + */ + termin = fopen("/dev/tty", "r"); + termout = fopen("/dev/tty", "w"); + if (!termin || !termout) + { + if (termin) + fclose(termin); + if (termout) + fclose(termout); + termin = stdin; + termout = stderr; + } + +#ifdef HAVE_TERMIOS_H + if (!echo) + { + tcgetattr(fileno(termin), &t); + t_orig = t; + t.c_lflag &= ~ECHO; + tcsetattr(fileno(termin), TCSAFLUSH, &t); + } +#else +#ifdef WIN32 + if (!echo) + { + /* get a new handle to turn echo off */ + t_orig = (LPDWORD) malloc(sizeof(DWORD)); + t = GetStdHandle(STD_INPUT_HANDLE); + + /* save the old configuration first */ + GetConsoleMode(t, t_orig); + + /* set to the new mode */ + SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); + } +#endif +#endif + + if (prompt) + { + fputs(gettext(prompt), termout); + fflush(termout); + } + + if (fgets(destination, maxlen + 1, termin) == NULL) + destination[0] = '\0'; + + length = strlen(destination); + if (length > 0 && destination[length - 1] != '\n') + { + /* eat rest of the line */ + char buf[128]; + int buflen; + + do + { + if (fgets(buf, sizeof(buf), termin) == NULL) + break; + buflen = strlen(buf); + } while (buflen > 0 && buf[buflen - 1] != '\n'); + } + + if (length > 0 && destination[length - 1] == '\n') + /* remove trailing newline */ + destination[length - 1] = '\0'; + +#ifdef HAVE_TERMIOS_H + if (!echo) + { + tcsetattr(fileno(termin), TCSAFLUSH, &t_orig); + fputs("\n", termout); + fflush(termout); + } +#else +#ifdef WIN32 + if (!echo) + { + /* reset to the original console mode */ + SetConsoleMode(t, *t_orig); + fputs("\n", termout); + fflush(termout); + free(t_orig); + } +#endif +#endif + + if (termin != stdin) + { + fclose(termin); + fclose(termout); + } + + prompt_state = false; /* SIGINT okay again */ + + return destination; +} diff --git a/src/test/regress/expected/select_having_2.out b/src/test/regress/expected/select_having_2.out new file mode 100644 index 0000000..239e49f --- /dev/null +++ b/src/test/regress/expected/select_having_2.out @@ -0,0 +1,52 @@ +-- +-- SELECT_HAVING +-- +-- load test data +CREATE TABLE test_having (a int, b int, c char(8), d char); +INSERT INTO test_having VALUES (0, 1, 'XXXX', 'A'); +INSERT INTO test_having VALUES (1, 2, 'AAAA', 'b'); +INSERT INTO test_having VALUES (2, 2, 'AAAA', 'c'); +INSERT INTO test_having VALUES (3, 3, 'BBBB', 'D'); +INSERT INTO test_having VALUES (4, 3, 'BBBB', 'e'); +INSERT INTO test_having VALUES (5, 3, 'bbbb', 'F'); +INSERT INTO test_having VALUES (6, 4, 'cccc', 'g'); +INSERT INTO test_having VALUES (7, 4, 'cccc', 'h'); +INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I'); +INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j'); +SELECT b, c FROM test_having + GROUP BY b, c HAVING count(*) = 1 ORDER BY b, c; + b | c +---+---------- + 1 | XXXX + 3 | bbbb +(2 rows) + +-- HAVING is equivalent to WHERE in this case +SELECT b, c FROM test_having + GROUP BY b, c HAVING b = 3 ORDER BY b, c; + b | c +---+---------- + 3 | bbbb + 3 | BBBB +(2 rows) + +SELECT lower(c), count(c) FROM test_having + GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a) + ORDER BY lower(c); + lower | count +-------+------- + bbbb | 3 + cccc | 4 + xxxx | 1 +(3 rows) + +SELECT c, max(a) FROM test_having + GROUP BY c HAVING count(*) > 2 OR min(a) = max(a) + ORDER BY c; + c | max +----------+----- + bbbb | 5 + XXXX | 0 +(2 rows) + +DROP TABLE test_having; diff --git a/src/test/regress/expected/select_implicit_2.out b/src/test/regress/expected/select_implicit_2.out new file mode 100644 index 0000000..b399ceb --- /dev/null +++ b/src/test/regress/expected/select_implicit_2.out @@ -0,0 +1,324 @@ +-- +-- SELECT_IMPLICIT +-- Test cases for queries with ordering terms missing from the target list. +-- This used to be called "junkfilter.sql". +-- The parser uses the term "resjunk" to handle these cases. +-- - thomas 1998-07-09 +-- +-- load test data +CREATE TABLE test_missing_target (a int, b int, c char(8), d char); +INSERT INTO test_missing_target VALUES (0, 1, 'XXXX', 'A'); +INSERT INTO test_missing_target VALUES (1, 2, 'AAAA', 'b'); +INSERT INTO test_missing_target VALUES (2, 2, 'AAAA', 'c'); +INSERT INTO test_missing_target VALUES (3, 3, 'BBBB', 'D'); +INSERT INTO test_missing_target VALUES (4, 3, 'BBBB', 'e'); +INSERT INTO test_missing_target VALUES (5, 3, 'bbbb', 'F'); +INSERT INTO test_missing_target VALUES (6, 4, 'cccc', 'g'); +INSERT INTO test_missing_target VALUES (7, 4, 'cccc', 'h'); +INSERT INTO test_missing_target VALUES (8, 4, 'CCCC', 'I'); +INSERT INTO test_missing_target VALUES (9, 4, 'CCCC', 'j'); +-- w/ existing GROUP BY target +SELECT c, count(*) FROM test_missing_target GROUP BY test_missing_target.c ORDER BY c; + c | count +----------+------- + AAAA | 2 + bbbb | 1 + BBBB | 2 + cccc | 2 + CCCC | 2 + XXXX | 1 +(6 rows) + +-- w/o existing GROUP BY target using a relation name in GROUP BY clause +SELECT count(*) FROM test_missing_target GROUP BY test_missing_target.c ORDER BY c; + count +------- + 2 + 1 + 2 + 2 + 2 + 1 +(6 rows) + +-- w/o existing GROUP BY target and w/o existing a different ORDER BY target +-- failure expected +SELECT count(*) FROM test_missing_target GROUP BY a ORDER BY b; +ERROR: attribute "test_missing_target.b" must be GROUPed or used in an aggregate function +-- w/o existing GROUP BY target and w/o existing same ORDER BY target +SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b; + count +------- + 1 + 2 + 3 + 4 +(4 rows) + +-- w/ existing GROUP BY target using a relation name in target +SELECT test_missing_target.b, count(*) + FROM test_missing_target GROUP BY b ORDER BY b; + b | count +---+------- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 +(4 rows) + +-- w/o existing GROUP BY target +SELECT c FROM test_missing_target ORDER BY a; + c +---------- + XXXX + AAAA + AAAA + BBBB + BBBB + bbbb + cccc + cccc + CCCC + CCCC +(10 rows) + +-- w/o existing ORDER BY target +SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b desc; + count +------- + 4 + 3 + 2 + 1 +(4 rows) + +-- group using reference number +SELECT count(*) FROM test_missing_target ORDER BY 1 desc; + count +------- + 10 +(1 row) + +-- order using reference number +SELECT c, count(*) FROM test_missing_target GROUP BY 1 ORDER BY 1; + c | count +----------+------- + AAAA | 2 + bbbb | 1 + BBBB | 2 + cccc | 2 + CCCC | 2 + XXXX | 1 +(6 rows) + +-- group using reference number out of range +-- failure expected +SELECT c, count(*) FROM test_missing_target GROUP BY 3; +ERROR: GROUP BY position 3 is not in target list +-- group w/o existing GROUP BY and ORDER BY target under ambiguous condition +-- failure expected +SELECT count(*) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY b ORDER BY b; +ERROR: column reference "b" is ambiguous +-- order w/ target under ambiguous condition +-- failure NOT expected +SELECT a, a FROM test_missing_target + ORDER BY a; + a | a +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- order expression w/ target under ambiguous condition +-- failure NOT expected +SELECT a/2, a/2 FROM test_missing_target + ORDER BY a/2; + ?column? | ?column? +----------+---------- + 0 | 0 + 0 | 0 + 1 | 1 + 1 | 1 + 2 | 2 + 2 | 2 + 3 | 3 + 3 | 3 + 4 | 4 + 4 | 4 +(10 rows) + +-- group expression w/ target under ambiguous condition +-- failure NOT expected +SELECT a/2, a/2 FROM test_missing_target + GROUP BY a/2 ORDER BY a/2; + ?column? | ?column? +----------+---------- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 +(5 rows) + +-- group w/ existing GROUP BY target under ambiguous condition +SELECT x.b, count(*) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b ORDER BY x.b; + b | count +---+------- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 +(4 rows) + +-- group w/o existing GROUP BY target under ambiguous condition +SELECT count(*) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b ORDER BY x.b; + count +------- + 1 + 2 + 3 + 4 +(4 rows) + +-- group w/o existing GROUP BY target under ambiguous condition +-- into a table +SELECT count(*) INTO TABLE test_missing_target2 +FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b ORDER BY x.b; +SELECT * FROM test_missing_target2; + count +------- + 1 + 2 + 3 + 4 +(4 rows) + +-- Functions and expressions +-- w/ existing GROUP BY target +SELECT a%2, count(b) FROM test_missing_target +GROUP BY test_missing_target.a%2 +ORDER BY test_missing_target.a%2; + ?column? | count +----------+------- + 0 | 5 + 1 | 5 +(2 rows) + +-- w/o existing GROUP BY target using a relation name in GROUP BY clause +SELECT count(c) FROM test_missing_target +GROUP BY lower(test_missing_target.c) +ORDER BY lower(test_missing_target.c); + count +------- + 2 + 3 + 4 + 1 +(4 rows) + +-- w/o existing GROUP BY target and w/o existing a different ORDER BY target +-- failure expected +SELECT count(a) FROM test_missing_target GROUP BY a ORDER BY b; +ERROR: attribute "test_missing_target.b" must be GROUPed or used in an aggregate function +-- w/o existing GROUP BY target and w/o existing same ORDER BY target +SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2; + count +------- + 1 + 5 + 4 +(3 rows) + +-- w/ existing GROUP BY target using a relation name in target +SELECT lower(test_missing_target.c), count(c) + FROM test_missing_target GROUP BY lower(c) ORDER BY lower(c); + lower | count +-------+------- + aaaa | 2 + bbbb | 3 + cccc | 4 + xxxx | 1 +(4 rows) + +-- w/o existing GROUP BY target +SELECT a FROM test_missing_target ORDER BY upper(d); + a +--- + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +(10 rows) + +-- w/o existing ORDER BY target +SELECT count(b) FROM test_missing_target + GROUP BY (b + 1) / 2 ORDER BY (b + 1) / 2 desc; + count +------- + 7 + 3 +(2 rows) + +-- group w/o existing GROUP BY and ORDER BY target under ambiguous condition +-- failure expected +SELECT count(x.a) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY b/2 ORDER BY b/2; +ERROR: column reference "b" is ambiguous +-- group w/ existing GROUP BY target under ambiguous condition +SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b/2 ORDER BY x.b/2; + ?column? | count +----------+------- + 0 | 1 + 1 | 5 + 2 | 4 +(3 rows) + +-- group w/o existing GROUP BY target under ambiguous condition +-- failure expected due to ambiguous b in count(b) +SELECT count(b) FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b/2; +ERROR: column reference "b" is ambiguous +-- group w/o existing GROUP BY target under ambiguous condition +-- into a table +SELECT count(x.b) INTO TABLE test_missing_target3 +FROM test_missing_target x, test_missing_target y + WHERE x.a = y.a + GROUP BY x.b/2 ORDER BY x.b/2; +SELECT * FROM test_missing_target3; + count +------- + 1 + 5 + 4 +(3 rows) + +-- Cleanup +DROP TABLE test_missing_target; +DROP TABLE test_missing_target2; +DROP TABLE test_missing_target3; diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql new file mode 100644 index 0000000..5175f9f --- /dev/null +++ b/src/test/regress/sql/polymorphism.sql @@ -0,0 +1,367 @@ +-- Currently this tests polymorphic aggregates and indirectly does some +-- testing of polymorphic SQL functions. It ought to be extended. + + +-- Legend: +----------- +-- A = type is ANY +-- P = type is polymorphic +-- N = type is non-polymorphic +-- B = aggregate base type +-- S = aggregate state type +-- R = aggregate return type +-- 1 = arg1 of a function +-- 2 = arg2 of a function +-- ag = aggregate +-- tf = trans (state) function +-- ff = final function +-- rt = return type of a function +-- -> = implies +-- => = allowed +-- !> = not allowed +-- E = exists +-- NE = not-exists +-- +-- Possible states: +-- ---------------- +-- B = (A || P || N) +-- when (B = A) -> (tf2 = NE) +-- S = (P || N) +-- ff = (E || NE) +-- tf1 = (P || N) +-- tf2 = (NE || P || N) +-- R = (P || N) + +-- create functions for use as tf and ff with the needed combinations of +-- argument polymorphism, but within the constraints of valid aggregate +-- functions, i.e. tf arg1 and tf return type must match + +-- polymorphic single arg transfn +CREATE FUNCTION stfp(anyarray) returns anyarray as +'select $1' language 'sql'; +-- non-polymorphic single arg transfn +CREATE FUNCTION stfnp(int[]) returns int[] as +'select $1' language 'sql'; + +-- dual polymorphic transfn +CREATE FUNCTION tfp(anyarray,anyelement) returns anyarray as +'select $1 || $2' language 'sql'; +-- dual non-polymorphic transfn +CREATE FUNCTION tfnp(int[],int) returns int[] as +'select $1 || $2' language 'sql'; + +-- arg1 only polymorphic transfn +CREATE FUNCTION tf1p(anyarray,int) returns anyarray as +'select $1' language 'sql'; +-- arg2 only polymorphic transfn +CREATE FUNCTION tf2p(int[],anyelement) returns int[] as +'select $1' language 'sql'; + +-- finalfn polymorphic +CREATE FUNCTION ffp(anyarray) returns anyarray as +'select $1' language 'sql'; +-- finalfn non-polymorphic +CREATE FUNCTION ffnp(int[]) returns int[] as +'select $1' language 'sql'; + +-- Try to cover all the possible states: +-- +-- Note: in Cases 1 & 2, we are trying to return P. Therefore, if the transfn +-- is stfnp, tfnp, or tf2p, we must use ffp as finalfn, because stfnp, tfnp, +-- and tf2p do not return P. Conversely, in Cases 3 & 4, we are trying to +-- return N. Therefore, if the transfn is stfp, tfp, or tf1p, we must use ffnp +-- as finalfn, because stfp, tfp, and tf1p do not return N. +-- +-- Case1 (R = P) && (B = A) +-- ------------------------ +-- S tf1 +-- ------- +-- N N +-- should CREATE +CREATE AGGREGATE myaggp01a(BASETYPE = "ANY", SFUNC = stfnp, STYPE = int4[], + FINALFUNC = ffp, INITCOND = '{}'); + +-- P N +-- should ERROR: stfnp(anyarray) not matched by stfnp(int[]) +CREATE AGGREGATE myaggp02a(BASETYPE = "ANY", SFUNC = stfnp, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); + +-- N P +-- should CREATE +CREATE AGGREGATE myaggp03a(BASETYPE = "ANY", SFUNC = stfp, STYPE = int4[], + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp03b(BASETYPE = "ANY", SFUNC = stfp, STYPE = int4[], + INITCOND = '{}'); + +-- P P +-- should ERROR: we have no way to resolve S +CREATE AGGREGATE myaggp04a(BASETYPE = "ANY", SFUNC = stfp, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp04b(BASETYPE = "ANY", SFUNC = stfp, STYPE = anyarray, + INITCOND = '{}'); + + +-- Case2 (R = P) && ((B = P) || (B = N)) +-- ------------------------------------- +-- S tf1 B tf2 +-- ----------------------- +-- N N N N +-- should CREATE +CREATE AGGREGATE myaggp05a(BASETYPE = int, SFUNC = tfnp, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); + +-- N N N P +-- should CREATE +CREATE AGGREGATE myaggp06a(BASETYPE = int, SFUNC = tf2p, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); + +-- N N P N +-- should ERROR: tfnp(int[], anyelement) not matched by tfnp(int[], int) +CREATE AGGREGATE myaggp07a(BASETYPE = anyelement, SFUNC = tfnp, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); + +-- N N P P +-- should CREATE +CREATE AGGREGATE myaggp08a(BASETYPE = anyelement, SFUNC = tf2p, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); + +-- N P N N +-- should CREATE +CREATE AGGREGATE myaggp09a(BASETYPE = int, SFUNC = tf1p, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp09b(BASETYPE = int, SFUNC = tf1p, STYPE = int[], + INITCOND = '{}'); + +-- N P N P +-- should CREATE +CREATE AGGREGATE myaggp10a(BASETYPE = int, SFUNC = tfp, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp10b(BASETYPE = int, SFUNC = tfp, STYPE = int[], + INITCOND = '{}'); + +-- N P P N +-- should ERROR: tf1p(int[],anyelement) not matched by tf1p(anyarray,int) +CREATE AGGREGATE myaggp11a(BASETYPE = anyelement, SFUNC = tf1p, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp11b(BASETYPE = anyelement, SFUNC = tf1p, STYPE = int[], + INITCOND = '{}'); + +-- N P P P +-- should ERROR: tfp(int[],anyelement) not matched by tfp(anyarray,anyelement) +CREATE AGGREGATE myaggp12a(BASETYPE = anyelement, SFUNC = tfp, STYPE = int[], + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp12b(BASETYPE = anyelement, SFUNC = tfp, STYPE = int[], + INITCOND = '{}'); + +-- P N N N +-- should ERROR: tfnp(anyarray, int) not matched by tfnp(int[],int) +CREATE AGGREGATE myaggp13a(BASETYPE = int, SFUNC = tfnp, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); + +-- P N N P +-- should ERROR: tf2p(anyarray, int) not matched by tf2p(int[],anyelement) +CREATE AGGREGATE myaggp14a(BASETYPE = int, SFUNC = tf2p, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); + +-- P N P N +-- should ERROR: tfnp(anyarray, anyelement) not matched by tfnp(int[],int) +CREATE AGGREGATE myaggp15a(BASETYPE = anyelement, SFUNC = tfnp, + STYPE = anyarray, FINALFUNC = ffp, INITCOND = '{}'); + +-- P N P P +-- should ERROR: tf2p(anyarray, anyelement) not matched by tf2p(int[],anyelement) +CREATE AGGREGATE myaggp16a(BASETYPE = anyelement, SFUNC = tf2p, + STYPE = anyarray, FINALFUNC = ffp, INITCOND = '{}'); + +-- P P N N +-- should ERROR: we have no way to resolve S +CREATE AGGREGATE myaggp17a(BASETYPE = int, SFUNC = tf1p, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp17b(BASETYPE = int, SFUNC = tf1p, STYPE = anyarray, + INITCOND = '{}'); + +-- P P N P +-- should ERROR: tfp(anyarray, int) not matched by tfp(anyarray, anyelement) +CREATE AGGREGATE myaggp18a(BASETYPE = int, SFUNC = tfp, STYPE = anyarray, + FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp18b(BASETYPE = int, SFUNC = tfp, STYPE = anyarray, + INITCOND = '{}'); + +-- P P P N +-- should ERROR: tf1p(anyarray, anyelement) not matched by tf1p(anyarray, int) +CREATE AGGREGATE myaggp19a(BASETYPE = anyelement, SFUNC = tf1p, + STYPE = anyarray, FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp19b(BASETYPE = anyelement, SFUNC = tf1p, + STYPE = anyarray, INITCOND = '{}'); + +-- P P P P +-- should CREATE +CREATE AGGREGATE myaggp20a(BASETYPE = anyelement, SFUNC = tfp, + STYPE = anyarray, FINALFUNC = ffp, INITCOND = '{}'); +CREATE AGGREGATE myaggp20b(BASETYPE = anyelement, SFUNC = tfp, + STYPE = anyarray, INITCOND = '{}'); + +-- Case3 (R = N) && (B = A) +-- ------------------------ +-- S tf1 +-- ------- +-- N N +-- should CREATE +CREATE AGGREGATE myaggn01a(BASETYPE = "ANY", SFUNC = stfnp, STYPE = int4[], + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn01b(BASETYPE = "ANY", SFUNC = stfnp, STYPE = int4[], + INITCOND = '{}'); + +-- P N +-- should ERROR: stfnp(anyarray) not matched by stfnp(int[]) +CREATE AGGREGATE myaggn02a(BASETYPE = "ANY", SFUNC = stfnp, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn02b(BASETYPE = "ANY", SFUNC = stfnp, STYPE = anyarray, + INITCOND = '{}'); + +-- N P +-- should CREATE +CREATE AGGREGATE myaggn03a(BASETYPE = "ANY", SFUNC = stfp, STYPE = int4[], + FINALFUNC = ffnp, INITCOND = '{}'); + +-- P P +-- should ERROR: ffnp(anyarray) not matched by ffnp(int[]) +CREATE AGGREGATE myaggn04a(BASETYPE = "ANY", SFUNC = stfp, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); + + +-- Case4 (R = N) && ((B = P) || (B = N)) +-- ------------------------------------- +-- S tf1 B tf2 +-- ----------------------- +-- N N N N +-- should CREATE +CREATE AGGREGATE myaggn05a(BASETYPE = int, SFUNC = tfnp, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn05b(BASETYPE = int, SFUNC = tfnp, STYPE = int[], + INITCOND = '{}'); + +-- N N N P +-- should CREATE +CREATE AGGREGATE myaggn06a(BASETYPE = int, SFUNC = tf2p, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn06b(BASETYPE = int, SFUNC = tf2p, STYPE = int[], + INITCOND = '{}'); + +-- N N P N +-- should ERROR: tfnp(int[], anyelement) not matched by tfnp(int[], int) +CREATE AGGREGATE myaggn07a(BASETYPE = anyelement, SFUNC = tfnp, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn07b(BASETYPE = anyelement, SFUNC = tfnp, STYPE = int[], + INITCOND = '{}'); + +-- N N P P +-- should CREATE +CREATE AGGREGATE myaggn08a(BASETYPE = anyelement, SFUNC = tf2p, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn08b(BASETYPE = anyelement, SFUNC = tf2p, STYPE = int[], + INITCOND = '{}'); + +-- N P N N +-- should CREATE +CREATE AGGREGATE myaggn09a(BASETYPE = int, SFUNC = tf1p, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); + +-- N P N P +-- should CREATE +CREATE AGGREGATE myaggn10a(BASETYPE = int, SFUNC = tfp, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); + +-- N P P N +-- should ERROR: tf1p(int[],anyelement) not matched by tf1p(anyarray,int) +CREATE AGGREGATE myaggn11a(BASETYPE = anyelement, SFUNC = tf1p, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); + +-- N P P P +-- should ERROR: tfp(int[],anyelement) not matched by tfp(anyarray,anyelement) +CREATE AGGREGATE myaggn12a(BASETYPE = anyelement, SFUNC = tfp, STYPE = int[], + FINALFUNC = ffnp, INITCOND = '{}'); + +-- P N N N +-- should ERROR: tfnp(anyarray, int) not matched by tfnp(int[],int) +CREATE AGGREGATE myaggn13a(BASETYPE = int, SFUNC = tfnp, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn13b(BASETYPE = int, SFUNC = tfnp, STYPE = anyarray, + INITCOND = '{}'); + +-- P N N P +-- should ERROR: tf2p(anyarray, int) not matched by tf2p(int[],anyelement) +CREATE AGGREGATE myaggn14a(BASETYPE = int, SFUNC = tf2p, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn14b(BASETYPE = int, SFUNC = tf2p, STYPE = anyarray, + INITCOND = '{}'); + +-- P N P N +-- should ERROR: tfnp(anyarray, anyelement) not matched by tfnp(int[],int) +CREATE AGGREGATE myaggn15a(BASETYPE = anyelement, SFUNC = tfnp, + STYPE = anyarray, FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn15b(BASETYPE = anyelement, SFUNC = tfnp, + STYPE = anyarray, INITCOND = '{}'); + +-- P N P P +-- should ERROR: tf2p(anyarray, anyelement) not matched by tf2p(int[],anyelement) +CREATE AGGREGATE myaggn16a(BASETYPE = anyelement, SFUNC = tf2p, + STYPE = anyarray, FINALFUNC = ffnp, INITCOND = '{}'); +CREATE AGGREGATE myaggn16b(BASETYPE = anyelement, SFUNC = tf2p, + STYPE = anyarray, INITCOND = '{}'); + +-- P P N N +-- should ERROR: ffnp(anyarray) not matched by ffnp(int[]) +CREATE AGGREGATE myaggn17a(BASETYPE = int, SFUNC = tf1p, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); + +-- P P N P +-- should ERROR: tfp(anyarray, int) not matched by tfp(anyarray, anyelement) +CREATE AGGREGATE myaggn18a(BASETYPE = int, SFUNC = tfp, STYPE = anyarray, + FINALFUNC = ffnp, INITCOND = '{}'); + +-- P P P N +-- should ERROR: tf1p(anyarray, anyelement) not matched by tf1p(anyarray, int) +CREATE AGGREGATE myaggn19a(BASETYPE = anyelement, SFUNC = tf1p, + STYPE = anyarray, FINALFUNC = ffnp, INITCOND = '{}'); + +-- P P P P +-- should ERROR: ffnp(anyarray) not matched by ffnp(int[]) +CREATE AGGREGATE myaggn20a(BASETYPE = anyelement, SFUNC = tfp, + STYPE = anyarray, FINALFUNC = ffnp, INITCOND = '{}'); + +-- create test data for polymorphic aggregates +create temp table t(f1 int, f2 int[], f3 text); +insert into t values(1,array[1],'a'); +insert into t values(1,array[11],'b'); +insert into t values(1,array[111],'c'); +insert into t values(2,array[2],'a'); +insert into t values(2,array[22],'b'); +insert into t values(2,array[222],'c'); +insert into t values(3,array[3],'a'); +insert into t values(3,array[3],'b'); + +-- test the successfully created polymorphic aggregates +select f3, myaggp01a(*) from t group by f3; +select f3, myaggp03a(*) from t group by f3; +select f3, myaggp03b(*) from t group by f3; +select f3, myaggp05a(f1) from t group by f3; +select f3, myaggp06a(f1) from t group by f3; +select f3, myaggp08a(f1) from t group by f3; +select f3, myaggp09a(f1) from t group by f3; +select f3, myaggp09b(f1) from t group by f3; +select f3, myaggp10a(f1) from t group by f3; +select f3, myaggp10b(f1) from t group by f3; +select f3, myaggp20a(f1) from t group by f3; +select f3, myaggp20b(f1) from t group by f3; +select f3, myaggn01a(*) from t group by f3; +select f3, myaggn01b(*) from t group by f3; +select f3, myaggn03a(*) from t group by f3; +select f3, myaggn05a(f1) from t group by f3; +select f3, myaggn05b(f1) from t group by f3; +select f3, myaggn06a(f1) from t group by f3; +select f3, myaggn06b(f1) from t group by f3; +select f3, myaggn08a(f1) from t group by f3; +select f3, myaggn08b(f1) from t group by f3; +select f3, myaggn09a(f1) from t group by f3; +select f3, myaggn10a(f1) from t group by f3;