Remove contrib modules that have been agreed to be obsolete.

(There are more that will be removed once they've been copied to
pgfoundry.org.)
This commit is contained in:
Tom Lane 2005-06-22 22:56:29 +00:00
parent 4cc7a93d22
commit d20763dbee
71 changed files with 1 additions and 30667 deletions

View File

@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/contrib/Makefile,v 1.54 2005/03/12 15:36:24 neilc Exp $
# $PostgreSQL: pgsql/contrib/Makefile,v 1.55 2005/06/22 22:56:25 tgl Exp $
subdir = contrib
top_builddir = ..
@ -21,13 +21,9 @@ WANTED_DIRS = \
isbn_issn \
lo \
ltree \
miscutil \
mysql \
noupdate \
oid2name \
pg_autovacuum \
pg_buffercache \
pg_dumplo \
pg_trgm \
pgbench \
pgcrypto \
@ -35,26 +31,19 @@ WANTED_DIRS = \
rtree_gist \
seg \
spi \
string \
tablefunc \
tips \
tsearch \
tsearch2 \
userlock \
vacuumlo
# Missing:
# adddepend \ (does not have a makefile)
# array \ (removed all but the README)
# ipc_check \ (does not have a makefile)
# mSQL-interface \ (requires msql installed)
# mac \ (does not have a makefile)
# oracle \ (does not have a makefile)
# pg_upgrade \ (does not have a makefile)
# reindexdb \ (does not have a makefile)
# start-scripts \ (does not have a makefile)
# tools \ (does not have a makefile)
# xml \ (non-standard makefile)
# xml2 \ (non-standard makefile)

View File

@ -28,10 +28,6 @@ adddepend -
Add object dependency information to pre-7.3 objects.
by Rod Taylor <rbt@rbt.ca>
array -
Array iterator functions (now obsolete due to backend improvements)
by Massimo Dal Zotto <dz@cs.unitn.it>
btree_gist -
Support for emulating BTREE indexing in GiST
by Oleg Bartunov <oleg@sai.msu.su> and Teodor Sigaev <teodor@sigaev.ru>
@ -87,10 +83,6 @@ intarray -
Index support for arrays of int4, using GiST
by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov <oleg@sai.msu.su>
ipc_check -
Simple test script to help in configuring IPC.
FreeBSD only, for now.
isbn_issn -
PostgreSQL type extensions for ISBN (books) and ISSN (serials)
by Garrett A. Wollman <wollman@khavrinen.lcs.mit.edu>
@ -111,19 +103,6 @@ mac -
Support functions for MAC address types
by Lawrence E. Rosenman <ler@lerctr.org>
miscutil -
PostgreSQL assert checking and various utility functions
by Massimo Dal Zotto <dz@cs.unitn.it>
mysql -
Utility to convert MySQL schema dumps to SQL92 and PostgreSQL
by Thomas Lockhart <lockhart@alumni.caltech.edu>
Max Rudensky <fonin@ziet.zhitomir.ua>
Valentine Danilchuk <valdan@ziet.zhitomir.ua>
noupdate -
Trigger to prevent updates on single columns
oid2name -
Maps numeric files to table names
by B Palmer <bpalmer@crimelabs.net>
@ -140,19 +119,11 @@ pg_buffercache -
Real time queries on the shared buffer cache
by Mark Kirkwood <markir@paradise.net.nz>
pg_dumplo -
Dump large objects
by Karel Zak <zakkr@zf.jcu.cz>
pg_trgm -
Functions for determining the similarity of text based on trigram
matching.
by Oleg Bartunov <oleg@sai.msu.su> and Teodor Sigaev <teodor@sigaev.ru>
pg_upgrade -
Upgrade from previous PostgreSQL version without pg_dump/reload
by Bruce Momjian <pgman@candle.pha.pa.us>
pgbench -
TPC-B like benchmarking tool
by Tatsuo Ishii <t-ishii@sra.co.jp>
@ -183,10 +154,6 @@ spi -
start-scripts -
Scripts for starting the server at boot time.
string -
C-like input/output conversion routines for strings
by Massimo Dal Zotto <dz@cs.unitn.it>
tablefunc -
Examples of functions returning tables
@ -196,15 +163,6 @@ tips/apache_logging -
Getting Apache to log to PostgreSQL
by Terry Mackintosh <terry@terrym.com>
tools -
Assorted developer tools
by Massimo Dal Zotto <dz@cs.unitn.it>
tsearch -
Full-text-index support using GiST (obsolete version)
by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov
<oleg@sai.msu.su>.
tsearch2 -
Full-text-index support using GiST
by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov
@ -218,10 +176,6 @@ vacuumlo -
Remove orphaned large objects
by Peter T Mount <peter@retep.org.uk>
xml -
Storing XML in PostgreSQL (obsolete version)
by John Gray <jgray@azuli.co.uk>
xml2 -
Storing XML in PostgreSQL
by John Gray <jgray@azuli.co.uk>

View File

@ -1,31 +0,0 @@
Array iterator functions have been removed as of PostgreSQL 7.4, because
equivalent functionality is now available built in to the backend.
For example, previously, using contrib/array, you might have used the
following construct:
create table t(id int4[], txt text[]);
-- select tuples with some id element equal to 123
select * from t where t.id *= 123;
Now you would do this instead:
-- select tuples with some id element equal to 123
select * from t where 123 = any (t.id);
-- or you could also do this
select * from t where 123 = some (t.id);
Similarly, if using contrib/array, you did the following:
-- select tuples with all txt elements matching '^[A-Z]'
select * from t where t.txt[1:3] **~ '^[A-Z]';
Now do this instead:
-- select tuples with all txt elements matching '^[A-Z]'
select * from t where '^[A-Z]' ~ all (t.txt[1:3]);
See this section in the PostgreSQL documentation for more detail:
The SQL Language => Functions and Operators => Row and Array Comparisons

View File

@ -1,22 +0,0 @@
This simple perl script was designed under FreeBSD, and, right now, is
limited to it. It provides a simple way of determining and directing
administrators in what has to be done to get IPC working, and configured.
Usage:
ipc_check.pl
- simply checks for semaphores and shared memory being enabled
- if one or other is not enabled, appropriate "options" are provided
to get it compiled into the kernel
ipc_check.pl -B <# of buffers>
- checks to see if there are sufficient shared memory buffers to
run the postmaster with a -B option as provided
- if insufficient buffers are provided, appropriate 'sysctl' commands,
and instructions, are provided to the administrator to increase
them

View File

@ -1,51 +0,0 @@
#!/usr/bin/perl
# Notes ... -B 1 == 8k
if(@ARGV > 1) {
if($ARGV[0] eq "-B") {
$buffers = $ARGV[1];
}
}
if($buffers > 0) {
$kb_memory_required = $buffers * 8;
}
$shm = `sysctl kern.ipc | grep shmall`;
( $junk, $shm_amt ) = split(/ /, $shm);
chomp($shm_amt);
$sem = `sysctl kern.ipc | grep semmap`;
print "\n\n";
if(length($shm) > 0) {
printf "shared memory enabled: %d kB available\n", $shm_amt * 4;
if($buffers > 0) {
if($kb_memory_required / 4 > $shm_amt) {
print "\n";
print "to provide enough shared memory for a \"-B $buffers\" setting\n";
print "issue the following command\n\n";
printf "\tsysctl -w kern.ipc.shmall=%d\n", $kb_memory_required / 4;
print "\nand add the following to your /etc/sysctl.conf file:\n\n";
printf "\tkern.ipc.shmall=%d\n", $kb_memory_required / 4;
} else {
print "\n";
print "no changes to kernel required for a \"-B $buffers\" setting\n";
}
}
} else {
print "no shared memory support available\n";
print "add the following option to your kernel config:\n\n";
print "\toptions SYSVSHM\n\n";
}
print "\n==========================\n\n";
if(length($sem) > 0) {
print "semaphores enabled\n";
} else {
print "no semaphore support available\n";
print "add the following option to your kernel config:\n\n";
print "\toptions SYSVSEM\n\n";
}

View File

@ -1,15 +0,0 @@
# $PostgreSQL: pgsql/contrib/miscutil/Makefile,v 1.18 2004/08/20 20:13:05 momjian Exp $
MODULES = misc_utils
DATA_built = misc_utils.sql
DOCS = README.misc_utils
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/miscutil
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@ -1,26 +0,0 @@
Miscellaneous utility functions for PostgreSQL.
Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
This software is distributed under the GNU General Public License
either version 2, or (at your option) any later version.
backend_pid()
return the pid of our corresponding backend.
unlisten(relname)
unlisten from a relation or from all relations if the argument
is null, empty or '*'.
It is now obsoleted by the new unlisten command but still useful
if you want unlisten a name computed by the query.
Note that a listen/notify relname can be any ascii string, not
just valid relation names.
min(x,y)
max(x,y)
return the min or max of two integers.
--
Massimo Dal Zotto <dz@cs.unitn.it>

View File

@ -1,106 +0,0 @@
/*
* misc_utils.c --
*
* This file defines miscellaneous PostgreSQL utility functions.
*
* Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
*
* This file is distributed under the GNU General Public License
* either version 2, or (at your option) any later version.
*/
#include "postgres.h"
#include <unistd.h>
#include <signal.h>
#include "access/heapam.h"
#include "access/htup.h"
#include "access/relscan.h"
#include "access/skey.h"
#include "access/tupdesc.h"
#include "catalog/pg_listener.h"
#include "commands/async.h"
#include "fmgr.h"
#include "storage/lmgr.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/tqual.h"
#include "misc_utils.h"
int
backend_pid(void)
{
return getpid();
}
int
unlisten(char *relname)
{
Async_Unlisten(relname, getpid());
return 0;
}
int
int4max(int x, int y)
{
return Max(x, y);
}
int
int4min(int x, int y)
{
return Min(x, y);
}
/*
* Return the number of active listeners on a relation name.
*/
int
active_listeners(text *relname)
{
HeapTuple lTuple;
Relation lRel;
HeapScanDesc sRel;
TupleDesc tdesc;
ScanKeyData key;
Datum d;
bool isnull;
int len,
pid;
int count = 0;
int ourpid = getpid();
char listen_name[NAMEDATALEN];
lRel = heap_open(ListenerRelationId, AccessShareLock);
tdesc = RelationGetDescr(lRel);
if (relname && (VARSIZE(relname) > VARHDRSZ))
{
MemSet(listen_name, 0, NAMEDATALEN);
len = Min(VARSIZE(relname) - VARHDRSZ, NAMEDATALEN - 1);
memcpy(listen_name, VARDATA(relname), len);
ScanKeyInit(&key,
Anum_pg_listener_relname,
BTEqualStrategyNumber, F_NAMEEQ,
PointerGetDatum(listen_name));
sRel = heap_beginscan(lRel, SnapshotNow, 1, &key);
}
else
sRel = heap_beginscan(lRel, SnapshotNow, 0, (ScanKey) NULL);
while ((lTuple = heap_getnext(sRel, ForwardScanDirection)) != NULL)
{
d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
pid = DatumGetInt32(d);
if ((pid == ourpid) || (kill(pid, 0) == 0))
count++;
}
heap_endscan(sRel);
heap_close(lRel, AccessShareLock);
return count;
}

View File

@ -1,10 +0,0 @@
#ifndef MISC_UTILS_H
#define MISC_UTILS_H
int backend_pid(void);
int unlisten(char *relname);
int int4max(int x, int y);
int int4min(int x, int y);
int active_listeners(text *relname);
#endif

View File

@ -1,54 +0,0 @@
-- misc_utils.sql --
--
-- SQL code to define misc functions.
--
-- Copyright (c) 1998, Massimo Dal Zotto <dz@cs.unitn.it>
--
-- This file is distributed under the GNU General Public License
-- either version 2, or (at your option) any later version.
-- Return the pid of the backend.
--
-- Adjust this setting to control where the objects get created.
SET search_path = public;
CREATE OR REPLACE FUNCTION backend_pid()
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
-- Unlisten from a relation.
--
CREATE OR REPLACE FUNCTION "unlisten"(name)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
-- Unlisten from all relations for this backend.
--
CREATE OR REPLACE FUNCTION "unlisten"()
RETURNS int4
AS 'SELECT "unlisten"(''*'')'
LANGUAGE 'SQL';
-- min(x,y)
--
CREATE OR REPLACE FUNCTION min(int4,int4)
RETURNS int4
AS 'MODULE_PATHNAME', 'int4min'
LANGUAGE 'C' STRICT;
-- max(x,y)
--
CREATE OR REPLACE FUNCTION max(int4,int4)
RETURNS int4
AS 'MODULE_PATHNAME', 'int4max'
LANGUAGE 'C' STRICT;
-- Return the number of active listeners on a relation
--
CREATE OR REPLACE FUNCTION active_listeners(text)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C';

View File

@ -1,16 +0,0 @@
# mysql conversion Perl scripts
# $PostgreSQL: pgsql/contrib/mysql/Makefile,v 1.1 2004/11/04 06:09:21 neilc Exp $
MODULES =
SCRIPTS = my2pg.pl mysql2pgsql
DOCS = README.mysql
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/mysql
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@ -1,12 +0,0 @@
Here are two conversion utilities for MySQL dumps. Use the one you prefer.
The most recent version of my2pg.pl can be obtained from:
http://www.omnistarinc.com/~fonin/downloads.php#my2pg
my2pg.diff has additional changes for CREATE FUNCTION.
Another tool, mysql2pgsql, can be found at:
http://gborg.postgresql.org/project/mysql2psql/projdisplay.php

View File

@ -1,112 +0,0 @@
*** /laptop/my2pg.pl Mon Apr 19 18:51:44 2004
--- my2pg.pl Mon Apr 19 18:59:09 2004
***************
*** 38,43 ****
--- 38,50 ----
# $My2pg: my2pg.pl,v 1.28 2001/12/06 19:32:20 fonin Exp $
# $Id: my2pg.diff,v 1.1 2004/04/19 23:18:12 momjian Exp $
+ # Custom patch
+ # Revision 1.9 2002/08/22 00:01:39 tgl
+ # Add a bunch of pseudo-types to replace the behavior formerly associated
+ # with OPAQUE, as per recent pghackers discussion. I still want to do some
+ # more work on the 'cstring' pseudo-type, but I'm going to commit the bulk
+ # of the changes now before the tree starts shifting under me ...
+
#
# $Log: my2pg.diff,v $
# Revision 1.1 2004/04/19 23:18:12 momjian
# Update to my2pg version 1.28, add docs, update URL for newest version.
#
# Create diff of custom changes Tom made to the utility for CREATE
# FUNCTION.
#
# This will make moving this utility out of CVS easier.
#
# Revision 1.28 2002/11/30 12:03:48 fonin
***************
*** 332,342 ****
print LIBTYPES "\n * Types for table ".uc($table_name);
print LIBTYPES "\n */\n";
! $types.="\nCREATE FUNCTION $typename"."_in (opaque)
RETURNS $typename
AS '$libtypename'
LANGUAGE 'c'
! WITH (ISCACHABLE);\n";
# creating output function
my $func_out="
--- 339,349 ----
print LIBTYPES "\n * Types for table ".uc($table_name);
print LIBTYPES "\n */\n";
! $types.="\nCREATE FUNCTION $typename"."_in (cstring)
RETURNS $typename
AS '$libtypename'
LANGUAGE 'c'
! WITH (ISSTRICT, ISCACHABLE);\n";
# creating output function
my $func_out="
***************
*** 386,396 ****
return (*a>=*b);
}\n";
! $types.="\nCREATE FUNCTION $typename"."_out (opaque)
! RETURNS opaque
AS '$libtypename'
LANGUAGE 'c'
! WITH (ISCACHABLE);\n";
$types.="\nCREATE TYPE $typename (
internallength = 2,
--- 393,403 ----
return (*a>=*b);
}\n";
! $types.="\nCREATE FUNCTION $typename"."_out ($typename)
! RETURNS cstring
AS '$libtypename'
LANGUAGE 'c'
! WITH (ISSTRICT, ISCACHABLE);\n";
$types.="\nCREATE TYPE $typename (
internallength = 2,
***************
*** 532,538 ****
print LIBTYPES "\n * Types for table ".uc($table_name);
print LIBTYPES "\n */\n";
! $types.="\nCREATE FUNCTION $typename"."_in (opaque)
RETURNS $typename
AS '$libtypename'
LANGUAGE 'c';\n";
--- 539,545 ----
print LIBTYPES "\n * Types for table ".uc($table_name);
print LIBTYPES "\n */\n";
! $types.="\nCREATE FUNCTION $typename"."_in (cstring)
RETURNS $typename
AS '$libtypename'
LANGUAGE 'c';\n";
***************
*** 584,591 ****
\n";
! $types.="\nCREATE FUNCTION $typename"."_out (opaque)
! RETURNS opaque
AS '$libtypename'
LANGUAGE 'c';\n";
--- 591,598 ----
\n";
! $types.="\nCREATE FUNCTION $typename"."_out ($typename)
! RETURNS cstring
AS '$libtypename'
LANGUAGE 'c';\n";

View File

@ -1,193 +0,0 @@
<HTML>
<HEAD>
<TITLE>my2pg - MySQL -> PostgreSQL dump conversion utility.</TITLE>
<LINK REV="made" HREF="mailto:bhcompile@daffy.perf.redhat.com">
</HEAD>
<BODY>
<A NAME="__index__"></A>
<!-- INDEX BEGIN -->
<UL>
<LI><A HREF="#name">NAME</A></LI>
<LI><A HREF="#syntax">SYNTAX</A></LI>
<LI><A HREF="#overview">OVERVIEW</A></LI>
<LI><A HREF="#commandline options">COMMAND-LINE OPTIONS</A></LI>
<LI><A HREF="#side effects">SIDE EFFECTS</A></LI>
<LI><A HREF="#bugs">BUGS</A></LI>
<LI><A HREF="#authors">AUTHORS</A></LI>
<LI><A HREF="#credits">CREDITS</A></LI>
<LI><A HREF="#license">LICENSE</A></LI>
</UL>
<!-- INDEX END -->
<HR>
<P>
<H1><A NAME="name">NAME</A></H1>
<P>my2pg - MySQL -&gt; PostgreSQL dump conversion utility.</P>
<P>
<HR>
<H1><A NAME="syntax">SYNTAX</A></H1>
<PRE>
mysqldump db | ./my2pg.pl [-nds] &gt; pgsqldump.sql
vi libtypes.c
make
psql database &lt; pgsqldump.txt
where</PRE>
<DL>
<DT><STRONG><A NAME="item_pgsqldump%2Esql"><EM>pgsqldump.sql</EM></A></STRONG><BR>
<DD>
- file suitable for loading into PostgreSQL.
<P></P>
<DT><STRONG><A NAME="item_libtypes%2Ec"><EM>libtypes.c</EM></A></STRONG><BR>
<DD>
- C source for emulated MySQL types (ENUM, SET) generated by <STRONG>my2pg</STRONG>
<P></P></DL>
<P>
<HR>
<H1><A NAME="overview">OVERVIEW</A></H1>
<P><STRONG>my2pg</STRONG> utility attempts to convert MySQL database dump to Postgres's one.
<STRONG>my2pg</STRONG> performs such conversions:</P>
<UL>
<LI><STRONG><A NAME="item_Type_conversion%2E">Type conversion.</A></STRONG><BR>
It tries to find proper Postgres
type for each column.
Unknown types are silently pushing to output dump;
ENUM and SET types implemented via user types
(C source for such types can be found in
<STRONG>libtypes.c</STRONG> file);
<P></P>
<LI><STRONG><A NAME="item_Encloses_identifiers_into_double_quotes%2E">Encloses identifiers into double quotes.</A></STRONG><BR>
All column and table
names should be enclosed to double-quotes to prevent
conflict with reserved SQL keywords;
<P></P>
<LI><STRONG><A NAME="item_Converting">Converting</A></STRONG><BR>
AUTO_INCREMENT fields to SERIAL. Actually, creating the sequence and
setting default value to nextval('seq'), well, you know :)
<P></P>
<LI><STRONG>Converting</STRONG><BR>
<CODE>KEY(field)</CODE> to CREATE INDEX i_field on table (field);
<P></P>
<LI><STRONG><A NAME="item_The_same">The same</A></STRONG><BR>
for UNIQUE keys;
<P></P>
<LI><STRONG><A NAME="item_Indices">Indices</A></STRONG><BR>
are creating AFTER rows insertion (to speed up the load);
<P></P>
<LI><STRONG><A NAME="item_Translates_%27%23%27">Translates '#'</A></STRONG><BR>
MySQL comments to ANSI SQL '--'
<P></P></UL>
<P>It encloses dump in transaction block to prevent single errors
during data load.</P>
<P>
<HR>
<H1><A NAME="commandline options">COMMAND-LINE OPTIONS</A></H1>
<P>My2pg takes the following command-line options:</P>
<DL>
<DT><STRONG><A NAME="item_%2Dn">-n</A></STRONG><BR>
<DD>
Convert *CHAR DEFAULT '' NOT NULL types to *CHAR NULL.
Postgres can't load empty '' strings in NOT NULL fields.
<P></P>
<DT><STRONG><A NAME="item_%2Dd">-d</A></STRONG><BR>
<DD>
Add double quotes around table and column names
<P></P>
<DT><STRONG><A NAME="item_%2Dh">-h</A></STRONG><BR>
<DD>
Show usage banner.
<P></P>
<DT><STRONG><A NAME="item_%2Ds">-s</A></STRONG><BR>
<DD>
Do not attempt to convert data. Currently my2pg only tries to convert
date and time data.
<P></P></DL>
<P>
<HR>
<H1><A NAME="side effects">SIDE EFFECTS</A></H1>
<UL>
<LI><STRONG><A NAME="item_creates">creates</A></STRONG><BR>
file <STRONG>libtypes.c</STRONG> in current directory
overwriting existed file without any checks;
<P></P>
<LI><STRONG><A NAME="item_the_same">the same</A></STRONG><BR>
for Makefile.
<P></P></UL>
<P>
<HR>
<H1><A NAME="bugs">BUGS</A></H1>
<P>Known bugs are:</P>
<UL>
<LI><STRONG><A NAME="item_Possible_problems_with_the_timestamp_data%2E">Possible problems with the timestamp data.</A></STRONG><BR>
PostgreSQL does not accept incorrect date/time values like <STRONG>2002-00-15</STRONG>,
while MySQL does not care about that. Currently my2pg cannot handle this
issue. You should care yourself to convert such a data.
<P></P>
<LI><STRONG><A NAME="item_Use_%2Ds_option_if_your_numeric_data_are_broken_du">Use -s option if your numeric data are broken during conversion.</A></STRONG><BR>
My2pg attempts to convert MySQL timestamps of the form <STRONG>yyyymmdd</STRONG> to
<STRONG>yyyy-mm-dd</STRONG> and <STRONG>yyyymmddhhmmss</STRONG> to <STRONG>yyyy-mm-dd hh:mm:ss</STRONG>. It performs
some heuristic checks to ensure that the month,day,hour,minutes and seconds have
values from the correct range (0..12, 0..31, 0..23, 0..59, 0..59 respectively).
It is still possible that your numeric values that satisfy these conditions
will get broken.
<P></P>
<LI><STRONG><A NAME="item_Possible_problems_with_enclosing_identifiers_in_do">Possible problems with enclosing identifiers in double quotes.</A></STRONG><BR>
All identifiers such as table and column names should be enclosed in double
quotes. Program can't handle upper-case identifiers,
like DBA. Lower-case identifiers are OK.
<P></P>
<LI><STRONG><A NAME="item_SET_type_emulation_is_not_full%2E_LIKE_operation_o">SET type emulation is not full. LIKE operation on</A></STRONG><BR>
SETs, raw integer input values should be implemented
<P></P>
<LI><STRONG><A NAME="item_Makefile"><STRONG>Makefile</STRONG></A></STRONG><BR>
generated during output is
platform-dependent and surely works only on
Linux/gcc (FreeBSD/gcc probably works as well - not tested)
<P></P>
<LI><STRONG><A NAME="item_Generated_libtypes%2Ec_contain_line">Generated <STRONG>libtypes.c</STRONG> contain line</A></STRONG><BR>
<PRE>
#include &lt;postgres.h&gt;</PRE>
<P>This file may be located not in standard compiler
include path, you need to check it before compiling.</P>
</UL>
<P>
<HR>
<H1><A NAME="authors">AUTHORS</A></H1>
<P><STRONG>(c) 2000-2002 Maxim V. Rudensky (<A HREF="mailto:fonin@omnistaronline.com">fonin@ziet.zhitomir.ua</A>)</STRONG> (developer, maintainer)</P>
<P><STRONG>(c) 2000 Valentine V. Danilchuk (<A HREF="mailto:valdan@ziet.zhitomir.ua">valdan@ziet.zhitomir.ua</A>)</STRONG> (original script)</P>
<P>
<HR>
<H1><A NAME="credits">CREDITS</A></H1>
<P>Great thanks to all those people who provided feedback and make development
of this tool easier.</P>
<P>Jeff Waugh &lt;<A HREF="mailto:jaw@ic.net">jaw@ic.net</A>&gt;</P>
<P>Joakim Lemström &lt;<A HREF="mailto:jocke@bytewize.com">jocke@bytewize.com</A>&gt; || &lt;<A HREF="mailto:buddyh19@hotmail.com">buddyh19@hotmail.com</A>&gt;</P>
<P>Yunliang Yu &lt;<A HREF="mailto:yu@math.duke.edu">yu@math.duke.edu</A>&gt;</P>
<P>Brad Hilton &lt;<A HREF="mailto:bhilton@vpop.net">bhilton@vpop.net</A>&gt;</P>
<P>If you are not listed here please write to me.</P>
<P>
<HR>
<H1><A NAME="license">LICENSE</A></H1>
<P><STRONG>BSD</STRONG></P>
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View File

@ -1,283 +0,0 @@
#!/usr/bin/perl
# mysql2pgsql
# Take a MySQL schema dump and turn it into SQL92 and PostgreSQL form.
# Thomas Lockhart, (c) 2000, PostgreSQL Inc.
# Thanks to Tim Perdue at SourceForge.Net for testing and feedback.
#
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;
use IO::File;
use Getopt::Long;
my $progname = "mysql2pgsql";
my $version = "0.3";
GetOptions("debug!", "verbose!", "version", "path=s", "help", "data!");
my $debug = $opt_debug || 0;
my $verbose = $opt_verbose || 0;
my $pathfrom = $opt_path || "";
my $nodata = (! $opt_data);
$pathfrom = "$pathfrom/" if ($pathfrom =~ /.*[^\/]$/);
print "$0: $progname version $version\n"
if ($opt_version || $opt_help);
print "\t(c) 2000 Thomas Lockhart PostgreSQL Inc.\n"
if ($opt_version && $opt_verbose || $opt_help);
if ($opt_help) {
print "$0 --verbose --version --help --path=dir --nodata infile ...\n";
exit;
}
while (@ARGV) {
my $ostem;
my $oname;
my $pname;
my @xargs;
$iname = shift @ARGV;
$ostem = $iname;
$ostem = $1 if ($ostem =~ /.+\/([^\/]+)$/);
$ostem = $1 if ($ostem =~ /(.+)[.][^.]*$/);
$oname = "$ostem.sql92";
$pname = "$ostem.init";
@xargs = ($iname, $oname);
push @xargs, $pname unless ($nodata);
print "@xargs\n" if ($debug);
TransformDumpFile($iname, $oname, $pname);
}
exit;
sub TransformDumpFile {
local ($iname, $oname, $pname) = @_;
local @dlines;
local @slines;
local @plines;
local @tables; # list of tables created
local %pkeys;
local %pseqs;
local %sequences;
open(IN, "<$iname") || die "Unable to open file $iname";
while (<IN>) {
chomp;
push @dlines, $_;
}
print("Calling CreateSchema with $#dlines lines\n") if ($debug);
@slines = CreateSchema(@dlines);
open(OUT, ">$oname") || die "Unable to open output file $oname";
foreach (@slines) {
print "> $_" if ($debug);
print OUT "$_";
}
close(OUT);
return if (! defined($pname));
@plines = PopulateSchema(@tables);
open(OUT, ">$pname") || die "Unable to open output file $pname";
foreach (@plines) {
print "> $_" if ($debug);
print OUT "$_";
}
close(OUT);
}
sub PopulateSchema {
local @tables = @_;
local @out;
local $pkey;
local $pseq;
foreach (@tables) {
$table = $_;
$tpath = "$pathfrom$table";
print "Table is $table\n" if ($debug);
push @out, "\n";
push @out, "copy $table from '$tpath.txt';\n";
if (defined($pkeys{$table})) {
foreach ($pkeys{$table}) {
$pkey = $_;
$pseq = $pseqs{$table};
print "Key for $table is $pkey on $pseq\n" if ($debug);
# //push @out, "\$value = select max($pkey) from $table;\n";
push @out, "select setval ('$pseq', (select max($pkey) from $table));\n";
}
}
}
return @out;
}
sub CreateSchema {
local @lines = @_;
local @out;
# undef $last;
local %knames;
push @out, "--\n";
push @out, "-- Generated from mysql2pgsql\n";
push @out, "-- (c) 2000, Thomas Lockhart, PostgreSQL Inc.\n";
push @out, "--\n";
push @out, "\n";
while (@lines) {
$_ = shift @lines;
print "< $_\n" if ($debug);
# Replace hash comments with SQL9x standard syntax
$_ = "-- $1" if (/^[\#](.*)/);
# Found a CREATE TABLE statement?
if (/(create\s+table)\s+(\w+)\s+([(])\s*$/i) {
$table = $2;
$table = "\"$1\"" if ($table =~ /^(user)$/);
push @tables, $table;
push @tabledef, "create table $table (";
# push @out, "$_\n";
while (@lines) {
$_ = shift @lines;
print "< $_\n" if ($debug);
# Replace int(11) with SQL9x standard syntax
while (/int\(\d*\)/gi) {
$_ = "$`integer$'";
}
# Replace float(10,2) with SQL9x standard syntax
while (/(float)\((\d+),\s*(\d+)\)/gi) {
$_ = "$`$1($2)$'";
}
# Replace smallinteger with SQL9x syntax
while (/smallinteger/gi) {
$_ = "$`integer$'";
}
# Replace mediumtext with PostgreSQL syntax
while (/(longtext|mediumtext|blob|largeblob)/gi) {
$_ = "$`text$'";
}
# Replace integer ... auto_increment with PostgreSQL syntax
while (/(\s*)(\w+)\s+integer\s+(.*)\s+auto_increment/gi) {
$serid = $table . "_pk_seq";
push @out, "-- serial identifier $serid will likely be truncated\n"
if (length($serid) >= 32);
if (length($serid) >= 32) {
$excess=(length($serid)-31);
$serid = substr($table,0,-($excess)) . "_pk_seq";
push @out, "-- serial identifier $serid was truncated\n";
}
push @out, "CREATE SEQUENCE $serid;\n\n";
$pkeys{$table} = $2;
$pseqs{$table} = $serid;
push @out, "-- key is $pkeys{$table}, sequence is $pseqs{$table}\n" if ($debug);
$_ = "$`$1$2 integer default nextval('$serid') $3$'";
}
# Replace date with double-quoted name
# while (/^(\s*)(date|time)(\s+)/gi) {
# $_ = "$1\"$2\"$3$'";
# }
# Found "KEY"? Then remove it from the CREATE TABLE statement
# and instead write a CREATE INDEX statement.
if (/^\s*key\s+(\w+)\s*[(](\w[()\w\d,\s]*)[)][,]?/i) {
$iname = $1;
$column = $2;
$iname = $1 if ($iname =~ /^idx_(\w[\_\w\d]+)/);
# Sheesh, there can be upper bounds on index string sizes?
# Get rid of the length specifier (e.g. filename(45) -> filename)
while ($column =~ /(\w[\w\d])[(]\d+[)]/g) {
$column = "$`$1$'";
}
# $column = $1 if ($column =~ /(\w+)[(]\d+[)]/);
# push @out, "Index on $table($column) is $iname\n";
if (defined($knames{$iname})) {
push @out, "-- $iname already exists";
# sprintf($iname, "idx_%_%s", $table, $iname);
# $iname = "idx_" . $table . "_" . $column;
# Do not bother with more to the name; it will be too big anyway
$iname = $table . "_" . $column;
push @out, "; use $iname instead\n";
}
$knames{$iname} = $iname;
$keydef{$column} = $iname;
# push @out, "! $_\n";
# $last = $tabledef[$#tabledef];
# push @out, "? $#tabledef $last\n";
# push @out, "match $1\n" if ($last =~ /(.*),\s*$/);
# Remove the trailing comma from the previous line, if necessary
$tabledef[$#tabledef] = $1
if (($#tabledef > 0) && ($tabledef[$#tabledef] =~ /(.*),\s*$/));
# push @out, "? $tabledef[$#tabledef]\n";
# If this is the end of the statement, save it and exit loop
} elsif (/^\s*[)]\;/) {
push @tabledef, $_;
# push @out, "< $_\n";
last;
# Otherwise, just save the line
} else {
# push @out, "$last\n" if (defined($last));
# $last = $_;
push @tabledef, $_;
# push @out, "$_\n";
}
}
foreach $t (@tabledef) {
push @out, "$t\n";
}
undef @tabledef;
foreach $k (keys %keydef) {
push @out, "create index $keydef{$k} on $table ($k);\n";
}
undef %keydef;
} else {
push @out, "$_\n";
}
}
# push @out, "$last\n" if (defined($last));
foreach (keys %pkeys) {
my $val = $pkeys{$_};
print "key is $val\n" if ($debug);
}
return @out;
}
sub StripComma {
local $line = shift @_;
$line = "$1" if ($line =~ /(.*)[,]\s*$/);
return $line;
}

View File

@ -1,15 +0,0 @@
# $PostgreSQL: pgsql/contrib/noupdate/Makefile,v 1.11 2004/08/20 20:13:05 momjian Exp $
MODULES = noup
DATA_built = noup.sql
DOCS = README.noup
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/noupdate
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

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

View File

@ -1,112 +0,0 @@
/*
* noup.c -- functions to remove update permission from a column
*/
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */
#include <ctype.h> /* tolower () */
extern Datum noup(PG_FUNCTION_ARGS);
/*
* noup () -- revoke permission on column
*
* Though it's called without args You have to specify referenced
* table/column while creating trigger:
* EXECUTE PROCEDURE noup ('col').
*/
PG_FUNCTION_INFO_V1(noup);
Datum
noup(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of args specified in CREATE TRIGGER */
char **args; /* arguments: column names and table name */
int nkeys; /* # of key columns (= nargs / 2) */
Datum *kvals; /* key values */
Relation rel; /* triggered relation */
HeapTuple tuple = NULL; /* tuple to return */
TupleDesc tupdesc; /* tuple description */
bool isnull; /* to know is some column NULL or not */
int ret;
int i;
/*
* Some checks first...
*/
/* Called by trigger manager ? */
if (!CALLED_AS_TRIGGER(fcinfo))
/* internal error */
elog(ERROR, "noup: not fired by trigger manager");
/* Should be called for ROW trigger */
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
/* internal error */
elog(ERROR, "noup: can't process STATEMENT events");
/* Should not be called for INSERT */
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
/* internal error */
elog(ERROR, "noup: can't process INSERT events");
/* Should not be called for DELETE */
else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
/* internal error */
elog(ERROR, "noup: can't process DELETE events");
/* check new Tuple */
tuple = trigdata->tg_newtuple;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
args = trigger->tgargs;
nkeys = nargs;
rel = trigdata->tg_relation;
tupdesc = rel->rd_att;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
/* internal error */
elog(ERROR, "noup: SPI_connect returned %d", ret);
/*
* We use SPI plan preparation feature, so allocate space to place key
* values.
*/
kvals = (Datum *) palloc(nkeys * sizeof(Datum));
/* For each column in key ... */
for (i = 0; i < nkeys; i++)
{
/* get index of column in tuple */
int fnumber = SPI_fnumber(tupdesc, args[i]);
/* Bad guys may give us un-existing column in CREATE TRIGGER */
if (fnumber < 0)
/* internal error */
elog(ERROR, "noup: there is no attribute %s in relation %s",
args[i], SPI_getrelname(rel));
/* Well, get binary (in internal format) value of column */
kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull);
/*
* If it's NOT NULL then cancel update
*/
if (!isnull)
{
elog(WARNING, "%s: update not allowed", args[i]);
SPI_finish();
return PointerGetDatum(NULL);
}
}
SPI_finish();
return PointerGetDatum(tuple);
}

View File

@ -1,7 +0,0 @@
-- Adjust this setting to control where the objects get created.
SET search_path = public;
CREATE OR REPLACE FUNCTION noup ()
RETURNS trigger
AS 'MODULE_PATHNAME'
LANGUAGE 'C';

View File

@ -1,19 +0,0 @@
# $PostgreSQL: pgsql/contrib/pg_dumplo/Makefile,v 1.14 2005/03/25 18:17:11 momjian Exp $
PROGRAM = pg_dumplo
OBJS = main.o lo_export.o lo_import.o utils.o
PG_CPPFLAGS = -I$(libpq_srcdir)
PG_LIBS = $(libpq_pgport)
DOCS = README.pg_dumplo
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/pg_dumplo
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@ -1,148 +0,0 @@
$PostgreSQL: pgsql/contrib/pg_dumplo/README.pg_dumplo,v 1.3 2003/11/29 19:51:35 pgsql Exp $
pg_dumplo - PostgreSQL large object dumper
==========================================
By Karel Zak <zakkr@zf.jcu.cz>
Compilation:
===========
* run master ./configure in the PG source top directory
* gmake all
* gmake install
THANKS:
======
<??? I lost his e-mail ???>
* option '--all' and pg_class usage
Pavel Janík ml. <Pavel.Janik@linux.cz>
* HOWTO (the rest of this file)
How to use pg_dumplo?
=====================
(c) 2000, Pavel Janík ml. <Pavel.Janik@linux.cz>
Q: How do you use pg_dumplo?
============================
A: This is a small demo of backing up the database table with Large Objects:
We will create a demo database and a small and useless table `lo' inside
it:
SnowWhite:$ createdb test
CREATE DATABASE
Ok, our database with the name 'test' is created. Now we should create demo
table which will contain only one column with the name 'id' which will hold
the OID number of a Large Object:
SnowWhite:$ psql test
Welcome to psql, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
test=# CREATE TABLE lo (id oid);
CREATE
test=# \lo_import /etc/aliases
lo_import 19338
test=# INSERT INTO lo VALUES (19338);
INSERT 19352 1
test=# select * from lo;
id
-------
19338
(1 row)
test=# \q
In the above example you can see that we have also imported one "Large
Object" - the file /etc/aliases. It has an oid of 19338 so we have inserted
this oid number to the database table lo to the column id. The final SELECT
shows that we have one record in the table.
Now we can demonstrate the work of pg_dumplo. We will create a dump directory
which will contain the whole dump of large objects (/tmp/dump):
mkdir -p /tmp/dump
Now we can dump all large objects from the database `test' which have OIDs
stored in the column `id' in the table `lo':
SnowWhite:$ pg_dumplo -s /tmp/dump -d test -l lo.id
pg_dumplo: dump lo.id (1 large obj)
Voila, we have the dump of all Large Objects in our directory:
SnowWhite:$ tree /tmp/dump/
/tmp/dump/
`-- test
|-- lo
| `-- id
| `-- 19338
`-- lo_dump.index
3 directories, 2 files
SnowWhite:$
In practice, we'd probably use
SnowWhite:$ pg_dumplo -s /tmp/dump -d test -e
to export all large objects that are referenced by any OID-type column
in the database. Calling out specific column(s) with -l is only needed
for a selective dump.
For routine backup purposes, the dump directory could now be converted into
an archive file with tar and stored on tape. Notice that a single dump
directory can hold the dump of multiple databases.
Now, how can we recreate the contents of the table lo and the Large Object
database when something went wrong? To do this, we expect that pg_dump is
also used to store the definition and contents of the regular tables in
the database.
SnowWhite:$ pg_dump test >test.backup
Now, if we lose the database:
SnowWhite:$ dropdb test
DROP DATABASE
we can recreate it and reload the regular tables from the dump file:
SnowWhite:$ createdb test
CREATE DATABASE
SnowWhite:$ psql test <test.backup
But at this point our database has no large objects in it. What's more,
the large-object-referencing columns contain the OIDs of the old large
objects, which will not be the OIDs they'll have when reloaded. Never
fear: pg_dumplo will fix the large object references at the same time
it reloads the large objects. We reload the LO data from the dump
directory like this:
SnowWhite:$ pg_dumplo -s /tmp/dump -d test -i
19338 lo id test/lo/id/19338
SnowWhite:$
And this is everything. The contents of table lo will be automatically
updated to refer to the new large object OIDs.
Summary: In this small example we have shown that pg_dumplo can be used to
completely dump the database's Large Objects very easily.
For more information see the help ( pg_dumplo -h ).

View File

@ -1,219 +0,0 @@
/* -------------------------------------------------------------------------
* pg_dumplo
*
* $PostgreSQL: pgsql/contrib/pg_dumplo/lo_export.c,v 1.13 2004/11/28 23:49:49 tgl Exp $
*
* Karel Zak 1999-2004
* -------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "pg_dumplo.h"
extern int errno;
void
load_lolist(LODumpMaster * pgLO)
{
LOlist *ll;
int i;
int n;
/*
* Now find any candidate tables who have columns of type oid.
*
* NOTE: System tables including pg_largeobject will be ignored.
* Otherwise we'd end up dumping all LOs, referenced or not.
*
* NOTE: the system oid column is ignored, as it has attnum < 1. This
* shouldn't matter for correctness, but it saves time.
*/
pgLO->res = PQexec(pgLO->conn, "SELECT c.relname, a.attname, n.nspname "
"FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a, "
" pg_catalog.pg_type t, pg_catalog.pg_namespace n "
"WHERE a.attnum > 0 "
" AND a.attrelid = c.oid "
" AND a.atttypid = t.oid "
" AND t.typname = 'oid' "
" AND c.relkind = 'r' "
" AND c.relname NOT LIKE 'pg_%' "
" AND n.oid = c.relnamespace");
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn));
exit(RE_ERROR);
}
if ((n = PQntuples(pgLO->res)) == 0)
{
fprintf(stderr, "%s: No OID columns in the database.\n", progname);
exit(RE_ERROR);
}
pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist));
memset(pgLO->lolist, 0, (n + 1) * sizeof(LOlist));
if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR);
}
for (i = 0, ll = pgLO->lolist; i < n; i++, ll++)
{
ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
ll->lo_schema = strdup(PQgetvalue(pgLO->res, i, 2));
}
PQclear(pgLO->res);
}
void
pglo_export(LODumpMaster * pgLO)
{
LOlist *ll;
int tuples;
char path[BUFSIZ],
Qbuff[QUERY_BUFSIZ];
if (pgLO->action != ACTION_SHOW)
{
time_t t;
time(&t);
fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n");
fprintf(pgLO->index, "#\tDate: %s", ctime(&t));
fprintf(pgLO->index, "#\tHost: %s\n", pgLO->host);
fprintf(pgLO->index, "#\tDatabase: %s\n", pgLO->db);
fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user);
fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\tschema\n#\n");
}
pgLO->counter = 0;
for (ll = pgLO->lolist; ll->lo_table != NULL; ll++)
{
/*
* Query: find the LOs referenced by this column
*/
snprintf(Qbuff, QUERY_BUFSIZ,
"SELECT DISTINCT l.loid FROM \"%s\".\"%s\" x, pg_catalog.pg_largeobject l "
"WHERE x.\"%s\" = l.loid",
ll->lo_schema, ll->lo_table, ll->lo_attr);
/* puts(Qbuff); */
pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "%s: Failed to get LO OIDs:\n%s", progname,
PQerrorMessage(pgLO->conn));
}
else if ((tuples = PQntuples(pgLO->res)) == 0)
{
if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
printf("%s: no large objects in \"%s\".\"%s\".\"%s\"\n",
progname, ll->lo_schema, ll->lo_table, ll->lo_attr);
}
else
{
int t;
char *val;
/*
* Create DIR/FILE
*/
if (pgLO->action != ACTION_SHOW)
{
snprintf(path, BUFSIZ, "%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_schema);
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
snprintf(path, BUFSIZ, "%s/%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_schema, ll->lo_table);
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s", pgLO->space, pgLO->db,
ll->lo_schema, ll->lo_table, ll->lo_attr);
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
if (!pgLO->quiet)
printf("dump %s.%s.%s (%d large obj)\n",
ll->lo_schema, ll->lo_table, ll->lo_attr, tuples);
}
pgLO->counter += tuples;
for (t = 0; t < tuples; t++)
{
Oid lo;
val = PQgetvalue(pgLO->res, t, 0);
lo = atooid(val);
if (pgLO->action == ACTION_SHOW)
{
printf("%s.%s.%s: %u\n", ll->lo_schema, ll->lo_table, ll->lo_attr, lo);
continue;
}
snprintf(path, BUFSIZ, "%s/%s/%s/%s/%s/%s", pgLO->space,
pgLO->db, ll->lo_schema, ll->lo_table, ll->lo_attr, val);
if (lo_export(pgLO->conn, lo, path) < 0)
fprintf(stderr, "%s: lo_export failed:\n%s", progname,
PQerrorMessage(pgLO->conn));
else
fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s/%s\t%s\n",
val, ll->lo_table, ll->lo_attr, pgLO->db,
ll->lo_schema, ll->lo_table, ll->lo_attr,
val, ll->lo_schema);
}
}
PQclear(pgLO->res);
}
}

View File

@ -1,121 +0,0 @@
/* -------------------------------------------------------------------------
* pg_dumplo
*
* $PostgreSQL: pgsql/contrib/pg_dumplo/lo_import.c,v 1.11 2004/11/28 23:49:49 tgl Exp $
*
* Karel Zak 1999-2004
* -------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "pg_dumplo.h"
extern int errno;
void
pglo_import(LODumpMaster * pgLO)
{
LOlist loa;
Oid new_oid;
int ret, line=0;
char tab[MAX_TABLE_NAME],
attr[MAX_ATTR_NAME],
sch[MAX_SCHEMA_NAME],
path[BUFSIZ],
lo_path[BUFSIZ],
Qbuff[QUERY_BUFSIZ];
while (fgets(Qbuff, QUERY_BUFSIZ, pgLO->index))
{
line++;
if (*Qbuff == '#')
continue;
if (!pgLO->remove && !pgLO->quiet)
printf(Qbuff);
if ((ret=sscanf(Qbuff, "%u\t%s\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path, sch)) < 5)
{
/* backward compatible mode */
ret = sscanf(Qbuff, "%u\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path);
strcpy(sch, "public");
}
if (ret < 4)
{
fprintf(stderr, "%s: index file reading failed at line %d\n", progname, line);
PQexec(pgLO->conn, "ROLLBACK");
fprintf(stderr, "\n%s: ROLLBACK\n", progname);
exit(RE_ERROR);
}
loa.lo_schema = sch;
loa.lo_table = tab;
loa.lo_attr = attr;
if (path && *path=='/')
/* absolute path */
snprintf(lo_path, BUFSIZ, "%s", path);
else
snprintf(lo_path, BUFSIZ, "%s/%s", pgLO->space, path);
/*
* Import LO
*/
if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0)
{
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
PQexec(pgLO->conn, "ROLLBACK");
fprintf(stderr, "\n%s: ROLLBACK\n", progname);
exit(RE_ERROR);
}
if (pgLO->remove)
{
notice(pgLO, FALSE);
if (lo_unlink(pgLO->conn, loa.lo_oid) < 0)
fprintf(stderr, "%s: can't remove LO %u:\n%s",
progname, loa.lo_oid, PQerrorMessage(pgLO->conn));
else if (!pgLO->quiet)
printf("remove old %u and create new %u\n",
loa.lo_oid, new_oid);
notice(pgLO, TRUE);
}
pgLO->counter++;
/*
* UPDATE oid in tab
*/
snprintf(Qbuff, QUERY_BUFSIZ,
"UPDATE \"%s\".\"%s\" SET \"%s\"=%u WHERE \"%s\"=%u",
loa.lo_schema, loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid);
/*fprintf(stderr, Qbuff);*/
pgLO->res = PQexec(pgLO->conn, Qbuff);
if (PQresultStatus(pgLO->res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
PQclear(pgLO->res);
PQexec(pgLO->conn, "ROLLBACK");
fprintf(stderr, "\n%s: ROLLBACK\n", progname);
exit(RE_ERROR);
}
PQclear(pgLO->res);
}
}

View File

@ -1,307 +0,0 @@
/* -------------------------------------------------------------------------
* pg_dumplo
*
* $PostgreSQL: pgsql/contrib/pg_dumplo/main.c,v 1.22 2004/11/28 23:49:49 tgl Exp $
*
* Karel Zak 1999-2000
* -------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <errno.h>
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "pg_dumplo.h"
#ifndef HAVE_STRDUP
#include "strdup.h"
#endif
#include "getopt_long.h"
#ifndef HAVE_INT_OPTRESET
int optreset;
#endif
char *progname = NULL;
int main(int argc, char **argv);
static void usage(void);
static void parse_lolist(LODumpMaster * pgLO);
/*-----
* The mother of all C functions
*-----
*/
int
main(int argc, char **argv)
{
LODumpMaster _pgLO,
*pgLO = &_pgLO;
char *pwd = NULL;
pgLO->argv = argv;
pgLO->argc = argc;
pgLO->action = 0;
pgLO->lolist = NULL;
pgLO->user = NULL;
pgLO->db = NULL;
pgLO->host = NULL;
pgLO->port = NULL;
pgLO->space = NULL;
pgLO->index = NULL;
pgLO->remove = FALSE;
pgLO->quiet = FALSE;
pgLO->counter = 0;
pgLO->lolist_start = 0;
progname = argv[0];
/*
* Parse ARGV
*/
if (argc > 1)
{
int arg;
extern int optind;
int l_index = 0;
static struct option l_opt[] = {
{"help", no_argument, 0, 'h'},
{"user", required_argument, 0, 'u'},
{"pwd", required_argument, 0, 'p'},
{"db", required_argument, 0, 'd'},
{"host", required_argument, 0, 'h'},
{"port", required_argument, 0, 'o'},
{"space", required_argument, 0, 's'},
{"import", no_argument, 0, 'i'},
{"export", no_argument, 0, 'e'},
{"remove", no_argument, 0, 'r'},
{"quiet", no_argument, 0, 'q'},
{"all", no_argument, 0, 'a'},
{"show", no_argument, 0, 'w'},
{NULL, 0, 0, 0}
};
while ((arg = getopt_long(argc, argv, "?aeho:u:p:qd:l:t:irs:w", l_opt, &l_index)) != -1)
{
switch (arg)
{
case '?':
case 'h':
usage();
exit(RE_OK);
case 'u':
pgLO->user = strdup(optarg);
break;
case 't':
pgLO->host = strdup(optarg);
break;
case 'o':
pgLO->port = strdup(optarg);
break;
case 'p':
pwd = strdup(optarg);
break;
case 'd':
pgLO->db = strdup(optarg);
break;
case 's':
pgLO->space = strdup(optarg);
break;
case 'i':
pgLO->action = ACTION_IMPORT;
break;
case 'l':
pgLO->action = ACTION_EXPORT_ATTR;
pgLO->lolist_start = optind - 1;
parse_lolist(pgLO);
break;
case 'e':
case 'a':
pgLO->action = ACTION_EXPORT_ALL;
break;
case 'w':
pgLO->action = ACTION_SHOW;
break;
case 'r':
pgLO->remove = TRUE;
break;
case 'q':
pgLO->quiet = TRUE;
break;
default:
fprintf(stderr, "%s: bad arg -%c\n", progname, arg);
usage();
exit(RE_ERROR);
}
}
}
else
{
usage();
exit(RE_ERROR);
}
/*
* Check space
*/
if (pgLO->space==NULL && pgLO->action != ACTION_SHOW)
{
if (!(pgLO->space = getenv("PWD")))
pgLO->space = ".";
}
if (!pgLO->action)
{
fprintf(stderr, "%s: What do you want - export or import?\n", progname);
exit(RE_ERROR);
}
/*
* Make connection
*/
pgLO->conn = PQsetdbLogin(pgLO->host, pgLO->port, NULL, NULL, pgLO->db,
pgLO->user, pwd);
if (PQstatus(pgLO->conn) == CONNECTION_BAD)
{
fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn));
exit(RE_ERROR);
}
pgLO->host = PQhost(pgLO->conn) ? PQhost(pgLO->conn) : "localhost";
pgLO->db = PQdb(pgLO->conn);
pgLO->user = PQuser(pgLO->conn);
/*
* Init index file
*/
if (pgLO->action != ACTION_SHOW)
index_file(pgLO);
PQexec(pgLO->conn, "SET search_path = public");
PQexec(pgLO->conn, "BEGIN");
switch (pgLO->action)
{
case ACTION_SHOW:
case ACTION_EXPORT_ALL:
load_lolist(pgLO);
/* FALL THROUGH */
case ACTION_EXPORT_ATTR:
pglo_export(pgLO);
if (!pgLO->quiet)
{
if (pgLO->action == ACTION_SHOW)
printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter);
else
printf("\nExported %d large objects.\n\n", pgLO->counter);
}
break;
case ACTION_IMPORT:
pglo_import(pgLO);
if (!pgLO->quiet)
printf("\nImported %d large objects.\n\n", pgLO->counter);
break;
}
PQexec(pgLO->conn, "COMMIT");
PQfinish(pgLO->conn);
if (pgLO->action != ACTION_SHOW)
fclose(pgLO->index);
exit(RE_OK);
}
static void
parse_lolist(LODumpMaster * pgLO)
{
LOlist *ll;
char **d, *loc, *loc2,
buff[MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 3];
pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist));
if (!pgLO->lolist)
{
fprintf(stderr, "%s: can't allocate memory\n", progname);
exit(RE_ERROR);
}
for (d = pgLO->argv + pgLO->lolist_start, ll = pgLO->lolist;
*d != NULL;
d++, ll++)
{
strncpy(buff, *d, MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 2);
if ((loc = strchr(buff, '.')) == NULL || *(loc+1)=='\0')
{
fprintf(stderr, "%s: '%s' is bad 'table.attr' or 'schema.table.attr'\n", progname, buff);
exit(RE_ERROR);
}
loc2 = strchr(loc+1, '.');
*loc = '\0';
if (loc2)
{
/* "schema.table.attr"
*/
*loc2 = '\0';
ll->lo_schema = strdup(buff);
ll->lo_table = strdup(loc+1);
ll->lo_attr = strdup(loc2+1);
}
else
{
ll->lo_schema = strdup("public");
ll->lo_table = strdup(buff);
ll->lo_attr = strdup(loc+1);
}
}
ll++;
ll->lo_table = ll->lo_attr = (char *) NULL;
}
static void
usage(void)
{
printf("\npg_dumplo %s - PostgreSQL large objects dump\n", PG_VERSION);
puts("pg_dumplo [option]\n\n"
"-h --help this help\n"
"-u --user=<username> username for connection to server\n"
"-p --password=<password> password for connection to server\n"
"-d --db=<database> database name\n"
"-t --host=<hostname> server hostname\n"
"-o --port=<port> database server port (default: 5432)\n"
"-s --space=<dir> directory with dump tree (for export/import)\n"
"-i --import import large obj dump tree to DB\n"
"-e --export export (dump) large obj to dump tree\n"
"-l <schema.table.attr ...> dump attribute (columns) with LO to dump tree\n"
"-a --all dump all LO in DB (default)\n"
"-r --remove if is set '-i' try remove old LO\n"
"-q --quiet run quietly\n"
"-w --show not dump, but show all LO in DB\n"
"\n"
"Example (dump): pg_dumplo -d my_db -s /my_dump/dir -l t1.a t1.b t2.a\n"
" pg_dumplo -a -d my_db -s /my_dump/dir\n"
"Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n"
"Example (show): pg_dumplo -w -d my_db\n\n"
"Note: * option '-l' must be last option!\n"
" * default schema is \"public\"\n"
" * option '-i' without option '-r' make new large obj in DB\n"
" not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n"
" * if option -s is not set, pg_dumplo uses $PWD or \".\"\n"
); /* puts() */
}

View File

@ -1,83 +0,0 @@
/* -------------------------------------------------------------------------
* pg_dumplo.h
*
* $PostgreSQL: pgsql/contrib/pg_dumplo/pg_dumplo.h,v 1.11 2004/11/28 23:49:49 tgl Exp $
*
* Karel Zak 1999-2004
* -------------------------------------------------------------------------
*/
#ifndef PG_DUMPLO_H
#define PG_DUMPLO_H
#include "postgres_ext.h"
/* ----------
* Define
* ----------
*/
#define QUERY_BUFSIZ (8*1024)
#define DIR_UMASK 0755
#define FILE_UMASK 0644
#define TRUE 1
#define FALSE 0
#define RE_OK 0
#define RE_ERROR 1
#define MAX_SCHEMA_NAME 128
#define MAX_TABLE_NAME 128
#define MAX_ATTR_NAME 128
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
/* ----------
* LO struct
* ----------
*/
typedef struct
{
char *lo_schema,
*lo_table,
*lo_attr;
Oid lo_oid;
} LOlist;
typedef struct
{
int action;
LOlist *lolist;
char **argv,
*user,
*db,
*host,
*port,
*space;
FILE *index;
int counter,
argc,
lolist_start,
remove,
quiet;
PGresult *res;
PGconn *conn;
} LODumpMaster;
typedef enum
{
ACTION_NONE,
ACTION_SHOW,
ACTION_EXPORT_ATTR,
ACTION_EXPORT_ALL,
ACTION_IMPORT
} PGLODUMP_ACTIONS;
extern char *progname;
extern void notice(LODumpMaster * pgLO, int set);
extern void index_file(LODumpMaster * pgLO);
extern void load_lolist(LODumpMaster * pgLO);
extern void pglo_export(LODumpMaster * pgLO);
extern void pglo_import(LODumpMaster * pgLO);
#endif /* PG_DUMPLO_H */

View File

@ -1,97 +0,0 @@
/* -------------------------------------------------------------------------
* pg_dumplo
*
* $PostgreSQL: pgsql/contrib/pg_dumplo/utils.c,v 1.9 2004/08/29 05:06:36 momjian Exp $
*
* Karel Zak 1999-2000
* -------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "pg_dumplo.h"
extern int errno;
static void Dummy_NoticeProcessor(void *arg, const char *message);
static void Default_NoticeProcessor(void *arg, const char *message);
void
index_file(LODumpMaster * pgLO)
{
char path[BUFSIZ];
int sz;
if (pgLO->action == ACTION_SHOW)
return;
snprintf(path, BUFSIZ, "%s/%s", pgLO->space, pgLO->db);
if (pgLO->action == ACTION_EXPORT_ATTR ||
pgLO->action == ACTION_EXPORT_ALL)
{
if (mkdir(path, DIR_UMASK) == -1)
{
if (errno != EEXIST)
{
perror(path);
exit(RE_ERROR);
}
}
sz = strlen(path);
strncat(path, "/lo_dump.index", BUFSIZ - sz);
if ((pgLO->index = fopen(path, "w")) == NULL)
{
perror(path);
exit(RE_ERROR);
}
}
else if (pgLO->action != ACTION_NONE)
{
sz = strlen(path);
strncat(path, "/lo_dump.index", BUFSIZ - sz);
if ((pgLO->index = fopen(path, "r")) == NULL)
{
perror(path);
exit(RE_ERROR);
}
}
}
static
void
Dummy_NoticeProcessor(void *arg, const char *message)
{
;
}
static
void
Default_NoticeProcessor(void *arg, const char *message)
{
fprintf(stderr, "%s", message);
}
void
notice(LODumpMaster * pgLO, int set)
{
if (set)
PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL);
else
PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL);
}

View File

@ -1,16 +0,0 @@
pg_upgrade
PG_UPGRADE IS NOT AVAILABLE FOR UPGRADES FROM 7.2.X.
This is a version of pg_upgrade which will allow a 7.3 to 7.3 migration
if you need to perform an initdb. It has been only lightly tested.
Please report any problems to the PostgreSQL lists.
Read the manual page for more information. To view it:
nroff -man pg_upgrade.1 | more
Bruce Momjian
2002-07-03

View File

@ -1,492 +0,0 @@
#!/bin/sh
#
# pg_upgrade: update a database without needing a full dump/reload cycle.
# CAUTION: Read the manual page before trying to use this!
# $PostgreSQL: pgsql/contrib/pg_upgrade/pg_upgrade,v 1.16 2003/11/29 19:51:35 pgsql Exp $
#
# To migrate this to newer versions of PostgreSQL:
# 1) Update the version numbers at the top of the file
# 2) Search for specific version mentions in the script and update
# accordingly.
# 3) Add changes for next version.
#set -x
# UPGRADE_VERSION is the expected old database version
UPGRADE_VERSION="7.3"
CUR_VERSION="7.3"
# Set this to "Y" to enable this program
ENABLE="Y"
if [ "$ENABLE" != "Y" ]
then
echo "Sorry, $0 cannot upgrade database version $SRC_VERSION to $DST_VERSION." 1>&2
echo "The on-disk structure of tables has changed." 1>&2
echo "You will need to dump and restore using pg_dumpall." 1>&2
exit 1
fi
trap "rm -f /tmp/$$.*" 0 1 2 3 15
BASENAME=`basename "$0"`
PHASE=""
while [ "$#" -ne 0 ]
do
if [ "X$1" = "X-1" ]
then PHASE="1"
shift
elif [ "X$1" = "X-2" ]
then PHASE="2"
shift
elif [ "X$1" = "X-D" ]
then PGDATA="$2"
shift 2
fi
done
if [ "$PHASE" = "" ]
then echo "You must run $BASENAME in either mode 1 or mode 2." 1>&2
echo "Usage: $BASENAME [-D datadir] -1 | -2" 1>&2
exit 1
fi
if [ "$PGDATA" = "" ]
then echo "You must set the PGDATA environment variable or specify it with -D." 1>&2
echo "Usage: $BASENAME [-D datadir] -1 | -2" 1>&2
exit 1
fi
if [ ! -d "$PGDATA" ]
then echo "$PGDATA does not exist. Exiting." 1>&2
if [ "$PHASE" -eq 2 ]
then echo "Perhaps you didn't run initdb." 1>&2
fi
exit 1
fi
if [ "$USER" = "root" -o ! -r "$PGDATA"/PG_VERSION ]
then echo "You must run this as the PostgreSQL superuser. Exiting." 1>&2
exit 1
fi
# Strip off the trailing directory name and store our data there
# in the hope we are in the same filesystem so 'mv 'works.
INFODIR=`dirname "$PGDATA"`/pg_upgrade_info
SAVEDATA="$INFODIR"/data
make_dbobjoidmap()
{
psql -d template1 -At -c "SELECT datname FROM pg_database" |
grep -v '^template0$' |
while read DB
do
QUERY="SELECT relname, oid
FROM pg_class
WHERE relkind = 'r' OR
relkind = 'i' OR
relkind = 'S' OR
relkind = 't';"
psql -d "$DB" -At -F' ' -c "$QUERY" |
while read RELNAME_OID
do
echo "$DB $RELNAME_OID"
done
done
}
make_dboidmap()
{
psql -d template1 -At -F' ' -c \
'SELECT datname, oid FROM pg_database;' |
grep -v '^template0$'
}
move_objfiles()
{
# Test to make sure there is a matching file in each place
if [ ! -f "$SAVEDATA"/base/"$SRC_DBOID"/"$SRC_OID" -a \
! -h "$SAVEDATA"/base/"$SRC_DBOID"/"$SRC_OID" ]
then echo "Moving of database $DB, OID $SRC_OID, object $OBJ failed." 1>&2
echo "File not found. Exiting." 1>&2
return 1
fi
if [ ! -f "$PGDATA"/base/"$DST_DBOID"/"$DST_OID" -a \
! -h "$PGDATA"/base/"$DST_DBOID"/"$DST_OID" ]
then echo "Moving of database $DB, OID $DST_OID, object $OBJ failed." 1>&2
echo "File not found. Exiting." 1>&2
return 1
fi
# Move files
mv -f "$SAVEDATA"/base/"$SRC_DBOID"/"$SRC_OID" "$PGDATA"/base/"$DST_DBOID"/"$DST_OID"
if [ "$?" -ne 0 ]
then echo "Moving of database $DB, OID $SRC_OID, object $OBJ" 1>&2
echo "to $DST_OID failed. Exiting" 1>&2
return 1
fi
# handle table extents
ls "$SAVEDATA"/base/"$SRC_DBOID"/"$SRC_OID".* 2> /dev/null | while read FILE
do
EXT=`basename "$FILE" | sed 's/^.*\.\(.*\)$/\1/'`
mv -f "$FILE" "$PGDATA"/base/"$DST_DBOID"/"$DST_OID"."$EXT"
if [ "$?" -ne 0 ]
then echo "Moving of database $DB, OID $SRC_OID, object $OBJ" 1>&2
echo "to $DST_OID failed. Exiting." 1>&2
return 1
fi
done
}
if [ "$PHASE" -eq 1 ]
then
##########################
# Phase 1 starts here #
##########################
if [ ! -d "$PGDATA"/base/1 ]
then echo "There is no database template1 in $PGDATA/base." 1>&2
exit 1
fi
# get version
SRC_VERSION=`cat "$PGDATA"/PG_VERSION`
if [ "$SRC_VERSION" = "" ]
then echo "$BASENAME can not find the PostgreSQL version file" 1>&2
echo "'$PGDATA/PG_VERSION'. Exiting." 1>&2
exit 1
fi
if [ "$SRC_VERSION" != "$CUR_VERSION" -a \
"$SRC_VERSION" != "$UPGRADE_VERSION" ]
then echo "$BASENAME supports versions $UPGRADE_VERSION and $CUR_VERSION only." 1>&2
echo "However, your database is version $SRC_VERSION." 1>&2
echo "You will need to dump and restore using pg_dumpall. Exiting." 1>&2
exit 1
fi
# If server is down, start it so we can do some work.
if ! pg_ctl status | sed -n '1p' | grep "is running" > /dev/null 2>&1
then pg_ctl -w start
if [ $? -ne 0 ]
then echo "Can not start server. Exiting." 1>&2
exit 1
fi
fi
# create directory for our data
if ! rm -rf "$INFODIR"
then echo "Deletion of old pg_upgrade_info directory $INFODIR failed." 1>&2
echo "Exiting." 1>&2
exit 1
fi
if ! mkdir "$INFODIR"
then echo "Creation of new pg_upgrade_info directory $INFODIR failed." 1>&2
echo "Exiting." 1>&2
exit 1
fi
if ! chmod og-rwx "$INFODIR"
then echo "Permission change on new pg_upgrade_info directory $INFODIR failed." 1>&2
echo "Exiting." 1>&2
exit 1
fi
# Dump schema
pg_dumpall -s > "$INFODIR"/schema
if [ $? -ne 0 ]
then echo "Can not dump schema. Exiting." 1>&2
exit 1
fi
# Generate mappings for database
make_dboidmap > "$INFODIR"/dboidmap || exit "$?"
make_dbobjoidmap > "$INFODIR"/dbobjoidmap || exit "$?"
# Vacuum all databases to remove exipired rows.
# We will lose our transaction log file during the upgrade so we
# have to do this.
vacuumdb -a
if [ $? -ne 0 ]
then echo "Can not vacuum server. Exiting." 1>&2
exit 1
fi
# Stop server so we can move the directory.
pg_ctl -w stop
if [ $? -ne 0 ]
then echo "Can not stop server. Exiting." 1>&2
exit 1
fi
# No matter what the directory name, call it data
mv "$PGDATA" "$INFODIR"/data
if [ $? -ne 0 ]
then echo "Can not move old $PGDATA out of the way. Exiting." 1>&2
exit 1
fi
echo
echo
echo "$BASENAME phase 1 completed."
echo "Continue with the steps outlined in the $BASENAME manual page."
exit 0
fi
##########################
# Phase 2 starts here #
##########################
# check things
if [ ! -d "$INFODIR" ]
then echo "There is no '$INFODIR' directory from the phase 1 run of $BASENAME." 1>&2
exit 1
fi
if [ ! -d "$SAVEDATA" ]
then echo "There is no '$SAVEDATA' directory from the phase 1 run of $BASENAME." 1>&2
exit 1
fi
if [ ! -f "$SAVEDATA/PG_VERSION" ]
then echo "Cannot read '$SAVEDATA/PG_VERSION' --- something is wrong." 1>&2
exit 1
fi
if [ ! -f "$PGDATA/PG_VERSION" ]
then echo "Cannot read '$PGDATA/PG_VERSION' --- something is wrong." 1>&2
exit 1
fi
if [ ! -d "$PGDATA/base/1" ]
then echo "Cannot find database template1 in '$PGDATA/base'." 1>&2
echo "Are you running $BASENAME as the postgres superuser?" 1>&2
exit 1
fi
# Get the actual versions seen in the data dirs.
SRC_VERSION=`cat "$SAVEDATA"/PG_VERSION`
DST_VERSION=`cat "$PGDATA"/PG_VERSION`
# Check for version compatibility.
# This code will need to be updated/reviewed for each new PostgreSQL release.
if [ "$DST_VERSION" != "$CUR_VERSION" ]
then echo "$BASENAME is for PostgreSQL version $CUR_VERSION" 1>&2
echo "but $PGDATA/PG_VERSION contains $DST_VERSION." 1>&2
echo "Did you run initdb for version $UPGRADE_VERSION by mistake?" 1>&2
exit 1
fi
# Stop server for pg_resetxlog use
if pg_ctl status | sed -n '1p' | grep "is running" > /dev/null 2>&1
then pg_ctl -w stop
if [ $? -ne 0 ]
then echo "Can not start server. Exiting." 1>&2
exit 1
fi
fi
# check for proper pg_resetxlog version
pg_resetxlog 2> /dev/null
# file not found status is normally 127, not 1
if [ "$?" -ne 1 ]
then echo "Unable to find pg_resetxlog in your path." 1>&2
echo "Install it from pgsql/contrib/pg_resetxlog and continue. Exiting." 1>&2
exit 1
fi
if ! pg_resetxlog -x 2>&1 | grep 'xid' > /dev/null 2>&1
then echo "Old version of pg_resetxlog found in path." 1>&2
echo "Install a newer version of pg_resetxlog from pgsql/contrib/pg_resetxlog." 1>&2
echo "Exiting." 1>&2
exit 1
fi
SRC_XID=`pg_resetxlog -n "$SAVEDATA" | grep "NextXID" | awk -F' *' '{print $4}'`
DST_XID=`pg_resetxlog -n "$PGDATA" | grep "NextXID" | awk -F' *' '{print $4}'`
# compare locales to make sure they match
pg_resetxlog -n "$SAVEDATA" | grep "^LC_" > /tmp/$$.0
pg_resetxlog -n "$PGDATA" | grep "^LC_" > /tmp/$$.1
if ! diff /tmp/$$.0 /tmp/$$.1 > /dev/null
then echo "Locales do not match between the two versions. Exiting." 1>&2
exit 1
fi
# Restart postmaster
pg_ctl -w start
if [ $? -ne 0 ]
then echo "Can not start server. Exiting." 1>&2
exit 1
fi
###################################
# Checking done. Ready to proceed.
###################################
# Execute the schema script to create everything
psql template1 < "$INFODIR"/schema
if [ $? -ne 0 ]
then echo "There were errors in the input script. Exiting." 1>&2
exit 1
fi
echo "Input script completed, fixing row commit statuses..."
# Generate mappings for new database
make_dboidmap > /tmp/$$.dboidmap || exit "$?"
make_dbobjoidmap > /tmp/$$.dbobjoidmap || exit "$?"
# we are done with SQL database access
# shutdown forces buffers to disk
pg_ctl -w stop
if [ "$?" -ne 0 ]
then echo "Unable to stop database server. Exiting." 1>&2
exit 1
fi
echo "Commit fixes complete, moving data files..."
# Move table/index/sequence files
cat "$INFODIR"/dbobjoidmap | while read LINE
do
DB=`echo "$LINE" | awk '{print $1}'`
OBJ=`echo "$LINE" | awk '{print $2}'`
# Skip system tables, except for pg_largeobject
# pg_toast tables are handled later as part of the
# base table move
if [ `expr X"$OBJ" : X'pg_'` -eq 4 -a \
`expr X"$OBJ" : X'pg_largeobject'` -ne 15 ]
then continue
fi
SRC_OID=`echo "$LINE" | awk '{print $3}'`
SRC_DBOID=`grep "^$DB " "$INFODIR"/dboidmap | awk '{print $2}'`
DST_DBOID=`grep "^$DB " /tmp/$$.dboidmap | awk '{print $2}'`
DST_OID=`grep "^$DB $OBJ " /tmp/$$.dbobjoidmap | awk '{print $3}'`
move_objfiles
# Handle TOAST files if they exist
if grep "^$DB pg_toast_$SRC_OID " "$INFODIR"/dbobjoidmap \
> /dev/null 2>&1
then # toast heap
SAVE_SRC_OID="$SRC_OID"
SAVE_DST_OID="$DST_OID"
SRC_OID=`grep "^$DB pg_toast_$SAVE_SRC_OID " \
"$INFODIR"/dbobjoidmap | awk '{print $3}'`
DST_OID=`grep "^$DB pg_toast_$SAVE_DST_OID " \
/tmp/$$.dbobjoidmap | awk '{print $3}'`
move_objfiles
# toast index
SRC_OID=`grep "^$DB pg_toast_${SAVE_SRC_OID}_idx " \
"$INFODIR"/dbobjoidmap | awk '{print $3}'`
DST_OID=`grep "^$DB pg_toast_${SAVE_DST_OID}_idx " \
/tmp/$$.dbobjoidmap | awk '{print $3}'`
move_objfiles
fi
done
# Set this so future backends don't think these tuples are their own
# because it matches their own XID.
# Commit status already updated by vacuum above
# Set to maximum XID just in case SRC wrapped around recently and
# is lower than DST's database
if [ "$SRC_XID" -gt "$DST_XID" ]
then MAX_XID="$SRC_XID"
else MAX_XID="$DST_XID"
fi
pg_resetxlog -x "$MAX_XID" "$PGDATA"
if [ "$?" -ne 0 ]
then echo "Unable to set new XID. Exiting." 1>&2
exit 1
fi
# Move over old WAL
rm -r "$PGDATA"/pg_xlog
mv -f "$SAVEDATA"/pg_xlog "$PGDATA"
# Move over old clog
rm -r "$PGDATA"/pg_clog
mv -f "$SAVEDATA"/pg_clog "$PGDATA"
# Set last log file id and segment from old database
LOG_ID=`pg_resetxlog -n "$SAVEDATA" | grep "Current log file id:" |
awk -F' *' '{print $5}'`
if [ "$LOG_ID" = "" ]
then echo "Unable to get old log file id. Exiting." 1>&2
exit 1
fi
SEG_ID=`pg_resetxlog -n "$SAVEDATA" | grep "Next log file segment:" |
awk -F' *' '{print $5}'`
if [ "$SEG_ID" = "" ]
then echo "Unable to get old log segment id. Exiting." 1>&2
exit 1
fi
# Set checkpoint location of new database
pg_resetxlog -l "$LOG_ID","$SEG_ID" "$PGDATA"
if [ "$?" -ne 0 ]
then echo "Unable to set new log file/segment id. Exiting." 1>&2
exit 1
fi
# Restart server with moved data
pg_ctl -w start
if [ "$?" -ne 0 ]
then echo "Unable to restart database server. Exiting." 1>&2
exit 1
fi
# Now that we have moved the WAL/transaction log files, vacuum again to
# mark install rows with fixed transaction ids to prevent problems on xid
# wraparound.
vacuumdb -a
if [ $? -ne 0 ]
then echo "There were errors during VACUUM. Exiting." 1>&2
exit 1
fi
echo
echo
echo "$BASENAME phase 2 completed."
echo "You may remove the old database files with 'rm -r $INFODIR'."
exit 0

View File

@ -1,98 +0,0 @@
.\"
.TH PG_UPGRADE 1 "PG_UPGRADE(1)" "14 Jan 2002" "PostgreSQL Client Applications" ""
.SH NAME
pg_upgrade \- upgrading from a previous release without reloading
.SH SYNOPSIS
pg_upgrade [-D \fIdata_dir\fP] -1 | -2
.SH DESCRIPTION
\fBpg_upgrade\fP is a utility for upgrading from a previous PostgreSQL
release without reloading all the data. It can also be used as a data
recovery tool.
.LP
\fBpg_upgrade\fP must be run in two stages. In phase one you must run
\fBpg_upgrade\fP with your old database installation in place. In phase
two, \fBpg_upgrade\fP must be run on a freshly \fBinitdb\fP'ed server.
In both phases, the same newly installed \fBpg_upgrade\fP script must be
used.
.SH Upgrading PostgreSQL with pg_upgrade
.LP
1) Back up your existing data directory, preferably using
\fBpg_dumpall.\fP
.LP
2) Copy the program \fIpgsql/contrib/pg_upgrade/pg_upgrade\fP from the
current PostgreSQL distribution somewhere into your path.
.LP
3) Run phase one of \fBpg_upgrade:\fP
.LP
.B $ pg_upgrade -1
.sp
to collect information about the old database needed for the upgrade.
You may use \fI-D\fP to specify the data directory. By default it uses
the environment variable \fIPGDATA.\fP
.LP
4) Do:
.LP
.B $ cd pgsql/src
.br
.B $ make install
.sp
to install the PostgreSQL binaries for the new release.
.LP
5) Do:
.LP
.B $ cd pgsql/contrib/pg_resetxlog
.br
.B $ make install
.sp
to install the \fIpg_resetxlog\fP utility, which is needed during phase
2 of \fBpg_upgrade\fP.
.LP
6) Run initdb to create a new template1 database containing the system
tables for the new release. Make sure you use settings similar to those
used in your previous version.
.LP
7) Start the new \fIpostmaster.\fP (Note: it is critical that no users
connect to the server until the upgrade is complete. You may wish to
start the postmaster without -i or alter pg_hba.conf temporarily.)
.LP
8) Run phase two of \fBpg_upgrade:\fP
.LP
.B $ pg_upgrade -2
.sp
The program will do some checking to make sure everything is properly
configured, and will then recreate all your databases and tables,
but with no data. It will then physically move the data files
containing non-system tables and indexes into the proper
subdirectories.
.LP
9) Restore your old \fIpostmaster\fP flags or \fIpg_hba.conf\fP if
needed to allow user logins.
.sp
.LP
10) Carefully examine the contents of the upgraded databases. If you
detect problems, you'll need to recover by restoring from your full
\fBpg_dumpall\fP backup. You can delete the \fIpg_upgrade_info/\fP
directory when you are satisfied.
.LP
The upgraded databases will be in an un-vacuumed state. You will
probably want to run a \fIVACUUM ANALYZE\fP before beginning production
work.
.SH NOTES
While \fBpg_upgrade\fP is primarly an upgrade tool, it can also be used
for data recovery. During phase 1, \fBpg_upgrade\fP creates database
name / oid and database name / table name / oid mapping files in
\fIpg_upgrade_info/.\fP These files are tab-delimited. If your system is
too damaged, you may need to manually pull this information out of
\fBpg_database\fP and \fBpg_class\fP and create the files manually.
(Keep in mind most tables have \fBpg_toast_OID\fP and
\fBpg_toast_OID_idx\fP files that store very long values. These must be
recorded as well.) It also creates a schema-only \fBpg_dumpall.\fP In a
damaged installation, you may be able to make one of these from a recent
full \fBpg_dumpall.\fP
.LP
Phase 2 rebuilds each database with the schema from the old
installation. It then moves the physical data files from the old
installation and makes some modifications so the old data files work
properly in the new installation.
.SH SEE ALSO
initdb(1), postmaster(1), pg_dump(1), pg_dumpall(1), vacuumdb(1)

View File

@ -1,15 +0,0 @@
# $PostgreSQL: pgsql/contrib/string/Makefile,v 1.18 2004/08/20 20:13:08 momjian Exp $
MODULES = string_io
DATA_built = string_io.sql
DOCS = README.string_io
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/string
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

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

View File

@ -1,370 +0,0 @@
/*
* string_io.c --
*
* This file defines C-like input/output conversion routines for strings.
*
* Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
*
* This software is distributed under the GNU General Public License
* either version 2, or (at your option) any later version.
*/
#include "postgres.h"
#include <ctype.h>
#include "utils/builtins.h"
#include "string_io.h"
/* define this if you want to see iso-8859 characters */
#define ISO8859
#define VALUE(char) ((char) - '0')
#define DIGIT(val) ((val) + '0')
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
#ifndef ISO8859
#define NOTPRINTABLE(c) (!isprint((unsigned char) (c)))
#else
#define NOTPRINTABLE(c) (!isprint((unsigned char) (c)) && \
((unsigned char) (c) < (unsigned char) 0xa0))
#endif
/*
* string_output() --
*
* This function takes a pointer to a string data and an optional
* data size and returns a printable representation of the string
* translating all escape sequences to C-like \nnn or \c escapes.
* The function is used by output methods of various string types.
*
* Arguments:
* data - input data (can be NULL)
* size - optional size of data. A negative value indicates
* that data is a null terminated string.
*
* Returns:
* a pointer to a new string containing the printable
* representation of data.
*/
unsigned char *
string_output(unsigned char *data, int size)
{
register unsigned char c,
*p,
*r,
*result;
register int l,
len;
if (data == NULL)
{
result = (char *) palloc(2);
result[0] = '-';
result[1] = '\0';
return (result);
}
if (size < 0)
size = strlen(data);
/* adjust string length for escapes */
len = size;
for (p = data, l = size; l > 0; p++, l--)
{
switch (*p)
{
case '\\':
case '"':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
len++;
break;
case '{':
/* Escape beginning of string, to distinguish from arrays */
if (p == data)
len++;
break;
default:
if (NOTPRINTABLE(*p))
len += 3;
}
}
len++;
result = (char *) palloc(len);
for (p = data, r = result, l = size; (l > 0) && (c = *p); p++, l--)
{
switch (c)
{
case '\\':
case '"':
*r++ = '\\';
*r++ = c;
break;
case '\b':
*r++ = '\\';
*r++ = 'b';
break;
case '\f':
*r++ = '\\';
*r++ = 'f';
break;
case '\n':
*r++ = '\\';
*r++ = 'n';
break;
case '\r':
*r++ = '\\';
*r++ = 'r';
break;
case '\t':
*r++ = '\\';
*r++ = 't';
break;
case '\v':
*r++ = '\\';
*r++ = 'v';
break;
case '{':
/* Escape beginning of string, to distinguish from arrays */
if (p == data)
*r++ = '\\';
*r++ = c;
break;
default:
if (NOTPRINTABLE(c))
{
*r = '\\';
r += 3;
*r-- = DIGIT(c & 07);
c >>= 3;
*r-- = DIGIT(c & 07);
c >>= 3;
*r = DIGIT(c & 03);
r += 3;
}
else
*r++ = c;
}
}
*r = '\0';
return ((char *) result);
}
/*
* string_input() --
*
* This function accepts a C string in input and copies it into a new
* object allocated with palloc() translating all escape sequences.
* An optional header can be allocated before the string, for example
* to hold the length of a varlena object.
* This function is not necessary for input from sql commands because
* the parser already does escape translation, all data input routines
* receive strings in internal form.
*
* Arguments:
* str - input string possibly with escapes
* size - the required size of new data. A value of 0
* indicates a variable size string, while a
* negative value indicates a variable size string
* of size not greater than this absolute value.
* hdrsize - size of an optional header to be allocated before
* the data. It must then be filled by the caller.
* rtn_size - an optional pointer to an int variable where the
* size of the new string is stored back.
*
* Returns:
* a pointer to the new string or the header.
*/
unsigned char *
string_input(unsigned char *str, int size, int hdrsize, int *rtn_size)
{
register unsigned char *p,
*r;
unsigned char *result;
int len;
if ((str == NULL) || (hdrsize < 0))
return (char *) NULL;
/* Compute result size */
len = strlen(str);
for (p = str; *p;)
{
if (*p++ == '\\')
{
if (ISOCTAL(*p))
{
if (ISOCTAL(*(p + 1)))
{
p++;
len--;
}
if (ISOCTAL(*(p + 1)))
{
p++;
len--;
}
}
if (*p)
p++;
len--;
}
}
/* result has variable length */
if (size == 0)
size = len + 1;
else
/* result has variable length with maximum size */
if (size < 0)
size = Min(len, -size) + 1;
result = (char *) palloc(hdrsize + size);
memset(result, 0, hdrsize + size);
if (rtn_size)
*rtn_size = size;
r = result + hdrsize;
for (p = str; *p;)
{
register unsigned char c;
if ((c = *p++) == '\\')
{
switch (c = *p++)
{
case '\0':
p--;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
c = VALUE(c);
if (isdigit(*p))
c = (c << 3) + VALUE(*p++);
if (isdigit(*p))
c = (c << 3) + VALUE(*p++);
*r++ = c;
break;
case 'b':
*r++ = '\b';
break;
case 'f':
*r++ = '\f';
break;
case 'n':
*r++ = '\n';
break;
case 'r':
*r++ = '\r';
break;
case 't':
*r++ = '\t';
break;
case 'v':
*r++ = '\v';
break;
default:
*r++ = c;
}
}
else
*r++ = c;
}
return ((char *) result);
}
unsigned char *
c_charout(int32 c)
{
char str[2];
str[0] = (char) c;
str[1] = '\0';
return (string_output(str, 1));
}
/*
* This can be used for SET, bytea, text and unknown data types
*/
unsigned char *
c_textout(struct varlena * vlena)
{
int len = 0;
char *s = NULL;
if (vlena)
{
len = VARSIZE(vlena) - VARHDRSZ;
s = VARDATA(vlena);
}
return (string_output(s, len));
}
/*
* This can be used for varchar and bpchar strings
*/
unsigned char *
c_varcharout(unsigned char *s)
{
int len = 0;
if (s)
{
len = *(int32 *) s - 4;
s += 4;
}
return (string_output(s, len));
}
#if 0
struct varlena *
c_textin(unsigned char *str)
{
struct varlena *result;
int len;
if (str == NULL)
return ((struct varlena *) NULL);
result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len);
VARSIZE(result) = len;
return (result);
}
int32 *
c_charin(unsigned char *str)
{
return (string_input(str, 1, 0, NULL));
}
#endif
/* end of file */
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/

View File

@ -1,24 +0,0 @@
#ifndef STRING_IO_H
#define STRING_IO_H
unsigned char *string_output(unsigned char *data, int size);
unsigned char *string_input(unsigned char *str, int size, int hdrsize,
int *rtn_size);
unsigned char *c_charout(int32 c);
unsigned char *c_textout(struct varlena * vlena);
unsigned char *c_varcharout(unsigned char *s);
#if 0
struct varlena *c_textin(unsigned char *str);
int32 *
c_charin(unsigned char *str)
#endif
#endif
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/

View File

@ -1,84 +0,0 @@
-- string_io.sql --
--
-- SQL code to define the new string I/O functions
--
-- Copyright (c) 1998, Massimo Dal Zotto <dz@cs.unitn.it>
--
-- This file is distributed under the GNU General Public License
-- either version 2, or (at your option) any later version.
-- Define the new output functions.
--
CREATE FUNCTION c_charout(bpchar)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION c_textout(text)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION c_varcharout(varchar)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
-- This is not needed because escapes are handled by the parser
--
-- CREATE FUNCTION c_textin(cstring)
-- RETURNS text
-- AS 'MODULE_PATHNAME'
-- LANGUAGE 'c';
-- Define a function which sets the new output routines for char types.
--
-- SELECT c_mode();
--
CREATE FUNCTION c_mode()
RETURNS text
AS ' UPDATE pg_type SET typoutput=''c_textout'' WHERE typname=''SET'';
UPDATE pg_type SET typoutput=''c_varcharout'' WHERE typname=''bpchar'';
UPDATE pg_type SET typoutput=''c_textout'' WHERE typname=''bytea'';
UPDATE pg_type SET typoutput=''c_charout'' WHERE typname=''char'';
UPDATE pg_type SET typoutput=''c_textout'' WHERE typname=''text'';
UPDATE pg_type SET typoutput=''c_textout'' WHERE typname=''unknown'';
UPDATE pg_type SET typoutput=''c_varcharout'' WHERE typname=''varchar'';
select ''c_mode''::text;'
LANGUAGE 'SQL';
-- Define a function which restores the standard routines for char types.
--
-- SELECT pg_mode();
--
CREATE FUNCTION pg_mode()
RETURNS text
AS ' UPDATE pg_type SET typoutput=''textout'' WHERE typname=''SET'';
UPDATE pg_type SET typoutput=''varcharout'' WHERE typname=''bpchar'';
UPDATE pg_type SET typoutput=''textout'' WHERE typname=''bytea'';
UPDATE pg_type SET typoutput=''charout'' WHERE typname=''char'';
UPDATE pg_type SET typoutput=''textout'' WHERE typname=''text'';
UPDATE pg_type SET typoutput=''textout'' WHERE typname=''unknown'';
UPDATE pg_type SET typoutput=''varcharout'' WHERE typname=''varchar'';
select ''pg_mode''::text;'
LANGUAGE 'SQL';
-- Use these to do the changes manually.
--
-- UPDATE pg_type SET typoutput='textout' WHERE typname='SET';
-- UPDATE pg_type SET typoutput='varcharout' WHERE typname='bpchar';
-- UPDATE pg_type SET typoutput='textout' WHERE typname='bytea';
-- UPDATE pg_type SET typoutput='charout' WHERE typname='char';
-- UPDATE pg_type SET typoutput='textout' WHERE typname='text';
-- UPDATE pg_type SET typoutput='textout' WHERE typname='unknown';
-- UPDATE pg_type SET typoutput='varcharout' WHERE typname='varchar';
--
-- UPDATE pg_type SET typoutput='c_textout' WHERE typname='SET';
-- UPDATE pg_type SET typoutput='c_varcharout' WHERE typname='bpchar';
-- UPDATE pg_type SET typoutput='c_textout' WHERE typname='bytea';
-- UPDATE pg_type SET typoutput='c_charout' WHERE typname='char';
-- UPDATE pg_type SET typoutput='c_textout' WHERE typname='text';
-- UPDATE pg_type SET typoutput='c_textout' WHERE typname='unknown';
-- UPDATE pg_type SET typoutput='c_varcharout' WHERE typname='varchar';
-- end of file

View File

@ -1,28 +0,0 @@
#!/bin/bash
#
# Add local variables to C sources files to set emacs C style to 4-space tabs.
#
# Usage: cd $PG_HOME && add-emacs-variables `find . -name \*.[chy] -print`
for f in $*; do
if [ -L $f ] || grep -q '^ \* Local Variables:' $f; then
continue
fi
echo $f
touch -r $f /tmp/.add-local-variables.$$
cat <<- ' EOF' >> $f
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/
EOF
touch -r /tmp/.add-local-variables.$$ $f
done
rm -f /tmp/.add-local-variables.$$
# end of file

View File

@ -1,50 +0,0 @@
#!/bin/echo Usage: source
#
# Set the shell variables files, cfiles, hfiles, yfiles and sfiles with
# the names of all .c, .h, .y, and .S files in current directory tree.
# Define also some shell functions to grep the files. Typical usage is:
#
# $ cd src/
# $ source ../contrib/tools/find-sources
# $ gh BLCKSZ # grep BLCKSZ in .h files
# $ gcl MAXTUPLEN # list all .c files containing MAXTUPLEN
#
# THIS SCRIPT MUST BE SOURCED FROM BASH.
#
# Copyright (C) 1999 Massimo Dal Zotto <dz@cs.unitn.it>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
# Build the file lists
dir=${1-`pwd`}/
cfiles=`find $dir -name \*.c | sort`
hfiles=`find $dir -name \*.h | sort`
yfiles=`find $dir -name \*.y | sort`
sfiles=`find $dir -name \*.S | sort`
files="$hfiles $cfiles $yfiles $sfiles"
# Define some functions to grep the files in the lists
function g() { grep -- "$*" $files /dev/null; }
function gc() { grep -- "$*" $cfiles /dev/null; }
function gh() { grep -- "$*" $hfiles /dev/null; }
function gy() { grep -- "$*" $yfiles /dev/null; }
function gS() { grep -- "$*" $sfiles /dev/null; }
function gl() { grep -l -- "$*" $files /dev/null; }
function gcl() { grep -l -- "$*" $cfiles /dev/null; }
function ghl() { grep -l -- "$*" $hfiles /dev/null; }
function gyl() { grep -l -- "$*" $yfiles /dev/null; }
function gSl() { grep -l -- "$*" $sfiles /dev/null; }
# end of file

View File

@ -1,9 +0,0 @@
#!/bin/bash
#
# Makes an emacs tagfile for all .[chS] and .el files in the current
# directory tree.
etags $(find . -name \*.h) 2>/dev/null || true
etags -a $(find . -name \*.c) 2>/dev/null || true
etags -a $(find . -name \*.S) 2>/dev/null || true
etags -a $(find . -name \*.el) 2>/dev/null || true

View File

@ -1,35 +0,0 @@
# $PostgreSQL: pgsql/contrib/tsearch/Makefile,v 1.5 2004/08/20 20:13:08 momjian Exp $
PG_CPPFLAGS = -I.
MODULE_big = tsearch
OBJS = crc32.o morph.o txtidx.o query.o gistidx.o rewrite.o
DATA_built = tsearch.sql
DOCS = README.tsearch
REGRESS = tsearch
EXTRA_CLEAN = parser.c
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/tsearch
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif
# parser is compiled as part of query
query.o: parser.c
parser.c: parser.l
ifdef FLEX
$(FLEX) $(FLEXFLAGS) -8 -Ptsearch_yy -o'$@' $<
else
@$(missing) flex $< $@
endif
# DO NOT DELETE

View File

@ -1,420 +0,0 @@
==========================================================================
This module is deprecated in 7.4 version of PostgreSQL and will be
obsoleted in 8.0. Please, use new tsearch2 contrib module.
==========================================================================
Tsearch contrib module contains implementation of new data type txtidx -
a searchable data type (textual) with indexed access.
All work was done by Teodor Sigaev (teodor@stack.net) and Oleg Bartunov
(oleg@sai.msu.su).
CHANGES:
August 29, 2002
Space usage and using CLUSTER command documented
August 22, 2002
Fix works with 'bad' queries
August 13, 2002
Use parser of OpenFTS v0.33.
IMPORTANT NOTICE:
This is a first step of our work on integration of OpenFTS
full text search engine (http://openfts.sourceforge.net/) into
PostgreSQL. It's based on our recent development of GiST
(Generalized Search Tree) for PostgreSQL 7.2 (see our GiST page
at http://www.sai.msu.su/~megera/postgres/gist/ for info about GiST)
and will works only for PostgreSQL version 7.2 and later.
We didn't try to implement a full-featured search engine with
stable interfaces but rather experiment with various approaches.
There are many issues remains (most of them just not documented or
implemented) but we'd like to present a working prototype
of full text search engine fully integrated into PostgreSQL to
collect user's feedback and recommendations.
INSTALLATION:
cd contrib/tsearch
gmake
gmake install
REGRESSION TEST:
gmake installcheck
USAGE:
psql DATABASE < tsearch.sql (from contrib/tsearch)
INTRODUCTION:
This module provides an implementation of a new data type 'txtidx' which is
a string of a space separated "words". "Words" with spaces
should be enclosed in apostrophes and apostrophes inside a "word" should be
escaped by backslash.
This is quite different from OpenFTS approach which uses array
of integers (ID of lexems) and requires storing of lexem-id pairs in database.
One of the prominent benefit of this new approach is that it's possible now
to perform full text search in a 'natural' way.
Some examples:
create table foo (
titleidx txtidx
);
2 regular words:
insert into foo values ( 'the are' );
Word with space:
insert into foo values ( 'the\\ are' );
Words with apostrophe:
insert into foo values ( 'value\'s this' );
Complex word with apostrophe:
insert into foo values ( 'value\'s this we \'PostgreSQL site\'' );
select * from foo where titleidx @@ '\'PostgreSQL site\' | this';
select * from foo where titleidx @@ 'value\'s | this';
select * from foo where titleidx @@ '(the|this)&!we';
test=# select 'two words'::txtidx;
txtidx
---------------
'two' 'words'
(1 row)
test=# select 'single\\ word'::txtidx;
txtidx
---------------
'single word'
(1 row)
FULL TEXT SEARCH:
The basic idea of this data type is to use it for full text search inside
database. If you have a 'text' column title and corresponding column
titleidx of type 'txtidx', which contains the same information from
text column, then search on title could be replaced by
searching on titleidx which would be fast because of indexed access.
As a real life example consider database with table 'titles' containing
titles of mailing list postings in column 'title':
create table titles (
title text
);
Suppose, you already have a lot of titles and want to do full text search
on them.
First, you need to install contrib/tsearch module (see INSTALLATION and USAGE).
Add column 'titleidx' of type txtidx, containing space separated words from
title. It's possible to use function txt2txtidx(title) to fill 'titleidx'
column (see notice 1):
-- add titleidx column of type txtidx
alter table titles add titleidx txtidx;
update titles set titleidx=txt2txtidx(title);
Create index on titleidx:
create index t_idx on titles using gist(titleidx);
and now you can search all titles with words 'patch' and 'gist':
select title from titles where titleidx ## 'patch&gist';
Here, ## is a new operation defined for type 'txtidx' which could use index
(if exists) built on titleidx. This operator uses morphology to
expand query, i.e.
## 'patches&gist' will find titles with 'patch' and 'gist' also.
If you want to provide query as is, use operator @@ instead:
select title from titles where titleidx @@ 'patch&gist';
but remember, that function txt2txtidx does uses morphology, so you need
to fill column 'titleidx' using some another way. We hope in future releases
provide more consistent and convenient interfaces.
Query could contains boolean operators &,|,!,() with their usual meaning,
for example: 'patch&gist&!cvs', 'patch|cvs'.
Each operation ( ##, @@ ) requires appropriate query type -
txtidx ## mquery_txt
txtidx @@ query_txt
To see what query actually will be used :
test=# select 'patches&gist'::mquery_txt;
mquery_txt
------------------
'patch' & 'gist'
(1 row)
test=# select 'patches&gist'::query_txt;
query_txt
--------------------
'patches' & 'gist'
(1 row)
Notice the difference !
You could use trigger to be sure column 'titleidx' is consistent
with any changes in column 'title':
create trigger txtidxupdate before update or insert on titles
for each row execute procedure tsearch(titleidx, title);
This trigger uses the same parser, dictionaries as function
txt2txtidx (see notice 1).
Current syntax allows creating trigger for several columns
you want to be searchable:
create trigger txtidxupdate before update or insert on titles
for each row execute procedure tsearch(titleidx, title1, title2,... );
Use function txtidxsize(titleidx) to get the number of "words" in column
titleidx. To get total number of words in table titles:
test=# select sum(txtidxsize(titleidx)) from titles;
sum
---------
1917182
(1 row)
NOTICES:
1.
function txt2txtidx and trigger use parser, dictionaries coming with
this contrib module on default. Parser is mostly the same as in OpenFTS and
dictionaries are simple stemmers (sort of Lovin's stemmer which uses a
longest match algorithm.) for english and russian languages. There is a perl
script makedict/makedict.pl, which could be used to create specific
dictionaries from files with endings and stop-words.
Example files for english and russian languages are available
from http://www.sai.msu.su/~megera/postgres/gist/tsearch/.
Run script without parameters to see information about arguments and options.
Example:
cd makedict
./makedict.pl -l LOCALNAME -e FILEENDINGS -s FILESTOPWORD \
-o ../dict/YOURDICT.dct
Another options of makedict.pl:
-f do not execute tolower for any char
-a function of checking stopword will be work after lemmatize,
default is before
You need to edit dict.h to use your dictionary and, probably,
morph.c to change mapdict array.
Don't forget to do
make clean; make; make install
2.
txtidx doesn't preserve words ordering (this is not critical for searching)
for performance reason, for example:
test=# select 'page two'::txtidx;
txtidx
--------------
'two' 'page'
(1 row)
3.
Indexed access provided by txtidx data type isn't always good
because of internal data structure we use (RD-Tree). Particularly,
queries like '!gist' will be slower than just a sequential scan,
because for such queries RD-Tree doesn't provides selectivity on internal
nodes and all checks should be processed at leaf nodes, i.t. scan of
full index. You may play with function query_tree to see how effective
will be index usage:
test=# select querytree( 'patch&gist'::query_txt );
querytree
------------------
'patch' & 'gist'
(1 row)
This is an example of "good" query - index will effective for both words.
test=# select querytree( 'patch&!gist'::query_txt );
querytree
-----------
'patch'
(1 row)
This means that index is effective only to search word 'patch' and resulted
rows will be checked against '!gist'.
test=# select querytree( 'patch|!gist'::query_txt );
querytree
-----------
T
(1 row)
test=# select querytree( '!gist'::query_txt );
querytree
-----------
T
(1 row)
These two queries will be processed by scanning of full index !
Very slow !
4.
Following selects produce the same result
select title from titles where titleidx @@ 'patch&gist';
select title from titles where titleidx @@ 'patch' and titleidx @@ 'gist';
but the former will be more effective, because of internal optimization
of query executor.
TODO:
Better configurability (as in OpenFTS)
User's interfaces to parser, dictionaries ...
Write documentation
BENCHMARKS:
We use test collection in our experiments which contains 377905
titles from various mailing lists stored in our mailware
project.
All runs were performed on IBM ThinkPad T21 notebook with
PIII 733 Mhz, 256 RAM, 20 Gb HDD, Linux 2.2.19, postgresql 7.2.dev
We didn't do extensive benchmarking and all
numbers provide for illustration. Actual performance
is strongly depends on many factors (query, collection, dictionaries
and hardware).
Collection is available for download from
http://www.sai.msu.su/~megera/postgres/gist/tsearch/mw_titles.gz
(377905 titles from postgresql mailing lists, about 3Mb).
0. install contrib/tsearch module
1. createdb test
2. psql test < tsearch.sql (from contrib/tsearch)
3. zcat mw_titles.gz | psql test
(it will creates table, copy test data and creates index)
Database contains one table:
test=# \d titles
Table "titles"
Column | Type | Modifiers
----------+------------------------+-----------
title | character varying(256) |
titleidx | txtidx |
Indexes: t_idx
Index was created as:
create index t_idx on titles using gist(titleidx);
(notice: this operation takes about 14 minutes on my notebook)
Typical select looks like:
select title from titles where titleidx @@ 'patch&gist';
Total number of lexems in collection : 1917182
1. We trust index - we consider index is exact and no
checking against tuples is necessary.
update pg_amop set amopreqcheck = false where amopclaid =
(select oid from pg_opclass where opcname = 'gist_txtidx_ops');
using gist indices
1: titleidx @@ 'patch&gist' 0.000u 0.000s 0m0.054s 0.00%
2: titleidx @@ 'patch&gist' 0.020u 0.000s 0m0.045s 44.82%
3: titleidx @@ 'patch&gist' 0.000u 0.000s 0m0.044s 0.00%
using gist indices (morph)
1: titleidx ## 'patch&gist' 0.000u 0.010s 0m0.046s 21.62%
2: titleidx ## 'patch&gist' 0.010u 0.010s 0m0.046s 43.47%
3: titleidx ## 'patch&gist' 0.000u 0.000s 0m0.046s 0.00%
disable gist index
1: titleidx @@ 'patch&gist' 0.000u 0.010s 0m1.601s 0.62%
2: titleidx @@ 'patch&gist' 0.000u 0.000s 0m1.607s 0.00%
3: titleidx @@ 'patch&gist' 0.010u 0.000s 0m1.607s 0.62%
traditional like
1: title ~* 'gist' and title ~* 'patch' 0.010u 0.000s 0m9.206s 0.10%
2: title ~* 'gist' and title ~* 'patch' 0.000u 0.010s 0m9.205s 0.10%
3: title ~* 'gist' and title ~* 'patch' 0.010u 0.000s 0m9.208s 0.10%
2. Need to check results against tuples to avoid possible hash collision.
update pg_amop set amopreqcheck = true where amopclaid =
(select oid from pg_opclass where opcname = 'gist_txtidx_ops');
using gist indices
1: titleidx @@ 'patch&gist' 0.010u 0.000s 0m0.052s 19.26%
2: titleidx @@ 'patch&gist' 0.000u 0.000s 0m0.045s 0.00%
3: titleidx @@ 'patch&gist' 0.010u 0.000s 0m0.045s 22.39%
using gist indices (morph)
1: titleidx ## 'patch&gist' 0.000u 0.000s 0m0.046s 0.00%
2: titleidx ## 'patch&gist' 0.000u 0.010s 0m0.046s 21.75%
3: titleidx ## 'patch&gist' 0.020u 0.000s 0m0.047s 42.13%
There are no visible difference between these 2 cases but your
mileage may vary.
NOTES:
1. The size of txtidx column should be lesser than size of corresponding column.
Below some real numbers from test database (link above).
a) After loading data
-rw------- 1 postgres users 23191552 Aug 29 14:08 53016937
-rw------- 1 postgres users 81059840 Aug 29 14:08 52639027
Table titles (52639027) occupies 80Mb, index on txtidx column (53016937)
occupies 22Mb. Use contrib/oid2name to get mappings from oid to names.
After doing
test=# select title into titles_tmp from titles;
SELECT
I got size of table 'titles' without txtidx field
-rw------- 1 postgres users 30105600 Aug 29 14:14 53016938
So, txtidx column itself occupies about 50Mb.
b) after running 'vacuum full analyze' I got:
-rw------- 1 postgres users 30105600 Aug 29 14:26 53016938
-rw------- 1 postgres users 36880384 Aug 29 14:26 53016937
-rw------- 1 postgres users 51494912 Aug 29 14:26 52639027
53016938 = titles_tmp
So, actual size of 'txtidx' field is 20 Mb ! "quod erat demonstrandum"
2. CLUSTER command is highly recommended if you need fast searching.
For example:
test=# cluster t_idx on titles;
BUT ! In 7.2 CLUSTER command forgets about other indices and permissions,
so you need be carefull and rebuild these indices and restore permissions
after clustering. Also, clustering isn't dynamic, so you'd need to
use CLUSTER from time to time. In 7.3 CLUSTER command should works
fine.
after clustering:
-rw------- 1 postgres users 23404544 Aug 29 14:59 53394850
-rw------- 1 postgres users 30105600 Aug 29 14:26 53016938
-rw------- 1 postgres users 50995200 Aug 29 14:45 53394845
pg@zen:/usr/local/pgsql/data/base/52638986$ oid2name -d test
All tables from database "test":
---------------------------------
53394850 = t_idx
53394845 = titles
53016938 = titles_tmp

View File

@ -1,103 +0,0 @@
/* Both POSIX and CRC32 checksums */
#include <sys/types.h>
#include <stdio.h>
#include <sys/types.h>
#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 <srg@quick.com>
*/
#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;
}

View File

@ -1,10 +0,0 @@
#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

View File

@ -1,500 +0,0 @@
\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

View File

@ -1,33 +0,0 @@
#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 *descr[];
#endif

View File

@ -1,8 +0,0 @@
#define TABLE_DICT_START ,{
#define TABLE_DICT_END }
#include "dict/porter_english.dct"
#include "dict/russian_stemming.dct"
#undef TABLE_DICT_START
#undef TABLE_DICT_END

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,752 +0,0 @@
--
-- first, define the datatype. Turn off echoing so that expected file
-- does not depend on contents of seg.sql.
--
\set ECHO none
psql:tsearch.sql:9: NOTICE: type "txtidx" is not yet defined
DETAIL: Creating a shell type definition.
psql:tsearch.sql:14: NOTICE: argument type txtidx is only a shell
psql:tsearch.sql:38: NOTICE: type "query_txt" is not yet defined
DETAIL: Creating a shell type definition.
psql:tsearch.sql:43: NOTICE: argument type query_txt is only a shell
psql:tsearch.sql:55: NOTICE: type "mquery_txt" is not yet defined
DETAIL: Creating a shell type definition.
psql:tsearch.sql:61: NOTICE: argument type mquery_txt is only a shell
psql:tsearch.sql:156: NOTICE: type "gtxtidx" is not yet defined
DETAIL: Creating a shell type definition.
psql:tsearch.sql:161: NOTICE: argument type gtxtidx is only a shell
--txtidx
SELECT '1'::txtidx;
txtidx
--------
'1'
(1 row)
SELECT '1 '::txtidx;
txtidx
--------
'1'
(1 row)
SELECT ' 1'::txtidx;
txtidx
--------
'1'
(1 row)
SELECT ' 1 '::txtidx;
txtidx
--------
'1'
(1 row)
SELECT '1 2'::txtidx;
txtidx
---------
'1' '2'
(1 row)
SELECT '\'1 2\''::txtidx;
txtidx
--------
'1 2'
(1 row)
SELECT '\'1 \\\'2\''::txtidx;
txtidx
---------
'1 \'2'
(1 row)
SELECT '\'1 \\\'2\'3'::txtidx;
txtidx
-------------
'3' '1 \'2'
(1 row)
SELECT '\'1 \\\'2\' 3'::txtidx;
txtidx
-------------
'3' '1 \'2'
(1 row)
SELECT '\'1 \\\'2\' \' 3\' 4 '::txtidx;
txtidx
------------------
'4' ' 3' '1 \'2'
(1 row)
--query_txt
SELECT '1'::query_txt;
query_txt
-----------
'1'
(1 row)
SELECT '1 '::query_txt;
query_txt
-----------
'1'
(1 row)
SELECT ' 1'::query_txt;
query_txt
-----------
'1'
(1 row)
SELECT ' 1 '::query_txt;
query_txt
-----------
'1'
(1 row)
SELECT '\'1 2\''::query_txt;
query_txt
-----------
'1 2'
(1 row)
SELECT '\'1 \\\'2\''::query_txt;
query_txt
-----------
'1 \'2'
(1 row)
SELECT '!1'::query_txt;
query_txt
-----------
!'1'
(1 row)
SELECT '1|2'::query_txt;
query_txt
-----------
'1' | '2'
(1 row)
SELECT '1|!2'::query_txt;
query_txt
------------
'1' | !'2'
(1 row)
SELECT '!1|2'::query_txt;
query_txt
------------
!'1' | '2'
(1 row)
SELECT '!1|!2'::query_txt;
query_txt
-------------
!'1' | !'2'
(1 row)
SELECT '!(!1|!2)'::query_txt;
query_txt
------------------
!( !'1' | !'2' )
(1 row)
SELECT '!(!1|2)'::query_txt;
query_txt
-----------------
!( !'1' | '2' )
(1 row)
SELECT '!(1|!2)'::query_txt;
query_txt
-----------------
!( '1' | !'2' )
(1 row)
SELECT '!(1|2)'::query_txt;
query_txt
----------------
!( '1' | '2' )
(1 row)
SELECT '1&2'::query_txt;
query_txt
-----------
'1' & '2'
(1 row)
SELECT '!1&2'::query_txt;
query_txt
------------
!'1' & '2'
(1 row)
SELECT '1&!2'::query_txt;
query_txt
------------
'1' & !'2'
(1 row)
SELECT '!1&!2'::query_txt;
query_txt
-------------
!'1' & !'2'
(1 row)
SELECT '(1&2)'::query_txt;
query_txt
-----------
'1' & '2'
(1 row)
SELECT '1&(2)'::query_txt;
query_txt
-----------
'1' & '2'
(1 row)
SELECT '!(1)&2'::query_txt;
query_txt
------------
!'1' & '2'
(1 row)
SELECT '!(1&2)'::query_txt;
query_txt
----------------
!( '1' & '2' )
(1 row)
SELECT '1|2&3'::query_txt;
query_txt
-----------------
'1' | '2' & '3'
(1 row)
SELECT '1|(2&3)'::query_txt;
query_txt
-----------------
'1' | '2' & '3'
(1 row)
SELECT '(1|2)&3'::query_txt;
query_txt
---------------------
( '1' | '2' ) & '3'
(1 row)
SELECT '1|2&!3'::query_txt;
query_txt
------------------
'1' | '2' & !'3'
(1 row)
SELECT '1|!2&3'::query_txt;
query_txt
------------------
'1' | !'2' & '3'
(1 row)
SELECT '!1|2&3'::query_txt;
query_txt
------------------
!'1' | '2' & '3'
(1 row)
SELECT '!1|(2&3)'::query_txt;
query_txt
------------------
!'1' | '2' & '3'
(1 row)
SELECT '!(1|2)&3'::query_txt;
query_txt
----------------------
!( '1' | '2' ) & '3'
(1 row)
SELECT '(!1|2)&3'::query_txt;
query_txt
----------------------
( !'1' | '2' ) & '3'
(1 row)
SELECT '1|(2|(4|(5|6)))'::query_txt;
query_txt
-----------------------------------------
'1' | ( '2' | ( '4' | ( '5' | '6' ) ) )
(1 row)
SELECT '1|2|4|5|6'::query_txt;
query_txt
-----------------------------------------
( ( ( '1' | '2' ) | '4' ) | '5' ) | '6'
(1 row)
SELECT '1&(2&(4&(5&6)))'::query_txt;
query_txt
-----------------------------
'1' & '2' & '4' & '5' & '6'
(1 row)
SELECT '1&2&4&5&6'::query_txt;
query_txt
-----------------------------
'1' & '2' & '4' & '5' & '6'
(1 row)
SELECT '1&(2&(4&(5|6)))'::query_txt;
query_txt
---------------------------------
'1' & '2' & '4' & ( '5' | '6' )
(1 row)
SELECT '1&(2&(4&(5|!6)))'::query_txt;
query_txt
----------------------------------
'1' & '2' & '4' & ( '5' | !'6' )
(1 row)
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::query_txt;
query_txt
------------------------------------------
'1' & '2' & ' 4' & ( '|5' | '6 \' !|&' )
(1 row)
SELECT '1'::mquery_txt;
mquery_txt
------------
'1'
(1 row)
SELECT '1 '::mquery_txt;
mquery_txt
------------
'1'
(1 row)
SELECT ' 1'::mquery_txt;
mquery_txt
------------
'1'
(1 row)
SELECT ' 1 '::mquery_txt;
mquery_txt
------------
'1'
(1 row)
SELECT '\'1 2\''::mquery_txt;
mquery_txt
------------
'1' & '2'
(1 row)
SELECT '\'1 \\\'2\''::mquery_txt;
mquery_txt
------------
'1' & '2'
(1 row)
SELECT '!1'::mquery_txt;
mquery_txt
------------
!'1'
(1 row)
SELECT '1|2'::mquery_txt;
mquery_txt
------------
'1' | '2'
(1 row)
SELECT '1|!2'::mquery_txt;
mquery_txt
------------
'1' | !'2'
(1 row)
SELECT '!1|2'::mquery_txt;
mquery_txt
------------
!'1' | '2'
(1 row)
SELECT '!1|!2'::mquery_txt;
mquery_txt
-------------
!'1' | !'2'
(1 row)
SELECT '!(!1|!2)'::mquery_txt;
mquery_txt
------------------
!( !'1' | !'2' )
(1 row)
SELECT '!(!1|2)'::mquery_txt;
mquery_txt
-----------------
!( !'1' | '2' )
(1 row)
SELECT '!(1|!2)'::mquery_txt;
mquery_txt
-----------------
!( '1' | !'2' )
(1 row)
SELECT '!(1|2)'::mquery_txt;
mquery_txt
----------------
!( '1' | '2' )
(1 row)
SELECT '1&2'::mquery_txt;
mquery_txt
------------
'1' & '2'
(1 row)
SELECT '!1&2'::mquery_txt;
mquery_txt
------------
!'1' & '2'
(1 row)
SELECT '1&!2'::mquery_txt;
mquery_txt
------------
'1' & !'2'
(1 row)
SELECT '!1&!2'::mquery_txt;
mquery_txt
-------------
!'1' & !'2'
(1 row)
SELECT '(1&2)'::mquery_txt;
mquery_txt
------------
'1' & '2'
(1 row)
SELECT '1&(2)'::mquery_txt;
mquery_txt
------------
'1' & '2'
(1 row)
SELECT '!(1)&2'::mquery_txt;
mquery_txt
------------
!'1' & '2'
(1 row)
SELECT '!(1&2)'::mquery_txt;
mquery_txt
----------------
!( '1' & '2' )
(1 row)
SELECT '1|2&3'::mquery_txt;
mquery_txt
-----------------
'1' | '2' & '3'
(1 row)
SELECT '1|(2&3)'::mquery_txt;
mquery_txt
-----------------
'1' | '2' & '3'
(1 row)
SELECT '(1|2)&3'::mquery_txt;
mquery_txt
---------------------
( '1' | '2' ) & '3'
(1 row)
SELECT '1|2&!3'::mquery_txt;
mquery_txt
------------------
'1' | '2' & !'3'
(1 row)
SELECT '1|!2&3'::mquery_txt;
mquery_txt
------------------
'1' | !'2' & '3'
(1 row)
SELECT '!1|2&3'::mquery_txt;
mquery_txt
------------------
!'1' | '2' & '3'
(1 row)
SELECT '!1|(2&3)'::mquery_txt;
mquery_txt
------------------
!'1' | '2' & '3'
(1 row)
SELECT '!(1|2)&3'::mquery_txt;
mquery_txt
----------------------
!( '1' | '2' ) & '3'
(1 row)
SELECT '(!1|2)&3'::mquery_txt;
mquery_txt
----------------------
( !'1' | '2' ) & '3'
(1 row)
SELECT '1|(2|(4|(5|6)))'::mquery_txt;
mquery_txt
-----------------------------------------
'1' | ( '2' | ( '4' | ( '5' | '6' ) ) )
(1 row)
SELECT '1|2|4|5|6'::mquery_txt;
mquery_txt
-----------------------------------------
( ( ( '1' | '2' ) | '4' ) | '5' ) | '6'
(1 row)
SELECT '1&(2&(4&(5&6)))'::mquery_txt;
mquery_txt
-----------------------------
'1' & '2' & '4' & '5' & '6'
(1 row)
SELECT '1&2&4&5&6'::mquery_txt;
mquery_txt
-----------------------------
'1' & '2' & '4' & '5' & '6'
(1 row)
SELECT '1&(2&(4&(5|6)))'::mquery_txt;
mquery_txt
---------------------------------
'1' & '2' & '4' & ( '5' | '6' )
(1 row)
SELECT '1&(2&(4&(5|!6)))'::mquery_txt;
mquery_txt
----------------------------------
'1' & '2' & '4' & ( '5' | !'6' )
(1 row)
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::mquery_txt;
mquery_txt
---------------------------------
'1' & '2' & '4' & ( '5' | '6' )
(1 row)
SELECT 'querty-fgries | http://www.google.com/index.html | www.rambler.ru/index.shtml'::mquery_txt;
mquery_txt
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
( 'querty-fgri' & 'querti' & 'fgri' | 'www.google.com/index.html' & 'www.google.com' & '/index.html' ) | 'www.rambler.ru/index.shtml' & 'www.rambler.ru' & '/index.shtml'
(1 row)
CREATE TABLE test_txtidx( t text, a txtidx );
\copy test_txtidx from 'data/test_tsearch.data'
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr|qh';
count
-------
80
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr&qh';
count
-------
6
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq&yt';
count
-------
1
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq|yt';
count
-------
47
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq&yt)|(wr&qh)';
count
-------
7
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq|yt)&(wr|qh)';
count
-------
11
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'wR|qh';
count
-------
80
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'wR&qh';
count
-------
6
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'eq&yt';
count
-------
1
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'eq|yt';
count
-------
47
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## '(eq&yt)|(wR&qh)';
count
-------
7
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## '(eq|yt)&(wR|qh)';
count
-------
11
(1 row)
create index wowidx on test_txtidx using gist (a);
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr|qh';
count
-------
80
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr&qh';
count
-------
6
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq&yt';
count
-------
1
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq|yt';
count
-------
47
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq&yt)|(wr&qh)';
count
-------
7
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq|yt)&(wr|qh)';
count
-------
11
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'wR|qh';
count
-------
80
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'wR&qh';
count
-------
6
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'eq&yt';
count
-------
1
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## 'eq|yt';
count
-------
47
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## '(eq&yt)|(wR&qh)';
count
-------
7
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## '(eq|yt)&(wR|qh)';
count
-------
11
(1 row)
SELECT txt2txtidx('345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
txt2txtidx
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'ad' 'dw' 'jf' '234' '345' '4.2' '455' 'jqw' 'qwe' 'wer' 'wow' 'asdf' 'ewr1' 'qwer' 'sdjk' '5.005' 'ewri2' 'qwqwe' 'wefjn' 'gist.c' 'gist.h' 'qwerti' '234.435' ':8100/?' 'qwe-wer' 'readlin' 'www.com' '+4.0e-10' 'gist.h.c' 'rewt/ewr' 'qwe@efd.r' 'readline-4' '/?ad=qwe&dw' '/wqe-324/ewr' 'aew.werc.ewr' '1aew.werc.ewr' '2aew.werc.ewr' '3aew.werc.ewr' '4aew.werc.ewr' '5aew.werc.ewr' '6aew.werc.ewr' '7aew.werc.ewr' '/usr/local/fff' '/awdf/dwqe/4325' ':8100/?ad=qwe&dw' 'teodor@stack.net' '5aew.werc.ewr:8100/?' ':8100/?ad=qwe&dw=%20%32' 'aew.werc.ewr/?ad=qwe&dw' '1aew.werc.ewr/?ad=qwe&dw' '3aew.werc.ewr/?ad=qwe&dw' '6aew.werc.ewr:8100/?ad=qwe&dw' '7aew.werc.ewr:8100/?ad=qwe&dw=%20%32'
(1 row)
SELECT txtidxsize(txt2txtidx('345 qw'));
txtidxsize
------------
2
(1 row)
SELECT txtidxsize(txt2txtidx('345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty'));
txtidxsize
------------
53
(1 row)
INSERT INTO test_txtidx (a) VALUES ('345 qwerty');
CREATE TRIGGER txtidxupdate
BEFORE UPDATE OR INSERT ON test_txtidx
FOR EACH ROW EXECUTE PROCEDURE tsearch(a, t);
INSERT INTO test_txtidx (t) VALUES ('345 qwerty');
SELECT count(*) FROM test_txtidx WHERE a @@ '345&qwerty';
count
-------
1
(1 row)
SELECT count(*) FROM test_txtidx WHERE a ## '345&qwerty';
count
-------
1
(1 row)
UPDATE test_txtidx SET t = null WHERE t = '345 qwerty';
SELECT count(*) FROM test_txtidx WHERE a ## '345&qwerty';
count
-------
0
(1 row)
SELECT count(*) FROM test_txtidx WHERE a @@ '345&qwerty';
count
-------
1
(1 row)

View File

@ -1,783 +0,0 @@
#include "postgres.h"
#include <float.h>
#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 "txtidx.h"
#include "query.h"
#include "gistidx.h"
#include "crc32.h"
PG_FUNCTION_INFO_V1(gtxtidx_in);
Datum gtxtidx_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_out);
Datum gtxtidx_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_compress);
Datum gtxtidx_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_decompress);
Datum gtxtidx_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_consistent);
Datum gtxtidx_consistent(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_union);
Datum gtxtidx_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_same);
Datum gtxtidx_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_penalty);
Datum gtxtidx_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtxtidx_picksplit);
Datum gtxtidx_picksplit(PG_FUNCTION_ARGS);
#define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(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
gtxtidx_in(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("gtxtidx_in not implemented")));
PG_RETURN_DATUM(0);
}
Datum
gtxtidx_out(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("gtxtidx_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
gtxtidx_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval = entry;
if (entry->leafkey)
{ /* txtidx */
GISTTYPE *res;
txtidx *val = (txtidx *) 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;
}
/* 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);
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
gtxtidx_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
gtxtidx_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(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(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
gtxtidx_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int *size = (int *) PG_GETARG_POINTER(1);
BITVEC base;
int4 i,
len;
int4 flag = 0;
GISTTYPE *result;
MemSet((void *) base, 0, sizeof(BITVEC));
for (i = 0; i < entryvec->n; 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
gtxtidx_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;
}
Datum
gtxtidx_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);
int4 unionsize = 0;
BITVECP orig = GETSIGN(origval);
if (ISALLTRUE(origval))
{
*penalty = 0.0;
PG_RETURN_POINTER(penalty);
}
if (ISARRKEY(newval))
{
int4 *ptr = GETARR(newval),
n = ARRNELEM(newval);
while (n--)
{
if (GETBIT(orig, HASHVAL(*ptr)) == 0)
unionsize++;
ptr++;
}
*penalty = (float) unionsize;
}
else
{
if (ISALLTRUE(newval))
*penalty = (float) (SIGLENBIT - sizebitvec(orig));
else
{
char valtmp;
BITVECP nval = GETSIGN(newval);
int4 i;
LOOPBYTE(
valtmp = nval[i] | orig[i];
unionsize += SUMBIT(valtmp) - SUMBIT(orig[i]);
);
*penalty = (float) unionsize;
}
}
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;
}
Datum
gtxtidx_picksplit(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
OffsetNumber k,
j;
GISTTYPE *datum_l,
*datum_r;
BITVEC union_l,
union_r;
bool firsttime = true;
int4 size_alpha,
size_beta,
sizeu,
sizei;
int4 size_waste,
waste = 0.0;
int4 size_l,
size_r;
int4 nbytes;
OffsetNumber seed_1 = 0,
seed_2 = 0;
OffsetNumber *left,
*right;
OffsetNumber maxoff;
BITVECP ptra,
ptrb,
ptrc;
int i;
CACHESIGN *cache;
char valtmp;
SPLITCOST *costvector;
maxoff = entryvec->n - 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));
if (cache[k].allistrue || cache[j].allistrue)
{
sizeu = SIGLENBIT;
if (cache[k].allistrue && cache[j].allistrue)
sizei = SIGLENBIT;
else
sizei = (cache[k].allistrue) ?
sizebitvec(cache[j].sign) : sizebitvec(cache[k].sign);
}
else
{
sizeu = sizei = 0;
ptra = cache[j].sign;
ptrb = cache[k].sign;
/* critical section for bench !!! */
#define COUNT(pos) do { \
if ( GETBITBYTE(*(char*)ptra,pos) ) { \
sizeu++; \
if ( GETBITBYTE(*(char*)ptrb, pos) ) \
sizei++; \
} else if ( GETBITBYTE(*(char*)ptrb, pos) ) \
sizeu++; \
} while(0)
LOOPBYTE(
COUNT(0);
COUNT(1);
COUNT(2);
COUNT(3);
COUNT(4);
COUNT(5);
COUNT(6);
COUNT(7);
ptra = (BITVECP) (((char *) ptra) + 1);
ptrb = (BITVECP) (((char *) ptrb) + 1);
);
}
size_waste = sizeu - sizei;
if (size_waste > waste || firsttime)
{
waste = size_waste;
seed_1 = k;
seed_2 = j;
firsttime = false;
}
}
}
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;
size_l = SIGLENBIT;
}
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));
size_l = sizebitvec(GETSIGN(datum_l));
}
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;
size_r = SIGLENBIT;
}
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));
size_r = sizebitvec(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;
if (cache[j].allistrue)
{
size_alpha = SIGLENBIT - size_l;
size_beta = SIGLENBIT - size_r;
}
else
{
ptra = cache[seed_1].sign;
ptrb = cache[seed_2].sign;
ptrc = cache[j].sign;
size_beta = size_alpha = 0;
if (cache[seed_1].allistrue)
{
if (!cache[seed_2].allistrue)
{
LOOPBIT(
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
size_beta++;
);
}
}
else if (cache[seed_2].allistrue)
{
if (!cache[seed_1].allistrue)
{
LOOPBIT(
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
size_alpha++;
);
}
}
else
{
LOOPBIT(
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
size_alpha++;
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
size_beta++;
);
}
}
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)
size_alpha = SIGLENBIT;
else
{
ptra = cache[j].sign;
ptrb = GETSIGN(datum_l);
size_alpha = 0;
LOOPBYTE(
valtmp = union_l[i] = ptra[i] | ptrb[i];
size_alpha += SUMBIT(valtmp);
);
}
if (ISALLTRUE(datum_r) || cache[j].allistrue)
size_beta = SIGLENBIT;
else
{
ptra = cache[j].sign;
ptrb = GETSIGN(datum_r);
size_beta = 0;
LOOPBYTE(
valtmp = union_r[i] = ptra[i] | ptrb[i];
size_beta += SUMBIT(valtmp);
);
}
if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
{
if (!ISALLTRUE(datum_l))
{
if (size_alpha == SIGLENBIT)
{
if (size_alpha != size_l)
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
}
else
memcpy((void *) GETSIGN(datum_l), (void *) union_l, sizeof(BITVEC));
}
size_l = size_alpha;
*left++ = j;
v->spl_nleft++;
}
else
{
if (!ISALLTRUE(datum_r))
{
if (size_beta == SIGLENBIT)
{
if (size_beta != size_r)
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
}
else
memcpy((void *) GETSIGN(datum_r), (void *) union_r, sizeof(BITVEC));
}
size_r = size_beta;
*right++ = j;
v->spl_nright++;
}
}
*right = *left = FirstOffsetNumber;
v->spl_ldatum = PointerGetDatum(datum_l);
v->spl_rdatum = PointerGetDatum(datum_r);
PG_RETURN_POINTER(v);
}

View File

@ -1,64 +0,0 @@
#ifndef __GISTIDX_H__
#define __GISTIDX_H__
/*
#define GISTIDX_DEBUG
*/
/*
* signature defines
*/
#define BITBYTE 8
#define SIGLENINT 64 /* >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<SIGLEN;i++) {\
a;\
}
#define LOOPBIT(a) \
for(i=0;i<SIGLENBIT;i++) {\
a;\
}
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
#define GETBITBYTE(x,i) ( ((char)(x)) >> (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 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

View File

@ -1,303 +0,0 @@
#!/usr/bin/perl
use strict;
use Getopt::Std;
use locale;
my %opt;
getopts('l:he:s:ap:o:m:f', \%opt);
if ( $opt{h} || ! ($opt{e}||$opt{s}) || !$opt{l} ) {
print<<EOT;
Generator of variant of the Lovin's stemmer which
uses a longest match algorithm.
Author Teodor Sigaev <teodor\@stack.net>
Usage:
$0 -l LOCALENAME [ -e FILENAME ] [ -s FILENAME ] [ -p PREFIX ] [ -o FILENAME ] [ -a ] [ -m NUMBER ]
-e FILENAME - file with endings of word
-s FILENAME - file with list of stop-word
-o FILENAME - out file, default STDOUT
-a - stop-word are strimmed
-p PREFIX - prefix of function and etc, default strimmed locale
-m NUMBER - minimal length of rest after semming, default 3
-l LOCALENAME - name of locale
-f - do not call tolower for each char
At least one of -e or -s must be defined
EOT
exit;
}
if ( ! defined $opt{p} ) {
$opt{p} = $opt{l};
$opt{p}=~s/[^a-zA-Z0-9_]+//g;
}
$opt{m}=3 if ! defined $opt{m};
my ($enddata,$stopdata) = ('','');
my $maxchild = 0;
if ( $opt{e} ) {
my @tree;
buildtree(\@tree, $opt{e}, 1);
printstruct( \@tree, 0, \$enddata);
undef @tree;
}
if ( $opt{s} ) {
my @tree;
buildtree(\@tree, $opt{s}, 0);
printstruct( \@tree, 0, \$stopdata);
undef @tree;
}
die "No data\n" if ( ! (length $enddata || length $stopdata) );
$enddata = "\t{0,0,0,0}" if ( ! length $enddata );
$stopdata = "\t{0,0,0,0}" if ( ! length $stopdata );
my $fh=\*STDOUT;
if ( $opt{o} ) {
open(OUT,">$opt{o}") || die "Can;t open file '$opt{o}' for writing\n";
$fh = \*OUT;
}
my $linktype = 'uint32';
if ( $maxchild <= 0xff ) {
$linktype='uint8';
} elsif ( $maxchild <= 0xffff ) {
$linktype='uint16';
}
my $wherecheck = ( $opt{a} ) ?
"NULL,\n\t$opt{p}_is_stopword"
:
"$opt{p}_is_stopword,\n\tNULL";
my ($tolower, $resttolower) = ('','');
if ( ! $opt{f} ) {
$tolower = '*cur = tolower( *cur );';
$resttolower=<<EOT;
while( cur - buf >= 0 ) {
*cur = tolower(*cur);
cur--;
}
EOT
}
print {$fh} <<EOT;
/*
* Autogenerated file
*
* Variant of the Lovin's stemmer which uses a longest match algorithm.
* Endings are stored in a suffix tree.
*/
#ifdef DICT_BODY
#include <ctype.h>
typedef struct {
uint8 val;
uint8 flag;
uint8 right;
$linktype child;
} $opt{p}_NODE;
/* is exists left tree ? */
#define L 0x01
/* finish word flag */
#define F 0x02
#define ISLEFT(x) ((($opt{p}_NODE*)x)->flag & L)
#define ISFINISH(x) ((($opt{p}_NODE*)x)->flag & F)
#define MINLENREST $opt{m}
static $opt{p}_NODE $opt{p}_endstree[]={
$enddata
};
static $opt{p}_NODE $opt{p}_stoptree[]={
$stopdata
};
static char*
$opt{p}_stem( void* obj, char *in, int *len ) {
$opt{p}_NODE *ptr = $opt{p}_endstree;
int result = 0;
uint8 *buf = (uint8 *)in;
uint8 *cur = buf + (*len) - 1;
while( cur - buf >= MINLENREST ) {
$tolower
if ( ptr->val == *cur ) {
if ( ISFINISH(ptr) ) result = buf + (*len) - cur;
cur--;
if ( ! ptr->child ) break;
ptr += ptr->child;
} else if ( ptr->val > *cur ) {
if ( ISLEFT(ptr) )
ptr++;
else
break;
} else {
if ( ptr->right )
ptr += ptr->right;
else
break;
}
}
$resttolower
*len -= result;
return in;
}
static int
$opt{p}_is_stopword( void *obj, char *in, int len ) {
$opt{p}_NODE *ptr = $opt{p}_stoptree;
int result = 0;
uint8 *buf = (uint8 *)in;
uint8 *cur = buf;
while( cur - buf < len ) {
$tolower
if ( ptr->val == *cur ) {
cur++;
if ( ISFINISH(ptr) ) result = cur - buf;
if ( ! ptr->child ) break;
ptr += ptr->child;
} else if ( ptr->val > *cur ) {
if ( ISLEFT(ptr) )
ptr++;
else
break;
} else {
if ( ptr->right )
ptr += ptr->right;
else
break;
}
}
return (result==len) ? 1 : 0;
}
#undef L
#undef F
#undef ISLEFT
#undef ISFINISH
#undef MINLENREST
#endif /* DICT_BODY */
#ifdef DICT_TABLE
TABLE_DICT_START
\"$opt{l}\",
NULL,
NULL,
$opt{p}_stem,
$wherecheck
TABLE_DICT_END
#endif
EOT
close($fh) if ( $fh != \*STDOUT );
sub buildtree {
my ($reftree,$file, $needreverse) = @_;
open(DATA,$file) || die "Can't open file '$file'\n";
while(<DATA>) {
chomp;
next if ! length $_;
$_ = lc($_) if ! $opt{f};
addtostruct( $reftree, ( $needreverse ) ? scalar(reverse($_)) : $_ );
}
close DATA;
}
sub mkbintree {
my ( $start, $stop, $rprop, $rres) = @_;
my $middle = $start + int( ($stop-$start)/2 );
push( @$rres, $rprop->[$middle] );
my $idx = $#$rres;
$rres->[$idx]{right}=0;
$rres->[$idx]{left}=0;
return 1 if ( $start == $stop );
my $leftsize = 0;
if ( $middle!=$start ) {
$rres->[$idx]{left}=1;
$leftsize = mkbintree( $start, $middle-1, $rprop, $rres );
$rres->[$idx]{right}=$leftsize+1;
} else {
$rres->[$idx]{right} = 1;
}
return 1 + $leftsize + mkbintree( $middle+1, $stop, $rprop, $rres );
}
sub addtostruct {
my $node = shift;
my ($char, $subval) = split('', shift, 2);
$char = ord( $char );
if ( ! defined $node->[$char] ) {
$node->[$char] = {};
$node->[$char]{finish} = length $subval;
$node->[$char]{child} = [];
} elsif ( ! length $subval ) {
$node->[$char]{finish} = 0;
}
addtostruct( $node->[$char]{child}, $subval ) if ( length $subval );
}
sub printstruct {
my ($node, $pre, $refout) = @_;
my $add = 0;
my @prop;
my $outchild;
my $current = 0;
my $poschild=0;
my @tmp;
foreach my $i ( 0..255 ) {
next if ( !defined $node->[ $i ] );
push @prop , { val=>$i,
nchild=>printstruct( $node->[ $i ]{child}, 1, \$outchild ),
poschild=>$poschild };
$poschild += $prop[$#prop]{nchild};
}
return 0 if $#prop < 0;
if ($pre) {
$$refout .= ",\n\n";
}
mkbintree(0,$#prop,\@prop,\@tmp);
@prop = @tmp;
$current=$#prop+1;
foreach my $i ( 0..$#prop ) {
my $flag = ($prop[$i]{left}) ? 'L' : undef;
if ( $node->[ $prop[$i]{val} ]{finish}==0 ) {
$flag .= '|' if defined $flag;
$flag .= 'F';
} elsif ( ! defined $flag ) {
$flag='0';
}
$$refout .= "\t{'".chr( $prop[$i]{val} )."',".
$flag.','.
$prop[$i]{right}.','.
(($prop[$i]{nchild}==0)?0:($prop[$i]{poschild}+$current)).'}'.
(($i==$#prop)? '' : ",\n");
$maxchild = $prop[$i]{poschild}+$current if
( $prop[$i]{nchild} && $prop[$i]{poschild}+$current > $maxchild );
$current--;
$add += $prop[$i]{nchild};
}
$$refout .= $outchild;
return $#prop+1 + $add;
}

View File

@ -1,214 +0,0 @@
/*
* morphology module
* New dictionary is include in dict.h. For languages which
* use latin charset it may be need to modify mapdict table.
* Teodor Sigaev <teodor@stack.net>
*/
#include "postgres.h"
#include <locale.h>
#include "utils/builtins.h"
#include "morph.h"
#include "deflex.h"
/*
* Struct for calling dictionaries
* All of this methods are optional, but
* if all methods are NULL, then dictionary does nothing :)
* Return value of lemmatize must be palloced or the same.
* Return value of init must be malloced in other case
* it will be free in end of transaction!
*/
typedef struct
{
char localename[NAMEDATALEN];
/* init dictionary */
void *(*init) (void);
/* close dictionary */
void (*close) (void *);
/* find in dictionary */
char *(*lemmatize) (void *, char *, int *);
int (*is_stoplemm) (void *, char *, int);
int (*is_stemstoplemm) (void *, char *, int);
} DICT;
/* insert all dictionaries */
#define DICT_BODY
#include "dict.h"
#undef DICT_BODY
/* fill dictionary's structure */
#define DICT_TABLE
DICT dicts[] = {
{
"C", NULL, NULL, NULL, NULL, NULL /* fake dictionary */
}
#include "dict.h"
};
#undef DICT_TABLE
/* array for storing dictionary's objects (if needed) */
void *dictobjs[
lengthof(dicts)];
#define STOPLEXEM -2
#define BYLOCALE -1
#define NODICT 0
#define DEFAULTDICT 1
#define MAXNDICT 2
typedef int2 MAPDICT[MAXNDICT];
#define GETDICT(x,i) *( ((int2*)(x)) + (i) )
/* map dictionaries for lexem type */
static MAPDICT mapdict[] = {
{NODICT, NODICT}, /* not used */
{DEFAULTDICT, NODICT}, /* LATWORD */
{BYLOCALE, NODICT}, /* NONLATINWORD */
{BYLOCALE, DEFAULTDICT}, /* UWORD */
{NODICT, NODICT}, /* EMAIL */
{NODICT, NODICT}, /* FURL */
{NODICT, NODICT}, /* HOST */
{NODICT, NODICT}, /* SCIENTIFIC */
{NODICT, NODICT}, /* VERSIONNUMBER */
{BYLOCALE, DEFAULTDICT}, /* PARTHYPHENWORD */
{BYLOCALE, NODICT}, /* CYRPARTHYPHENWORD */
{DEFAULTDICT, NODICT}, /* LATPARTHYPHENWORD */
{STOPLEXEM, NODICT}, /* SPACE */
{STOPLEXEM, NODICT}, /* TAG */
{STOPLEXEM, NODICT}, /* HTTP */
{BYLOCALE, DEFAULTDICT}, /* HYPHENWORD */
{DEFAULTDICT, NODICT}, /* LATHYPHENWORD */
{BYLOCALE, NODICT}, /* CYRHYPHENWORD */
{NODICT, NODICT}, /* URI */
{NODICT, NODICT}, /* FILEPATH */
{NODICT, NODICT}, /* DECIMAL */
{NODICT, NODICT}, /* SIGNEDINT */
{NODICT, NODICT}, /* UNSIGNEDINT */
{STOPLEXEM, NODICT} /* HTMLENTITY */
};
static bool inited = false;
void
initmorph(void)
{
int i,
j,
k;
MAPDICT *md;
bool needinit[lengthof(dicts)];
const char *curlocale;
int bylocaledict = NODICT;
if (inited)
return;
for (i = 1; i < lengthof(dicts); i++)
needinit[i] = false;
curlocale = setlocale(LC_CTYPE, NULL);
if (curlocale)
{
for (i = 1; i < lengthof(dicts); i++)
if (strcmp(dicts[i].localename, curlocale) == 0)
{
bylocaledict = i;
break;
}
}
for (i = 1; i < lengthof(mapdict); i++)
{
k = 0;
md = &mapdict[i];
for (j = 0; j < MAXNDICT; j++)
{
GETDICT(md, k) = GETDICT(md, j);
if (GETDICT(md, k) == NODICT)
break;
else if (GETDICT(md, k) == BYLOCALE)
{
if (bylocaledict == NODICT)
continue;
GETDICT(md, k) = bylocaledict;
}
if (GETDICT(md, k) >= (int2) lengthof(dicts))
continue;
needinit[GETDICT(md, k)] = true;
k++;
}
for (; k < MAXNDICT; k++)
if (GETDICT(md, k) != STOPLEXEM)
GETDICT(md, k) = NODICT;
}
for (i = 1; i < lengthof(dicts); i++)
if (needinit[i] && dicts[i].init)
dictobjs[i] = (*(dicts[i].init)) ();
inited = true;
return;
}
char *
lemmatize(char *word, int *len, int type)
{
int2 nd;
int i;
DICT *dict;
for (i = 0; i < MAXNDICT; i++)
{
nd = GETDICT(&mapdict[type], i);
if (nd == NODICT)
{
/* there is no dictionary */
return word;
}
else if (nd == STOPLEXEM)
{
/* word is stopword */
return NULL;
}
else if (nd == BYLOCALE)
{
continue; /* no dict for current locale */
}
else
{
dict = &dicts[nd];
if (dict->is_stoplemm && (*(dict->is_stoplemm)) (dictobjs[nd], word, *len))
return NULL;
if (dict->lemmatize)
{
int oldlen = *len;
char *newword = (*(dict->lemmatize)) (dictobjs[nd], word, len);
/* word is recognized by dictionary */
if (newword != word || *len != oldlen)
{
if (dict->is_stemstoplemm &&
(*(dict->is_stemstoplemm)) (dictobjs[nd], word, *len))
{
if (newword != word && newword)
pfree(newword);
return NULL;
}
return newword;
}
}
}
}
return word;
}
bool
is_stoptype(int type)
{
return (GETDICT(&mapdict[type], 0) == STOPLEXEM) ? true : false;
}

View File

@ -1,10 +0,0 @@
#ifndef __MORPH_H__
#define __MORPH_H__
void initmorph(void);
char *lemmatize(char *word, int *len, int type);
bool is_stoptype(int type);
#endif

View File

@ -1,10 +0,0 @@
#ifndef __PARSER_H__
#define __PARSER_H__
char *token;
int tokenlen;
int tsearch_yylex(void);
void start_parse_str(char *, int);
void end_parse(void);
#endif

View File

@ -1,298 +0,0 @@
%{
#include "postgres.h"
#include "deflex.h"
#include "parser.h"
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))
char *token = NULL; /* pointer to token */
char *s = NULL; /* to return WHOLE hyphenated-word */
YY_BUFFER_STATE buf = NULL; /* buffer to parse; it need for parse from string */
%}
%option 8bit
%option never-interactive
%option nodefault
%option nounput
%option noyywrap
/* parser's state for parsing hyphenated-word */
%x DELIM
/* parser's state for parsing URL*/
%x URL
%x SERVER
/* parser's state for parsing TAGS */
%x INTAG
%x QINTAG
%x INCOMMENT
%x INSCRIPT
/* cyrillic koi8 char */
CYRALNUM [0-9\200-\377]
CYRALPHA [\200-\377]
ALPHA [a-zA-Z\200-\377]
ALNUM [0-9a-zA-Z\200-\377]
HOSTNAME ([-_[:alnum:]]+\.)+[[:alpha:]]+
URI [-_[:alnum:]/%,\.;=&?#]+
%%
"<"[Ss][Cc][Rr][Ii][Pp][Tt] { BEGIN INSCRIPT; }
<INSCRIPT>"</"[Ss][Cc][Rr][Ii][Pp][Tt]">" {
BEGIN INITIAL;
*tsearch_yytext=' '; *(tsearch_yytext+1) = '\0';
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SPACE;
}
"<!--" { BEGIN INCOMMENT; }
<INCOMMENT>"-->" {
BEGIN INITIAL;
*tsearch_yytext=' '; *(tsearch_yytext+1) = '\0';
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SPACE;
}
"<"[\![:alpha:]] { BEGIN INTAG; }
"</"[[:alpha:]] { BEGIN INTAG; }
<INTAG>"\"" { BEGIN QINTAG; }
<QINTAG>"\\\"" ;
<QINTAG>"\"" { BEGIN INTAG; }
<INTAG>">" {
BEGIN INITIAL;
token = tsearch_yytext;
*tsearch_yytext=' ';
token = tsearch_yytext;
tokenlen = 1;
return TAG;
}
<QINTAG,INTAG,INCOMMENT,INSCRIPT>.|\n ;
\&(quot|amp|nbsp|lt|gt)\; {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return HTMLENTITY;
}
\&\#[0-9][0-9]?[0-9]?\; {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return HTMLENTITY;
}
[-_\.[:alnum:]]+@{HOSTNAME} /* Emails */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return EMAIL;
}
[+-]?[0-9]+(\.[0-9]+)?[eEdD][+-]?[0-9]+ /* float */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SCIENTIFIC;
}
[0-9]+\.[0-9]+\.[0-9\.]*[0-9] {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return VERSIONNUMBER;
}
[+-]?[0-9]+\.[0-9]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return DECIMAL;
}
[+-][0-9]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SIGNEDINT;
}
<DELIM,INITIAL>[0-9]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return UNSIGNEDINT;
}
http"://" {
BEGIN URL;
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return HTTP;
}
ftp"://" {
BEGIN URL;
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return HTTP;
}
<URL,INITIAL>{HOSTNAME}[/:]{URI} {
BEGIN SERVER;
if (s) { free(s); s=NULL; }
s = strdup( tsearch_yytext );
tokenlen = tsearch_yyleng;
yyless( 0 );
token = s;
return FURL;
}
<SERVER,URL,INITIAL>{HOSTNAME} {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return HOST;
}
<SERVER>[/:]{URI} {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return URI;
}
[[:alnum:]\./_-]+"/"[[:alnum:]\./_-]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return FILEPATH;
}
({CYRALPHA}+-)+{CYRALPHA}+ /* composite-word */ {
BEGIN DELIM;
if (s) { free(s); s=NULL; }
s = strdup( tsearch_yytext );
tokenlen = tsearch_yyleng;
yyless( 0 );
token = s;
return CYRHYPHENWORD;
}
([[:alpha:]]+-)+[[:alpha:]]+ /* composite-word */ {
BEGIN DELIM;
if (s) { free(s); s=NULL; }
s = strdup( tsearch_yytext );
tokenlen = tsearch_yyleng;
yyless( 0 );
token = s;
return LATHYPHENWORD;
}
({ALNUM}+-)+{ALNUM}+ /* composite-word */ {
BEGIN DELIM;
if (s) { free(s); s=NULL; }
s = strdup( tsearch_yytext );
tokenlen = tsearch_yyleng;
yyless( 0 );
token = s;
return HYPHENWORD;
}
<DELIM>\+?[0-9]+\.[0-9]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return DECIMAL;
}
<DELIM>{CYRALPHA}+ /* one word in composite-word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return CYRPARTHYPHENWORD;
}
<DELIM>[[:alpha:]]+ /* one word in composite-word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return LATPARTHYPHENWORD;
}
<DELIM>{ALNUM}+ /* one word in composite-word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return PARTHYPHENWORD;
}
<DELIM>- {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SPACE;
}
<DELIM,SERVER,URL>.|\n /* return in basic state */ {
BEGIN INITIAL;
yyless( 0 );
}
{CYRALPHA}+ /* normal word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return CYRWORD;
}
[[:alpha:]]+ /* normal word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return LATWORD;
}
{ALNUM}+ /* normal word */ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return UWORD;
}
[ \r\n\t]+ {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SPACE;
}
. {
token = tsearch_yytext;
tokenlen = tsearch_yyleng;
return SPACE;
}
%%
/* clearing after parsing from string */
void
end_parse(void)
{
if (s)
{
free(s);
s = NULL;
}
tsearch_yy_delete_buffer( buf );
buf = NULL;
}
/* start parse from string */
void
start_parse_str(char* str, int limit)
{
if (buf)
end_parse();
buf = tsearch_yy_scan_bytes( str, limit );
tsearch_yy_switch_to_buffer( buf );
BEGIN INITIAL;
}

View File

@ -1,837 +0,0 @@
/*
* IO definitions for query_txt and mquery_txt. This type
* are identical, but for parsing mquery_txt used parser for text
* and also morphology is used.
* Internal structure:
* query tree, then string with original value.
* Query tree with plain view. It's means that in array of nodes
* right child is always next and left position = item+item->left
* Teodor Sigaev <teodor@stack.net>
*/
#include "postgres.h"
#include <ctype.h>
#include <float.h>
#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 "txtidx.h"
#include "crc32.h"
#include "query.h"
#include "morph.h"
#include "rewrite.h"
#include "deflex.h"
#include "parser.h"
PG_FUNCTION_INFO_V1(mqtxt_in);
Datum mqtxt_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(qtxt_in);
Datum qtxt_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(qtxt_out);
Datum qtxt_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(execqtxt);
Datum execqtxt(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(rexecqtxt);
Datum rexecqtxt(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(querytree);
Datum querytree(PG_FUNCTION_ARGS);
#define END 0
#define ERR 1
#define VAL 2
#define OPR 3
#define OPEN 4
#define CLOSE 5
#define VALTRUE 6 /* for stop words */
#define VALFALSE 7
/* parser's states */
#define WAITOPERAND 1
#define WAITOPERATOR 2
/*
* node of query tree, also used
* for storing polish notation in parser
*/
typedef struct NODE
{
int4 type;
int4 val;
int2 distance;
int2 length;
struct NODE *next;
} NODE;
typedef struct
{
char *buf;
int4 state;
int4 count;
/* reverse polish notation in list (for temporary usage) */
NODE *str;
/* number in str */
int4 num;
/* user-friendly operand */
int4 lenop;
int4 sumlen;
char *op;
char *curop;
/* state for value's parser */
TI_IN_STATE valstate;
} QPRS_STATE;
/*
* get token from query string
*/
static int4
gettoken_query(QPRS_STATE * state, int4 *val, int4 *lenval, char **strval)
{
while (1)
{
switch (state->state)
{
case WAITOPERAND:
if (*(state->buf) == '!')
{
(state->buf)++;
*val = (int4) '!';
return OPR;
}
else if (*(state->buf) == '(')
{
state->count++;
(state->buf)++;
return OPEN;
}
else if (*(state->buf) != ' ')
{
state->valstate.prsbuf = state->buf;
state->state = WAITOPERATOR;
if (gettoken_txtidx(&(state->valstate)))
{
*strval = state->valstate.word;
*lenval = state->valstate.curpos - state->valstate.word;
state->buf = state->valstate.prsbuf;
return VAL;
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("no operand")));
}
break;
case WAITOPERATOR:
if (*(state->buf) == '&' || *(state->buf) == '|')
{
state->state = WAITOPERAND;
*val = (int4) *(state->buf);
(state->buf)++;
return OPR;
}
else if (*(state->buf) == ')')
{
(state->buf)++;
state->count--;
return (state->count < 0) ? ERR : CLOSE;
}
else if (*(state->buf) == '\0')
return (state->count) ? ERR : END;
else if (*(state->buf) != ' ')
return ERR;
break;
default:
return ERR;
break;
}
(state->buf)++;
}
return END;
}
/*
* push new one in polish notation reverse view
*/
static void
pushquery(QPRS_STATE * state, int4 type, int4 val, int4 distance, int4 lenval)
{
NODE *tmp = (NODE *) palloc(sizeof(NODE));
tmp->type = type;
tmp->val = val;
if (distance > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("value is too big")));
if (lenval > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("operand is too long")));
tmp->distance = distance;
tmp->length = lenval;
tmp->next = state->str;
state->str = tmp;
state->num++;
}
/*
* This function is used for query_txt parsing
*/
static void
pushval_asis(QPRS_STATE * state, int type, char *strval, int lenval)
{
if (lenval > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("word is too long")));
pushquery(state, type, crc32_sz((uint8 *) strval, lenval),
state->curop - state->op, lenval);
while (state->curop - state->op + lenval + 1 >= state->lenop)
{
int4 tmp = state->curop - state->op;
state->lenop *= 2;
state->op = (char *) repalloc((void *) state->op, state->lenop);
state->curop = state->op + tmp;
}
memcpy((void *) state->curop, (void *) strval, lenval);
state->curop += lenval;
*(state->curop) = '\0';
state->curop++;
state->sumlen += lenval + 1;
return;
}
/*
* This function is used for mquery_txt parsing
*/
static void
pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval)
{
int4 type,
lenlemm;
int4 count = 0;
char *lemm;
start_parse_str(strval, lenval);
while ((type = tsearch_yylex()) != 0)
{
if (tokenlen > 0xffff)
{
end_parse();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("word is too long")));
}
lenlemm = tokenlen;
lemm = lemmatize(token, &lenlemm, type);
if (lemm)
{
if (lemm == token)
{
char *ptrs = token,
*ptrd;
ptrd = lemm = palloc(lenlemm + 1);
while (ptrs - token < lenlemm)
{
*ptrd = tolower((unsigned char) *ptrs);
ptrs++;
ptrd++;
}
*ptrd = '\0';
}
pushval_asis(state, VAL, lemm, lenlemm);
pfree(lemm);
}
else
pushval_asis(state, VALTRUE, NULL, 0);
if (count)
pushquery(state, OPR, (int4) '&', 0, 0);
count++;
}
end_parse();
}
#define STACKDEPTH 32
/*
* make polish notation of query
*/
static int4
makepol(QPRS_STATE * state, void (*pushval) (QPRS_STATE *, int, char *, int))
{
int4 val,
type;
int4 lenval;
char *strval;
int4 stack[STACKDEPTH];
int4 lenstack = 0;
while ((type = gettoken_query(state, &val, &lenval, &strval)) != END)
{
switch (type)
{
case VAL:
(*pushval) (state, VAL, strval, lenval);
while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
stack[lenstack - 1] == (int4) '!'))
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0);
}
break;
case OPR:
if (lenstack && val == (int4) '|')
pushquery(state, OPR, val, 0, 0);
else
{
if (lenstack == STACKDEPTH)
/* internal error */
elog(ERROR, "stack too short");
stack[lenstack] = val;
lenstack++;
}
break;
case OPEN:
if (makepol(state, pushval) == ERR)
return ERR;
if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
stack[lenstack - 1] == (int4) '!'))
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0);
}
break;
case CLOSE:
while (lenstack)
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0);
};
return END;
break;
case ERR:
default:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error")));
return ERR;
}
}
while (lenstack)
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0);
};
return END;
}
typedef struct
{
WordEntry *arrb;
WordEntry *arre;
char *values;
char *operand;
} CHKVAL;
/*
* compare 2 string values
*/
static int4
ValCompare(CHKVAL * chkval, WordEntry * ptr, ITEM * item)
{
if (ptr->len == item->length)
return strncmp(
&(chkval->values[ptr->pos]),
&(chkval->operand[item->distance]),
item->length);
return (ptr->len > item->length) ? 1 : -1;
}
/*
* is there value 'val' in array or not ?
*/
static bool
checkcondition_str(void *checkval, ITEM * val)
{
WordEntry *StopLow = ((CHKVAL *) checkval)->arrb;
WordEntry *StopHigh = ((CHKVAL *) checkval)->arre;
WordEntry *StopMiddle;
int difference;
/* Loop invariant: StopLow <= val < StopHigh */
while (StopLow < StopHigh)
{
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
difference = ValCompare((CHKVAL *) checkval, StopMiddle, val);
if (difference == 0)
return (true);
else if (difference < 0)
StopLow = StopMiddle + 1;
else
StopHigh = StopMiddle;
}
return (false);
}
/*
* check for boolean condition
*/
bool
execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM * val))
{
if (curitem->type == VAL)
return (*chkcond) (checkval, curitem);
else if (curitem->val == (int4) '!')
{
return (calcnot) ?
((execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
: true;
}
else if (curitem->val == (int4) '&')
{
if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
return execute(curitem + 1, checkval, calcnot, chkcond);
else
return false;
}
else
{ /* |-operator */
if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
return true;
else
return execute(curitem + 1, checkval, calcnot, chkcond);
}
return false;
}
/*
* boolean operations
*/
Datum
rexecqtxt(PG_FUNCTION_ARGS)
{
return DirectFunctionCall2(
execqtxt,
PG_GETARG_DATUM(1),
PG_GETARG_DATUM(0)
);
}
Datum
execqtxt(PG_FUNCTION_ARGS)
{
txtidx *val = (txtidx *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
CHKVAL chkval;
bool result;
if (!val->size || !query->size)
{
PG_FREE_IF_COPY(val, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(false);
}
chkval.arrb = ARRPTR(val);
chkval.arre = chkval.arrb + val->size;
chkval.values = STRPTR(val);
chkval.operand = GETOPERAND(query);
result = execute(
GETQUERY(query),
&chkval,
true,
checkcondition_str
);
PG_FREE_IF_COPY(val, 0);
PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(result);
}
/*
* find left operand in polish notation view
*/
static void
findoprnd(ITEM * ptr, int4 *pos)
{
#ifdef BS_DEBUG
elog(DEBUG4, (ptr[*pos].type == OPR) ?
"%d %c" : "%d %d", *pos, ptr[*pos].val);
#endif
if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE)
{
ptr[*pos].left = 0;
(*pos)++;
}
else if (ptr[*pos].val == (int4) '!')
{
ptr[*pos].left = 1;
(*pos)++;
findoprnd(ptr, pos);
}
else
{
ITEM *curitem = &ptr[*pos];
int4 tmp = *pos;
(*pos)++;
findoprnd(ptr, pos);
curitem->left = *pos - tmp;
findoprnd(ptr, pos);
}
}
/*
* input
*/
static QUERYTYPE *
queryin(char *buf, void (*pushval) (QPRS_STATE *, int, char *, int))
{
QPRS_STATE state;
int4 i;
QUERYTYPE *query;
int4 commonlen;
ITEM *ptr;
NODE *tmp;
int4 pos = 0;
#ifdef BS_DEBUG
char pbuf[16384],
*cur;
#endif
/* init state */
state.buf = buf;
state.state = WAITOPERAND;
state.count = 0;
state.num = 0;
state.str = NULL;
/* init value parser's state */
state.valstate.oprisdelim = true;
state.valstate.len = 32;
state.valstate.word = (char *) palloc(state.valstate.len);
/* init list of operand */
state.sumlen = 0;
state.lenop = 64;
state.curop = state.op = (char *) palloc(state.lenop);
*(state.curop) = '\0';
/* parse query & make polish notation (postfix, but in reverse order) */
makepol(&state, pushval);
pfree(state.valstate.word);
if (!state.num)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("empty query")));
/* make finish struct */
commonlen = COMPUTESIZE(state.num, state.sumlen);
query = (QUERYTYPE *) palloc(commonlen);
query->len = commonlen;
query->size = state.num;
ptr = GETQUERY(query);
/* set item in polish notation */
for (i = 0; i < state.num; i++)
{
ptr[i].type = state.str->type;
ptr[i].val = state.str->val;
ptr[i].distance = state.str->distance;
ptr[i].length = state.str->length;
tmp = state.str->next;
pfree(state.str);
state.str = tmp;
}
/* set user friendly-operand view */
memcpy((void *) GETOPERAND(query), (void *) state.op, state.sumlen);
pfree(state.op);
/* set left operand's position for every operator */
pos = 0;
findoprnd(ptr, &pos);
#ifdef BS_DEBUG
cur = pbuf;
*cur = '\0';
for (i = 0; i < query->size; i++)
{
if (ptr[i].type == OPR)
sprintf(cur, "%c(%d) ", ptr[i].val, ptr[i].left);
else
sprintf(cur, "%d(%s) ", ptr[i].val, GETOPERAND(query) + ptr[i].distance);
cur = strchr(cur, '\0');
}
elog(DEBUG4, "POR: %s", pbuf);
#endif
return query;
}
/*
* in without morphology
*/
Datum
qtxt_in(PG_FUNCTION_ARGS)
{
PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0), pushval_asis));
}
/*
* in with morphology
*/
Datum
mqtxt_in(PG_FUNCTION_ARGS)
{
QUERYTYPE *query;
ITEM *res;
int4 len;
#ifdef BS_DEBUG
ITEM *ptr;
int4 i;
char pbuf[16384],
*cur;
#endif
initmorph();
query = queryin((char *) PG_GETARG_POINTER(0), pushval_morph);
res = clean_fakeval(GETQUERY(query), &len);
if (!res)
{
query->len = HDRSIZEQT;
query->size = 0;
PG_RETURN_POINTER(query);
}
memcpy((void *) GETQUERY(query), (void *) res, len * sizeof(ITEM));
#ifdef BS_DEBUG
cur = pbuf;
*cur = '\0';
ptr = GETQUERY(query);
for (i = 0; i < len; i++)
{
if (ptr[i].type == OPR)
sprintf(cur, "%c(%d) ", ptr[i].val, ptr[i].left);
else
sprintf(cur, "%d(%s) ", ptr[i].val, GETOPERAND(query) + ptr[i].distance);
cur = strchr(cur, '\0');
}
elog(DEBUG4, "POR: %s", pbuf);
#endif
pfree(res);
PG_RETURN_POINTER(query);
}
/*
* out function
*/
typedef struct
{
ITEM *curpol;
char *buf;
char *cur;
char *op;
int4 buflen;
} INFIX;
#define RESIZEBUF(inf,addsize) \
while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \
{ \
int4 len = (inf)->cur - (inf)->buf; \
(inf)->buflen *= 2; \
(inf)->buf = (char*) repalloc( (void*)(inf)->buf, (inf)->buflen ); \
(inf)->cur = (inf)->buf + len; \
}
/*
* recursive walk on tree and print it in
* infix (human-readable) view
*/
static void
infix(INFIX * in, bool first)
{
if (in->curpol->type == VAL)
{
char *op = in->op + in->curpol->distance;
RESIZEBUF(in, in->curpol->length * 2 + 2);
*(in->cur) = '\'';
in->cur++;
while (*op)
{
if (*op == '\'')
{
*(in->cur) = '\\';
in->cur++;
}
*(in->cur) = *op;
op++;
in->cur++;
}
*(in->cur) = '\'';
in->cur++;
*(in->cur) = '\0';
in->curpol++;
}
else if (in->curpol->val == (int4) '!')
{
bool isopr = false;
RESIZEBUF(in, 1);
*(in->cur) = '!';
in->cur++;
*(in->cur) = '\0';
in->curpol++;
if (in->curpol->type == OPR)
{
isopr = true;
RESIZEBUF(in, 2);
sprintf(in->cur, "( ");
in->cur = strchr(in->cur, '\0');
}
infix(in, isopr);
if (isopr)
{
RESIZEBUF(in, 2);
sprintf(in->cur, " )");
in->cur = strchr(in->cur, '\0');
}
}
else
{
int4 op = in->curpol->val;
INFIX nrm;
in->curpol++;
if (op == (int4) '|' && !first)
{
RESIZEBUF(in, 2);
sprintf(in->cur, "( ");
in->cur = strchr(in->cur, '\0');
}
nrm.curpol = in->curpol;
nrm.op = in->op;
nrm.buflen = 16;
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
/* get right operand */
infix(&nrm, false);
/* get & print left operand */
in->curpol = nrm.curpol;
infix(in, false);
/* print operator & right operand */
RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
sprintf(in->cur, " %c %s", op, nrm.buf);
in->cur = strchr(in->cur, '\0');
pfree(nrm.buf);
if (op == (int4) '|' && !first)
{
RESIZEBUF(in, 2);
sprintf(in->cur, " )");
in->cur = strchr(in->cur, '\0');
}
}
}
Datum
qtxt_out(PG_FUNCTION_ARGS)
{
QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
INFIX nrm;
if (query->size == 0)
{
char *b = palloc(1);
*b = '\0';
PG_RETURN_POINTER(b);
}
nrm.curpol = GETQUERY(query);
nrm.buflen = 32;
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
*(nrm.cur) = '\0';
nrm.op = GETOPERAND(query);
infix(&nrm, true);
PG_FREE_IF_COPY(query, 0);
PG_RETURN_POINTER(nrm.buf);
}
/*
* debug function, used only for view query
* which will be executed in non-leaf pages in index
*/
Datum
querytree(PG_FUNCTION_ARGS)
{
QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
INFIX nrm;
text *res;
ITEM *q;
int4 len;
if (query->size == 0)
{
res = (text *) palloc(VARHDRSZ);
VARATT_SIZEP(res) = VARHDRSZ;
PG_RETURN_POINTER(res);
}
q = clean_NOT(GETQUERY(query), &len);
if (!q)
{
res = (text *) palloc(1 + VARHDRSZ);
VARATT_SIZEP(res) = 1 + VARHDRSZ;
*((char *) VARDATA(res)) = 'T';
}
else
{
nrm.curpol = q;
nrm.buflen = 32;
nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
*(nrm.cur) = '\0';
nrm.op = GETOPERAND(query);
infix(&nrm, true);
res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ);
VARATT_SIZEP(res) = nrm.cur - nrm.buf + VARHDRSZ;
strncpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf);
pfree(q);
}
PG_FREE_IF_COPY(query, 0);
PG_RETURN_POINTER(res);
}
#include "parser.c"

View File

@ -1,52 +0,0 @@
#ifndef __QUERY_H__
#define __QUERY_H__
/*
#define BS_DEBUG
*/
/*
* item in polish notation with back link
* to left operand
*/
typedef struct ITEM
{
int2 type;
int2 left;
int4 val;
/* user-friendly value */
uint16 distance;
uint16 length;
} ITEM;
/*
*Storage:
* (len)(size)(array of ITEM)(array of operand in user-friendly form)
*/
typedef struct
{
int4 len;
int4 size;
char data[1];
} QUERYTYPE;
#define HDRSIZEQT ( 2*sizeof(int4) )
#define COMPUTESIZE(size, lenofoperand) ( HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand) )
#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
#define GETOPERAND(x) ( (char*)GETQUERY(x) + ((QUERYTYPE*)(x))->size * sizeof(ITEM) )
#define ISOPERATOR(x) ( (x)=='!' || (x)=='&' || (x)=='|' || (x)=='(' || (x)==')' )
#define END 0
#define ERR 1
#define VAL 2
#define OPR 3
#define OPEN 4
#define CLOSE 5
#define VALTRUE 6 /* for stop words */
#define VALFALSE 7
bool execute(ITEM * curitem, void *checkval,
bool calcnot, bool (*chkcond) (void *checkval, ITEM * val));
#endif

View File

@ -1,293 +0,0 @@
/*
* Rewrite routines of query tree
* Teodor Sigaev <teodor@stack.net>
*/
#include "postgres.h"
#include <float.h>
#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 "query.h"
#include "rewrite.h"
typedef struct NODE
{
struct NODE *left;
struct NODE *right;
ITEM *valnode;
} NODE;
/*
* make query tree from plain view of query
*/
static NODE *
maketree(ITEM * in)
{
NODE *node = (NODE *) palloc(sizeof(NODE));
node->valnode = in;
node->right = node->left = NULL;
if (in->type == OPR)
{
node->right = maketree(in + 1);
if (in->val != (int4) '!')
node->left = maketree(in + in->left);
}
return node;
}
typedef struct
{
ITEM *ptr;
int4 len;
int4 cur;
} PLAINTREE;
static void
plainnode(PLAINTREE * state, NODE * node)
{
if (state->cur == state->len)
{
state->len *= 2;
state->ptr = (ITEM *) repalloc((void *) state->ptr, state->len * sizeof(ITEM));
}
memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(ITEM));
if (node->valnode->type == VAL)
state->cur++;
else if (node->valnode->val == (int4) '!')
{
state->ptr[state->cur].left = 1;
state->cur++;
plainnode(state, node->right);
}
else
{
int4 cur = state->cur;
state->cur++;
plainnode(state, node->right);
state->ptr[cur].left = state->cur - cur;
plainnode(state, node->left);
}
pfree(node);
}
/*
* make plain view of tree from 'normal' view of tree
*/
static ITEM *
plaintree(NODE * root, int4 *len)
{
PLAINTREE pl;
pl.cur = 0;
pl.len = 16;
if (root && (root->valnode->type == VAL || root->valnode->type == OPR))
{
pl.ptr = (ITEM *) palloc(pl.len * sizeof(ITEM));
plainnode(&pl, root);
}
else
pl.ptr = NULL;
*len = pl.cur;
return pl.ptr;
}
static void
freetree(NODE * node)
{
if (!node)
return;
if (node->left)
freetree(node->left);
if (node->right)
freetree(node->right);
pfree(node);
}
/*
* clean tree for ! operator.
* It's useful for debug, but in
* other case, such view is used with search in index.
* Operator ! always return TRUE
*/
static NODE *
clean_NOT_intree(NODE * node)
{
if (node->valnode->type == VAL)
return node;
if (node->valnode->val == (int4) '!')
{
freetree(node);
return NULL;
}
/* operator & or | */
if (node->valnode->val == (int4) '|')
{
if ((node->left = clean_NOT_intree(node->left)) == NULL ||
(node->right = clean_NOT_intree(node->right)) == NULL)
{
freetree(node);
return NULL;
}
}
else
{
NODE *res = node;
node->left = clean_NOT_intree(node->left);
node->right = clean_NOT_intree(node->right);
if (node->left == NULL && node->right == NULL)
{
pfree(node);
res = NULL;
}
else if (node->left == NULL)
{
res = node->right;
pfree(node);
}
else if (node->right == NULL)
{
res = node->left;
pfree(node);
}
return res;
}
return node;
}
ITEM *
clean_NOT(ITEM * ptr, int4 *len)
{
NODE *root = maketree(ptr);
return plaintree(clean_NOT_intree(root), len);
}
#ifdef V_UNKNOWN /* apparently Windows defines this :-( */
#undef V_UNKNOWN
#endif
#define V_UNKNOWN 0
#define V_TRUE 1
#define V_FALSE 2
/*
* Clean query tree from values which is always in
* text (stopword)
*/
static NODE *
clean_fakeval_intree(NODE * node, char *result)
{
char lresult = V_UNKNOWN,
rresult = V_UNKNOWN;
if (node->valnode->type == VAL)
return node;
else if (node->valnode->type == VALTRUE)
{
pfree(node);
*result = V_TRUE;
return NULL;
}
if (node->valnode->val == (int4) '!')
{
node->right = clean_fakeval_intree(node->right, &rresult);
if (!node->right)
{
*result = (rresult == V_TRUE) ? V_FALSE : V_TRUE;
freetree(node);
return NULL;
}
}
else if (node->valnode->val == (int4) '|')
{
NODE *res = node;
node->left = clean_fakeval_intree(node->left, &lresult);
node->right = clean_fakeval_intree(node->right, &rresult);
if (lresult == V_TRUE || rresult == V_TRUE)
{
freetree(node);
*result = V_TRUE;
return NULL;
}
else if (lresult == V_FALSE && rresult == V_FALSE)
{
freetree(node);
*result = V_FALSE;
return NULL;
}
else if (lresult == V_FALSE)
{
res = node->right;
pfree(node);
}
else if (rresult == V_FALSE)
{
res = node->left;
pfree(node);
}
return res;
}
else
{
NODE *res = node;
node->left = clean_fakeval_intree(node->left, &lresult);
node->right = clean_fakeval_intree(node->right, &rresult);
if (lresult == V_FALSE || rresult == V_FALSE)
{
freetree(node);
*result = V_FALSE;
return NULL;
}
else if (lresult == V_TRUE && rresult == V_TRUE)
{
freetree(node);
*result = V_TRUE;
return NULL;
}
else if (lresult == V_TRUE)
{
res = node->right;
pfree(node);
}
else if (rresult == V_TRUE)
{
res = node->left;
pfree(node);
}
return res;
}
return node;
}
ITEM *
clean_fakeval(ITEM * ptr, int4 *len)
{
NODE *root = maketree(ptr);
char result = V_UNKNOWN;
NODE *resroot;
resroot = clean_fakeval_intree(root, &result);
if (result != V_UNKNOWN)
{
elog(NOTICE, "query contains only stopword(s) or doesn't contain lexeme(s), ignored");
*len = 0;
return NULL;
}
return plaintree(resroot, len);
}

View File

@ -1,7 +0,0 @@
#ifndef __REWRITE_H__
#define __REWRITE_H__
ITEM *clean_NOT(ITEM * ptr, int4 *len);
ITEM *clean_fakeval(ITEM * ptr, int4 *len);
#endif

View File

@ -1,163 +0,0 @@
--
-- first, define the datatype. Turn off echoing so that expected file
-- does not depend on contents of seg.sql.
--
\set ECHO none
\i tsearch.sql
\set ECHO all
--txtidx
SELECT '1'::txtidx;
SELECT '1 '::txtidx;
SELECT ' 1'::txtidx;
SELECT ' 1 '::txtidx;
SELECT '1 2'::txtidx;
SELECT '\'1 2\''::txtidx;
SELECT '\'1 \\\'2\''::txtidx;
SELECT '\'1 \\\'2\'3'::txtidx;
SELECT '\'1 \\\'2\' 3'::txtidx;
SELECT '\'1 \\\'2\' \' 3\' 4 '::txtidx;
--query_txt
SELECT '1'::query_txt;
SELECT '1 '::query_txt;
SELECT ' 1'::query_txt;
SELECT ' 1 '::query_txt;
SELECT '\'1 2\''::query_txt;
SELECT '\'1 \\\'2\''::query_txt;
SELECT '!1'::query_txt;
SELECT '1|2'::query_txt;
SELECT '1|!2'::query_txt;
SELECT '!1|2'::query_txt;
SELECT '!1|!2'::query_txt;
SELECT '!(!1|!2)'::query_txt;
SELECT '!(!1|2)'::query_txt;
SELECT '!(1|!2)'::query_txt;
SELECT '!(1|2)'::query_txt;
SELECT '1&2'::query_txt;
SELECT '!1&2'::query_txt;
SELECT '1&!2'::query_txt;
SELECT '!1&!2'::query_txt;
SELECT '(1&2)'::query_txt;
SELECT '1&(2)'::query_txt;
SELECT '!(1)&2'::query_txt;
SELECT '!(1&2)'::query_txt;
SELECT '1|2&3'::query_txt;
SELECT '1|(2&3)'::query_txt;
SELECT '(1|2)&3'::query_txt;
SELECT '1|2&!3'::query_txt;
SELECT '1|!2&3'::query_txt;
SELECT '!1|2&3'::query_txt;
SELECT '!1|(2&3)'::query_txt;
SELECT '!(1|2)&3'::query_txt;
SELECT '(!1|2)&3'::query_txt;
SELECT '1|(2|(4|(5|6)))'::query_txt;
SELECT '1|2|4|5|6'::query_txt;
SELECT '1&(2&(4&(5&6)))'::query_txt;
SELECT '1&2&4&5&6'::query_txt;
SELECT '1&(2&(4&(5|6)))'::query_txt;
SELECT '1&(2&(4&(5|!6)))'::query_txt;
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::query_txt;
SELECT '1'::mquery_txt;
SELECT '1 '::mquery_txt;
SELECT ' 1'::mquery_txt;
SELECT ' 1 '::mquery_txt;
SELECT '\'1 2\''::mquery_txt;
SELECT '\'1 \\\'2\''::mquery_txt;
SELECT '!1'::mquery_txt;
SELECT '1|2'::mquery_txt;
SELECT '1|!2'::mquery_txt;
SELECT '!1|2'::mquery_txt;
SELECT '!1|!2'::mquery_txt;
SELECT '!(!1|!2)'::mquery_txt;
SELECT '!(!1|2)'::mquery_txt;
SELECT '!(1|!2)'::mquery_txt;
SELECT '!(1|2)'::mquery_txt;
SELECT '1&2'::mquery_txt;
SELECT '!1&2'::mquery_txt;
SELECT '1&!2'::mquery_txt;
SELECT '!1&!2'::mquery_txt;
SELECT '(1&2)'::mquery_txt;
SELECT '1&(2)'::mquery_txt;
SELECT '!(1)&2'::mquery_txt;
SELECT '!(1&2)'::mquery_txt;
SELECT '1|2&3'::mquery_txt;
SELECT '1|(2&3)'::mquery_txt;
SELECT '(1|2)&3'::mquery_txt;
SELECT '1|2&!3'::mquery_txt;
SELECT '1|!2&3'::mquery_txt;
SELECT '!1|2&3'::mquery_txt;
SELECT '!1|(2&3)'::mquery_txt;
SELECT '!(1|2)&3'::mquery_txt;
SELECT '(!1|2)&3'::mquery_txt;
SELECT '1|(2|(4|(5|6)))'::mquery_txt;
SELECT '1|2|4|5|6'::mquery_txt;
SELECT '1&(2&(4&(5&6)))'::mquery_txt;
SELECT '1&2&4&5&6'::mquery_txt;
SELECT '1&(2&(4&(5|6)))'::mquery_txt;
SELECT '1&(2&(4&(5|!6)))'::mquery_txt;
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::mquery_txt;
SELECT 'querty-fgries | http://www.google.com/index.html | www.rambler.ru/index.shtml'::mquery_txt;
CREATE TABLE test_txtidx( t text, a txtidx );
\copy test_txtidx from 'data/test_tsearch.data'
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr|qh';
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr&qh';
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq&yt';
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq|yt';
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq&yt)|(wr&qh)';
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq|yt)&(wr|qh)';
SELECT count(*) FROM test_txtidx WHERE a ## 'wR|qh';
SELECT count(*) FROM test_txtidx WHERE a ## 'wR&qh';
SELECT count(*) FROM test_txtidx WHERE a ## 'eq&yt';
SELECT count(*) FROM test_txtidx WHERE a ## 'eq|yt';
SELECT count(*) FROM test_txtidx WHERE a ## '(eq&yt)|(wR&qh)';
SELECT count(*) FROM test_txtidx WHERE a ## '(eq|yt)&(wR|qh)';
create index wowidx on test_txtidx using gist (a);
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr|qh';
SELECT count(*) FROM test_txtidx WHERE a @@ 'wr&qh';
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq&yt';
SELECT count(*) FROM test_txtidx WHERE a @@ 'eq|yt';
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq&yt)|(wr&qh)';
SELECT count(*) FROM test_txtidx WHERE a @@ '(eq|yt)&(wr|qh)';
SELECT count(*) FROM test_txtidx WHERE a ## 'wR|qh';
SELECT count(*) FROM test_txtidx WHERE a ## 'wR&qh';
SELECT count(*) FROM test_txtidx WHERE a ## 'eq&yt';
SELECT count(*) FROM test_txtidx WHERE a ## 'eq|yt';
SELECT count(*) FROM test_txtidx WHERE a ## '(eq&yt)|(wR&qh)';
SELECT count(*) FROM test_txtidx WHERE a ## '(eq|yt)&(wR|qh)';
SELECT txt2txtidx('345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
SELECT txtidxsize(txt2txtidx('345 qw'));
SELECT txtidxsize(txt2txtidx('345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty'));
INSERT INTO test_txtidx (a) VALUES ('345 qwerty');
CREATE TRIGGER txtidxupdate
BEFORE UPDATE OR INSERT ON test_txtidx
FOR EACH ROW EXECUTE PROCEDURE tsearch(a, t);
INSERT INTO test_txtidx (t) VALUES ('345 qwerty');
SELECT count(*) FROM test_txtidx WHERE a @@ '345&qwerty';
SELECT count(*) FROM test_txtidx WHERE a ## '345&qwerty';
UPDATE test_txtidx SET t = null WHERE t = '345 qwerty';
SELECT count(*) FROM test_txtidx WHERE a ## '345&qwerty';
SELECT count(*) FROM test_txtidx WHERE a @@ '345&qwerty';

View File

@ -1,218 +0,0 @@
-- Adjust this setting to control where the objects get created.
SET search_path = public;
-- TXTIDX type
CREATE FUNCTION txtidx_in(cstring)
RETURNS txtidx
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION txtidx_out(txtidx)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE TYPE txtidx (
INTERNALLENGTH = -1,
INPUT = txtidx_in,
OUTPUT = txtidx_out,
STORAGE = extended
);
CREATE FUNCTION txt2txtidx(text)
RETURNS txtidx
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION txtidxsize(txtidx)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
--QUERYTYPES
--without morphology
CREATE FUNCTION qtxt_in(cstring)
RETURNS query_txt
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION qtxt_out(query_txt)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE TYPE query_txt (
INTERNALLENGTH = -1,
INPUT = qtxt_in,
OUTPUT = qtxt_out
);
--with morphology
CREATE FUNCTION mqtxt_in(cstring)
RETURNS mquery_txt
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
--same C output function as for query_txt
CREATE FUNCTION mqtxt_out(mquery_txt)
RETURNS cstring
AS 'MODULE_PATHNAME', 'qtxt_out'
LANGUAGE 'C' with (isstrict);
CREATE TYPE mquery_txt (
INTERNALLENGTH = -1,
INPUT = mqtxt_in,
OUTPUT = mqtxt_out
);
--only for debug
CREATE FUNCTION querytree(query_txt)
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION querytree(mquery_txt)
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
--operations
CREATE FUNCTION execqtxt(txtidx, query_txt)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
COMMENT ON FUNCTION execqtxt(txtidx, query_txt) IS 'boolean operation with text index';
CREATE FUNCTION execqtxt(txtidx, mquery_txt)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
COMMENT ON FUNCTION execqtxt(txtidx, mquery_txt) IS 'boolean operation with text index';
CREATE FUNCTION rexecqtxt(query_txt, txtidx)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
COMMENT ON FUNCTION rexecqtxt(query_txt, txtidx) IS 'boolean operation with text index';
CREATE FUNCTION rexecqtxt(mquery_txt, txtidx)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
COMMENT ON FUNCTION rexecqtxt(mquery_txt, txtidx) IS 'boolean operation with text index';
CREATE OPERATOR @@ (
LEFTARG = txtidx,
RIGHTARG = query_txt,
PROCEDURE = execqtxt,
COMMUTATOR = '~@',
RESTRICT = contsel,
JOIN = contjoinsel
);
CREATE OPERATOR ~@ (
LEFTARG = query_txt,
RIGHTARG = txtidx,
PROCEDURE = rexecqtxt,
COMMUTATOR = '@@',
RESTRICT = contsel,
JOIN = contjoinsel
);
CREATE OPERATOR ## (
LEFTARG = txtidx,
RIGHTARG = mquery_txt,
PROCEDURE = execqtxt,
COMMUTATOR = '~#',
RESTRICT = contsel,
JOIN = contjoinsel
);
CREATE OPERATOR ~# (
LEFTARG = mquery_txt,
RIGHTARG = txtidx,
PROCEDURE = rexecqtxt,
COMMUTATOR = '##',
RESTRICT = contsel,
JOIN = contjoinsel
);
--Trigger
CREATE FUNCTION tsearch()
RETURNS trigger
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
--GiST
--GiST key type
CREATE FUNCTION gtxtidx_in(cstring)
RETURNS gtxtidx
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION gtxtidx_out(gtxtidx)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE TYPE gtxtidx (
INTERNALLENGTH = -1,
INPUT = gtxtidx_in,
OUTPUT = gtxtidx_out
);
-- support functions
CREATE FUNCTION gtxtidx_consistent(gtxtidx,internal,int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION gtxtidx_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION gtxtidx_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION gtxtidx_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict);
CREATE FUNCTION gtxtidx_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION gtxtidx_union(internal, internal)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
CREATE FUNCTION gtxtidx_same(gtxtidx, gtxtidx, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE 'C';
-- create the operator class
CREATE OPERATOR CLASS gist_txtidx_ops
DEFAULT FOR TYPE txtidx USING gist
AS
OPERATOR 1 @@ (txtidx, query_txt) RECHECK ,
OPERATOR 2 ## (txtidx, mquery_txt) RECHECK ,
FUNCTION 1 gtxtidx_consistent (gtxtidx, internal, int4),
FUNCTION 2 gtxtidx_union (internal, internal),
FUNCTION 3 gtxtidx_compress (internal),
FUNCTION 4 gtxtidx_decompress (internal),
FUNCTION 5 gtxtidx_penalty (internal, internal, internal),
FUNCTION 6 gtxtidx_picksplit (internal, internal),
FUNCTION 7 gtxtidx_same (gtxtidx, gtxtidx, internal),
STORAGE gtxtidx;

View File

@ -1,626 +0,0 @@
/*
* In/Out definitions for txtidx type
* Internal structure:
* string of values, array of position lexem in string and it's length
* Teodor Sigaev <teodor@stack.net>
*/
#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 "utils/pg_locale.h"
#include <ctype.h> /* tolower */
#include "txtidx.h"
#include "query.h"
#include "deflex.h"
#include "parser.h"
#include "morph.h"
PG_FUNCTION_INFO_V1(txtidx_in);
Datum txtidx_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txtidx_out);
Datum txtidx_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txt2txtidx);
Datum txt2txtidx(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(tsearch);
Datum tsearch(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txtidxsize);
Datum txtidxsize(PG_FUNCTION_ARGS);
/*
* in/out text index type
*/
static char *BufferStr;
static int
compareentry(const void *a, const void *b)
{
if (((WordEntry *) a)->len == ((WordEntry *) b)->len)
{
return strncmp(
&BufferStr[((WordEntry *) a)->pos],
&BufferStr[((WordEntry *) b)->pos],
((WordEntry *) b)->len);
}
return (((WordEntry *) a)->len > ((WordEntry *) b)->len) ? 1 : -1;
}
static int
uniqueentry(WordEntry * a, int4 l, char *buf, int4 *outbuflen)
{
WordEntry *ptr,
*res;
res = a;
*outbuflen = res->len;
if (l == 1)
return l;
ptr = a + 1;
BufferStr = buf;
qsort((void *) a, l, sizeof(int4), compareentry);
*outbuflen = res->len;
while (ptr - a < l)
{
if (!(ptr->len == res->len &&
strncmp(&buf[ptr->pos], &buf[res->pos], res->len) == 0))
{
res++;
res->len = ptr->len;
res->pos = ptr->pos;
*outbuflen += res->len;
}
ptr++;
}
return res + 1 - a;
}
#define WAITWORD 1
#define WAITENDWORD 2
#define WAITNEXTCHAR 3
#define WAITENDCMPLX 4
#define RESIZEPRSBUF \
do { \
if ( state->curpos - state->word == 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_txtidx(TI_IN_STATE * state)
{
int4 oldstate = 0;
state->curpos = state->word;
state->state = WAITWORD;
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
{
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")));
state->prsbuf++;
return 1;
}
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
/* internal error */
elog(ERROR, "internal error");
state->prsbuf++;
}
return 0;
}
Datum
txtidx_in(PG_FUNCTION_ARGS)
{
char *buf = PG_GETARG_CSTRING(0);
TI_IN_STATE state;
WordEntry *arr;
int4 len = 0,
totallen = 64;
txtidx *in;
char *tmpbuf,
*cur;
int4 i,
buflen = 256;
state.prsbuf = buf;
state.len = 32;
state.word = (char *) palloc(state.len);
state.oprisdelim = false;
arr = (WordEntry *) palloc(sizeof(WordEntry) * totallen);
cur = tmpbuf = (char *) palloc(buflen);
while (gettoken_txtidx(&state))
{
if (len == totallen)
{
totallen *= 2;
arr = (WordEntry *) repalloc((void *) arr, sizeof(int4) * 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 > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("word is too long")));
arr[len].len = state.curpos - state.word;
if (cur - tmpbuf > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("too long value")));
arr[len].pos = cur - tmpbuf;
memcpy((void *) cur, (void *) state.word, arr[len].len);
cur += arr[len].len;
len++;
}
pfree(state.word);
if (!len)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("void value")));
len = uniqueentry(arr, len, tmpbuf, &buflen);
totallen = CALCDATASIZE(len, buflen);
in = (txtidx *) palloc(totallen);
in->len = totallen;
in->size = len;
cur = STRPTR(in);
for (i = 0; i < len; i++)
{
memcpy((void *) cur, (void *) &tmpbuf[arr[i].pos], arr[i].len);
arr[i].pos = cur - STRPTR(in);
cur += arr[i].len;
}
pfree(tmpbuf);
memcpy((void *) ARRPTR(in), (void *) arr, sizeof(int4) * len);
pfree(arr);
PG_RETURN_POINTER(in);
}
Datum
txtidxsize(PG_FUNCTION_ARGS)
{
txtidx *in = (txtidx *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
int4 ret = in->size;
PG_FREE_IF_COPY(in, 0);
PG_RETURN_INT32(ret);
}
Datum
txtidx_out(PG_FUNCTION_ARGS)
{
txtidx *out = (txtidx *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
char *outbuf;
int4 i,
j,
lenbuf = STRSIZE(out) + 1 /* \0 */ + out->size * 2 /* '' */ + out->size - 1 /* space */ ;
WordEntry *ptr = ARRPTR(out);
char *curin,
*curout;
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++ = '\'';
ptr++;
}
outbuf[lenbuf - 1] = '\0';
PG_FREE_IF_COPY(out, 0);
PG_RETURN_POINTER(outbuf);
}
typedef struct
{
uint16 len;
char *word;
} WORD_T; /* WORD type defined on win32; we'll use WORD_T */
typedef struct
{
WORD_T *words;
int4 lenwords;
int4 curwords;
} PRSTEXT;
/*
* Parse text to lexems
*/
static void
parsetext(PRSTEXT * prs, char *buf, int4 buflen)
{
int type,
lenlemm;
char *ptr,
*ptrw;
char *lemm;
start_parse_str(buf, buflen);
while ((type = tsearch_yylex()) != 0)
{
if (prs->curwords == prs->lenwords)
{
prs->lenwords *= 2;
prs->words = (WORD_T *) repalloc((void *) prs->words, prs->lenwords * sizeof(WORD_T));
}
if (tokenlen > 0xffff)
{
end_parse();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("word is too long")));
}
lenlemm = tokenlen;
lemm = lemmatize(token, &lenlemm, type);
if (!lemm)
continue;
if (lemm != token)
{
prs->words[prs->curwords].len = lenlemm;
prs->words[prs->curwords].word = lemm;
}
else
{
prs->words[prs->curwords].len = lenlemm;
ptrw = prs->words[prs->curwords].word = (char *) palloc(lenlemm);
ptr = token;
while (ptr - token < lenlemm)
{
*ptrw = tolower((unsigned char) *ptr);
ptr++;
ptrw++;
}
}
prs->curwords++;
}
end_parse();
}
static int
compareWORD(const void *a, const void *b)
{
if (((WORD_T *) a)->len == ((WORD_T *) b)->len)
return strncmp(
((WORD_T *) a)->word,
((WORD_T *) b)->word,
((WORD_T *) b)->len);
return (((WORD_T *) a)->len > ((WORD_T *) b)->len) ? 1 : -1;
}
static int
uniqueWORD(WORD_T * a, int4 l)
{
WORD_T *ptr,
*res;
if (l == 1)
return l;
res = a;
ptr = a + 1;
qsort((void *) a, l, sizeof(WORD_T), compareWORD);
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;
}
else
pfree(ptr->word);
ptr++;
}
return res + 1 - a;
}
/*
* make value of txtidx
*/
static txtidx *
makevalue(PRSTEXT * prs)
{
int4 i,
lenstr = 0,
totallen;
txtidx *in;
WordEntry *ptr;
char *str,
*cur;
prs->curwords = uniqueWORD(prs->words, prs->curwords);
for (i = 0; i < prs->curwords; i++)
lenstr += prs->words[i].len;
totallen = CALCDATASIZE(prs->curwords, lenstr);
in = (txtidx *) palloc(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 > 0xffff)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("value is too big")));
ptr->pos = cur - str;
ptr++;
memcpy((void *) cur, (void *) prs->words[i].word, prs->words[i].len);
pfree(prs->words[i].word);
cur += prs->words[i].len;
}
pfree(prs->words);
return in;
}
Datum
txt2txtidx(PG_FUNCTION_ARGS)
{
text *in = PG_GETARG_TEXT_P(0);
PRSTEXT prs;
txtidx *out = NULL;
prs.lenwords = 32;
prs.curwords = 0;
prs.words = (WORD_T *) palloc(sizeof(WORD_T) * prs.lenwords);
initmorph();
parsetext(&prs, VARDATA(in), VARSIZE(in) - VARHDRSZ);
PG_FREE_IF_COPY(in, 0);
if (prs.curwords)
{
out = makevalue(&prs);
PG_RETURN_POINTER(out);
}
pfree(prs.words);
PG_RETURN_NULL();
}
/*
* Trigger
*/
Datum
tsearch(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
Trigger *trigger;
Relation rel;
HeapTuple rettuple = NULL;
int numidxattr,
i;
PRSTEXT prs;
Datum datum = (Datum) 0;
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 tsearch(txtidx_field, text_field1,...)");
numidxattr = SPI_fnumber(rel->rd_att, trigger->tgargs[0]);
if (numidxattr == SPI_ERROR_NOATTRIBUTE)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("could not find txtidx_field")));
prs.lenwords = 32;
prs.curwords = 0;
prs.words = (WORD_T *) palloc(sizeof(WORD_T) * prs.lenwords);
initmorph();
/* find all words in indexable column */
for (i = 1; i < trigger->tgnargs; i++)
{
int numattr;
Oid oidtype;
Datum txt_datum;
bool isnull;
text *txt;
numattr = SPI_fnumber(rel->rd_att, trigger->tgargs[i]);
if (numattr == SPI_ERROR_NOATTRIBUTE)
{
elog(WARNING, "TSearch: can not find 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_datum = SPI_getbinval(rettuple, rel->rd_att, numattr, &isnull);
if (isnull)
continue;
txt = DatumGetTextP(txt_datum);
parsetext(&prs, VARDATA(txt), VARSIZE(txt) - VARHDRSZ);
}
/* make txtidx value */
if (prs.curwords)
{
datum = PointerGetDatum(makevalue(&prs));
rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr,
&datum, NULL);
pfree(DatumGetPointer(datum));
}
else
{
char nulls = 'n';
pfree(prs.words);
rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr,
&datum, &nulls);
}
if (rettuple == NULL)
/* internal error */
elog(ERROR, "TSearch: %d returned by SPI_modifytuple", SPI_result);
return PointerGetDatum(rettuple);
}

View File

@ -1,46 +0,0 @@
#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
{
uint16 len;
uint16 pos;
} WordEntry;
typedef struct
{
int4 len;
int4 size;
char data[1];
} txtidx;
#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) * ((txtidx*)x)->size ) )
#define STRSIZE(x) ( ((txtidx*)x)->len - DATAHDRSIZE - ( sizeof(WordEntry) * ((txtidx*)x)->size ) )
typedef struct
{
char *prsbuf;
char *word;
char *curpos;
int4 len;
int4 state;
bool oprisdelim;
} TI_IN_STATE;
int4 gettoken_txtidx(TI_IN_STATE * state);
#endif

View File

@ -1,19 +0,0 @@
# $PostgreSQL: pgsql/contrib/xml/Makefile,v 1.10 2004/11/04 06:09:23 neilc Exp $
MODULE_big = pgxml_dom
OBJS = pgxml_dom.o
SHLIB_LINK = -lxml2
DATA_built = pgxml_dom.sql
DOCS = README.xml
override CFLAGS += $(shell xml2-config --cflags)
ifdef USE_PGXS
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/xml
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@ -1,121 +0,0 @@
This version is obsoleted by /contrib/xml2.
This package contains some simple routines for manipulating XML
documents stored in PostgreSQL. This is a work-in-progress and
somewhat basic at the moment (see the file TODO for some outline of
what remains to be done). It has the same BSD licence as PostgreSQL.
At present, two modules (based on different XML handling libraries)
are provided.
Prerequisite:
pgxml.c:
expat parser 1.95.0 or newer (http://expat.sourceforge.net)
or
pgxml_dom.c:
libxml2 (http://xmlsoft.org)
The libxml2 version provides more complete XPath functionality, and
seems like a good way to go. I've left the old versions in there for
comparison.
Compiling and loading:
----------------------
The Makefile only builds the libxml2 version.
To compile, just type make.
Then you can use psql to load the two function definitions:
\i pgxml_dom.sql
Function documentation and usage:
---------------------------------
pgxml_parse(text) returns bool
parses the provided text and returns true or false if it is
well-formed or not. It returns NULL if the parser couldn't be
created for any reason.
pgxml_xpath (XQuery functions) - differs between the versions:
pgxml.c (expat version) has:
pgxml_xpath(text doc, text xpath, int n) returns text
parses doc and returns the cdata of the nth occurence of
the "simple path" entry.
However, the remainder of this document will cover the pgxml_dom.c version.
pgxml_xpath(text doc, text xpath, text toptag, text septag) returns text
evaluates xpath on doc, and returns the result wrapped in
<toptag>...</toptag> and each result node wrapped in
<septag></septag>. toptag and septag may be empty strings, in which
case the respective tag will be omitted.
Example:
Given a table docstore:
Attribute | Type | Modifier
-----------+---------+----------
docid | integer |
document | text |
containing documents such as (these are archaeological site
descriptions, in case anyone is wondering):
<?XML version="1.0"?>
<site provider="Foundations" sitecode="ak97" version="1">
<name>Church Farm, Ashton Keynes</name>
<invtype>watching brief</invtype>
<location scheme="osgb">SU04209424</location>
</site>
one can type:
select docid,
pgxml_xpath(document,'//site/name/text()','','') as sitename,
pgxml_xpath(document,'//site/location/text()','','') as location
from docstore;
and get as output:
docid | sitename | location
-------+--------------------------------------+------------
1 | Church Farm, Ashton Keynes | SU04209424
2 | Glebe Farm, Long Itchington | SP41506500
3 | The Bungalow, Thames Lane, Cricklade | SU10229362
(3 rows)
or, to illustrate the use of the extra tags:
select docid as id,
pgxml_xpath(document,'//find/type/text()','set','findtype')
from docstore;
id | pgxml_xpath
----+-------------------------------------------------------------------------
1 | <set></set>
2 | <set><findtype>Urn</findtype></set>
3 | <set><findtype>Pottery</findtype><findtype>Animal bone</findtype></set>
(3 rows)
Which produces a new, well-formed document. Note that document 1 had
no matching instances, so the set returned contains no
elements. document 2 has 1 matching element and document 3 has 2.
This is just scratching the surface because XPath allows all sorts of
operations.
Note: I've only implemented the return of nodeset and string values so
far. This covers (I think) many types of queries, however.
John Gray <jgray@azuli.co.uk> 16 August 2001

View File

@ -1,78 +0,0 @@
PGXML TODO List
===============
Some of these items still require much more thought! Since the first
release, the XPath support has improved (because I'm no longer using a
homemade algorithm!).
1. Performance considerations
At present each document is parsed to produce the DOM tree on every query.
Pros:
Easy
No persistent memory or storage allocation for parsed trees
(libxml docs suggest representation of a document might
be 4 times the size of the text)
Cons:
Slow/ CPU intensive to parse.
Makes it difficult for PLs to apply libxml manipulations to create
new documents or amend existing ones.
2. XQuery
I'm not sure if the addition of XQuery would be best as a function or
as a new front-end parser. This is one to think about, but with a
decent implementation of XPath, one of the prerequisites is covered.
3. DOM Interfaces
Expose more aspects of the DOM to user functions/ PLs. This would
allow a procedure in a PL to run some queries and then use exposed
interfaces to libxml to create an XML document out of the query
results. I accept the argument that this might be more properly
performed on the client side.
4. Returning sets of documents from XPath queries.
Although the current implementation allows you to amalgamate the
returned results into a single document, it's quite possible that
you'd like to use the returned set of nodes as a source for FROM.
Is there a good way to optimise/index the results of certain XPath
operations to make them faster?:
select docid, pgxml_xpath(document,'//site/location/text()','','') as location
where pgxml_xpath(document,'//site/name/text()','','') = 'Church Farm';
and with multiple element occurences in a document?
select d.docid, pgxml_xpath(d.document,'//site/location/text()','','')
from docstore d,
pgxml_xpaths('docstore','document','//feature/type/text()','docid') ft
where ft.key = d.docid and ft.value ='Limekiln';
pgxml_xpaths params are relname, attrname, xpath, returnkey. It would
return a set of two-element tuples (key,value) consisting of the value of
returnkey, and the cdata value of the xpath. The XML document would be
defined by relname and attrname.
The pgxml_xpaths function could be the basis of a functional index,
which could speed up the above query very substantially, working
through the normal query planner mechanism.
5. Return type support.
Better support for returning e.g. numeric or boolean values. I need to
get to grips with the returned data from libxml first.
John Gray <jgray@azuli.co.uk> 16 August 2001

View File

@ -1,352 +0,0 @@
/********************************************************
* Interface code to parse an XML document using expat
********************************************************/
#include "postgres.h"
#include "fmgr.h"
#include "expat.h"
#include "pgxml.h"
/* Memory management - we make expat use standard pg MM */
XML_Memory_Handling_Suite mhs;
/* passthrough functions (palloc is a macro) */
static void *
pgxml_palloc(size_t size)
{
return palloc(size);
}
static void *
pgxml_repalloc(void *ptr, size_t size)
{
return repalloc(ptr, size);
}
static void
pgxml_pfree(void *ptr)
{
return pfree(ptr);
}
static void
pgxml_mhs_init()
{
mhs.malloc_fcn = pgxml_palloc;
mhs.realloc_fcn = pgxml_repalloc;
mhs.free_fcn = pgxml_pfree;
}
static void
pgxml_handler_init()
{
/*
* This code should set up the relevant handlers from user-supplied
* settings. Quite how these settings are made is another matter :)
*/
}
/* Returns true if document is well-formed */
PG_FUNCTION_INFO_V1(pgxml_parse);
Datum
pgxml_parse(PG_FUNCTION_ARGS)
{
/* called as pgxml_parse(document) */
XML_Parser p;
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
int32 docsize = VARSIZE(t) - VARHDRSZ;
pgxml_mhs_init();
pgxml_handler_init();
p = XML_ParserCreate_MM(NULL, &mhs, NULL);
if (!p)
{
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
errmsg("could not create expat parser")));
PG_RETURN_NULL(); /* seems appropriate if we couldn't parse */
}
if (!XML_Parse(p, (char *) VARDATA(t), docsize, 1))
{
/*
* elog(WARNING, "Parse error at line %d:%s",
* XML_GetCurrentLineNumber(p),
* XML_ErrorString(XML_GetErrorCode(p)));
*/
XML_ParserFree(p);
PG_RETURN_BOOL(false);
}
XML_ParserFree(p);
PG_RETURN_BOOL(true);
}
/* XPath handling functions */
/* XPath support here is for a very skeletal kind of XPath!
It was easy to program though... */
/* This first is the core function that builds a result set. The
actual functions called by the user manipulate that result set
in various ways.
*/
static XPath_Results *
build_xpath_results(text *doc, text *pathstr)
{
XPath_Results *xpr;
char *res;
pgxml_udata *udata;
XML_Parser p;
int32 docsize;
xpr = (XPath_Results *) palloc((sizeof(XPath_Results)));
memset((void *) xpr, 0, sizeof(XPath_Results));
xpr->rescount = 0;
docsize = VARSIZE(doc) - VARHDRSZ;
/* res isn't going to be the real return type, it is just a buffer */
res = (char *) palloc(docsize);
memset((void *) res, 0, docsize);
xpr->resbuf = res;
udata = (pgxml_udata *) palloc((sizeof(pgxml_udata)));
memset((void *) udata, 0, sizeof(pgxml_udata));
udata->currentpath[0] = '\0';
udata->textgrab = 0;
udata->path = (char *) palloc(VARSIZE(pathstr));
memcpy(udata->path, VARDATA(pathstr), VARSIZE(pathstr) - VARHDRSZ);
udata->path[VARSIZE(pathstr) - VARHDRSZ] = '\0';
udata->resptr = res;
udata->reslen = 0;
udata->xpres = xpr;
/* Now fire up the parser */
pgxml_mhs_init();
p = XML_ParserCreate_MM(NULL, &mhs, NULL);
if (!p)
{
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
errmsg("could not create expat parser")));
pfree(xpr);
pfree(udata->path);
pfree(udata);
pfree(res);
return NULL;
}
XML_SetUserData(p, (void *) udata);
/* Set the handlers */
XML_SetElementHandler(p, pgxml_starthandler, pgxml_endhandler);
XML_SetCharacterDataHandler(p, pgxml_charhandler);
if (!XML_Parse(p, (char *) VARDATA(doc), docsize, 1))
{
/*
* elog(WARNING, "Parse error at line %d:%s",
* XML_GetCurrentLineNumber(p),
* XML_ErrorString(XML_GetErrorCode(p)));
*/
XML_ParserFree(p);
pfree(xpr);
pfree(udata->path);
pfree(udata);
return NULL;
}
pfree(udata->path);
pfree(udata);
XML_ParserFree(p);
return xpr;
}
PG_FUNCTION_INFO_V1(pgxml_xpath);
Datum
pgxml_xpath(PG_FUNCTION_ARGS)
{
/* called as pgxml_xpath(document,pathstr, index) for the moment */
XPath_Results *xpresults;
text *restext;
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
text *t2 = PG_GETARG_TEXT_P(1);
int32 ind = PG_GETARG_INT32(2) - 1;
xpresults = build_xpath_results(t, t2);
/*
* This needs to be changed depending on the mechanism for returning
* our set of results.
*/
if (xpresults == NULL) /* parse error (not WF or parser failure) */
PG_RETURN_NULL();
if (ind >= (xpresults->rescount))
PG_RETURN_NULL();
restext = (text *) palloc(xpresults->reslens[ind] + VARHDRSZ);
memcpy(VARDATA(restext), xpresults->results[ind], xpresults->reslens[ind]);
VARATT_SIZEP(restext) = xpresults->reslens[ind] + VARHDRSZ;
pfree(xpresults->resbuf);
pfree(xpresults);
PG_RETURN_TEXT_P(restext);
}
static void
pgxml_pathcompare(void *userData)
{
char *matchpos;
matchpos = strstr(UD->currentpath, UD->path);
if (matchpos == NULL)
{ /* Should we have more logic here ? */
if (UD->textgrab)
{
UD->textgrab = 0;
pgxml_finalisegrabbedtext(userData);
}
return;
}
/*
* OK, we have a match of some sort. Now we need to check that our
* match is anchored to the *end* of the string AND that it is
* immediately preceded by a '/'
*/
/*
* This test wouldn't work if strlen (UD->path) overran the length of
* the currentpath, but that's not possible because we got a match!
*/
if ((matchpos + strlen(UD->path))[0] == '\0')
{
if ((UD->path)[0] == '/')
{
if (matchpos == UD->currentpath)
UD->textgrab = 1;
}
else
{
if ((matchpos - 1)[0] == '/')
UD->textgrab = 1;
}
}
}
static void
pgxml_starthandler(void *userData, const XML_Char * name,
const XML_Char ** atts)
{
char sepstr[] = "/";
if ((strlen(name) + strlen(UD->currentpath)) > MAXPATHLENGTH - 2)
elog(WARNING, "path too long");
else
{
strncat(UD->currentpath, sepstr, 1);
strcat(UD->currentpath, name);
}
if (UD->textgrab)
{
/*
* Depending on user preference, should we "reconstitute" the
* element into the result text?
*/
}
else
pgxml_pathcompare(userData);
}
static void
pgxml_endhandler(void *userData, const XML_Char * name)
{
/*
* Start by removing the current element off the end of the
* currentpath
*/
char *sepptr;
sepptr = strrchr(UD->currentpath, '/');
if (sepptr == NULL)
{
/* internal error */
elog(ERROR, "did not find '/'");
sepptr = UD->currentpath;
}
if (strcmp(name, sepptr + 1) != 0)
{
elog(WARNING, "wanted [%s], got [%s]", sepptr, name);
/* unmatched entry, so do nothing */
}
else
{
sepptr[0] = '\0'; /* Chop that element off the end */
}
if (UD->textgrab)
pgxml_pathcompare(userData);
}
static void
pgxml_charhandler(void *userData, const XML_Char * s, int len)
{
if (UD->textgrab)
{
if (len > 0)
{
memcpy(UD->resptr, s, len);
UD->resptr += len;
UD->reslen += len;
}
}
}
/* Should I be using PG list types here? */
static void
pgxml_finalisegrabbedtext(void *userData)
{
/* In res/reslen, we have a single result. */
UD->xpres->results[UD->xpres->rescount] = UD->resptr - UD->reslen;
UD->xpres->reslens[UD->xpres->rescount] = UD->reslen;
UD->reslen = 0;
UD->xpres->rescount++;
/*
* This effectively concatenates all the results together but we do
* know where one ends and the next begins
*/
}

View File

@ -1,42 +0,0 @@
/* Header for pg xml parser interface */
static void *pgxml_palloc(size_t size);
static void *pgxml_repalloc(void *ptr, size_t size);
static void pgxml_pfree(void *ptr);
static void pgxml_mhs_init();
static void pgxml_handler_init();
Datum pgxml_parse(PG_FUNCTION_ARGS);
Datum pgxml_xpath(PG_FUNCTION_ARGS);
static void pgxml_starthandler(void *userData, const XML_Char * name,
const XML_Char ** atts);
static void pgxml_endhandler(void *userData, const XML_Char * name);
static void pgxml_charhandler(void *userData, const XML_Char * s, int len);
static void pgxml_pathcompare(void *userData);
static void pgxml_finalisegrabbedtext(void *userData);
#define MAXPATHLENGTH 512
#define MAXRESULTS 100
typedef struct
{
int rescount;
char *results[MAXRESULTS];
int32 reslens[MAXRESULTS];
char *resbuf; /* pointer to the result buffer for pfree */
} XPath_Results;
typedef struct
{
char currentpath[MAXPATHLENGTH];
char *path;
int textgrab;
char *resptr;
int32 reslen;
XPath_Results *xpres;
} pgxml_udata;
#define UD ((pgxml_udata *) userData)

View File

@ -1,10 +0,0 @@
-- SQL for XML parser
-- Adjust this setting to control where the objects get created.
SET search_path TO public;
CREATE OR REPLACE FUNCTION pgxml_parse(text) RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE c STRICT;
CREATE OR REPLACE FUNCTION pgxml_xpath(text, text, text, text) RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE c STRICT;

View File

@ -1,265 +0,0 @@
/* Parser interface for DOM-based parser (libxml) rather than
stream-based SAX-type parser */
#include "postgres.h"
#include "fmgr.h"
/* libxml includes */
#include <libxml/xpath.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
/* declarations */
static void *pgxml_palloc(size_t size);
static void *pgxml_repalloc(void *ptr, size_t size);
static void pgxml_pfree(void *ptr);
static char *pgxml_pstrdup(const char *string);
static void pgxml_parser_init();
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc,
xmlChar * toptagname, xmlChar * septagname,
int format);
static xmlChar *pgxml_texttoxmlchar(text *textstring);
Datum pgxml_parse(PG_FUNCTION_ARGS);
Datum pgxml_xpath(PG_FUNCTION_ARGS);
/* memory handling passthrough functions (e.g. palloc, pstrdup are
currently macros, and the others might become so...) */
static void *
pgxml_palloc(size_t size)
{
return palloc(size);
}
static void *
pgxml_repalloc(void *ptr, size_t size)
{
return repalloc(ptr, size);
}
static void
pgxml_pfree(void *ptr)
{
pfree(ptr);
}
static char *
pgxml_pstrdup(const char *string)
{
return pstrdup(string);
}
static void
pgxml_parser_init()
{
/*
* This code should also set parser settings from user-supplied info.
* Quite how these settings are made is another matter :)
*/
xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
xmlInitParser();
}
/* Returns true if document is well-formed */
PG_FUNCTION_INFO_V1(pgxml_parse);
Datum
pgxml_parse(PG_FUNCTION_ARGS)
{
/* called as pgxml_parse(document) */
xmlDocPtr doctree;
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
int32 docsize = VARSIZE(t) - VARHDRSZ;
pgxml_parser_init();
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
if (doctree == NULL)
{
xmlCleanupParser();
PG_RETURN_BOOL(false); /* i.e. not well-formed */
}
xmlCleanupParser();
xmlFreeDoc(doctree);
PG_RETURN_BOOL(true);
}
static xmlChar
*
pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
xmlDocPtr doc,
xmlChar * toptagname,
xmlChar * septagname,
int format)
{
/* Function translates a nodeset into a text representation */
/*
* iterates over each node in the set and calls xmlNodeDump to write
* it to an xmlBuffer -from which an xmlChar * string is returned.
*/
/* each representation is surrounded by <tagname> ... </tagname> */
/* if format==0, add a newline between nodes?? */
xmlBufferPtr buf;
xmlChar *result;
int i;
buf = xmlBufferCreate();
if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
{
xmlBufferWriteChar(buf, "<");
xmlBufferWriteCHAR(buf, toptagname);
xmlBufferWriteChar(buf, ">");
}
if (nodeset != NULL)
{
for (i = 0; i < nodeset->nodeNr; i++)
{
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
xmlBufferWriteChar(buf, "<");
xmlBufferWriteCHAR(buf, septagname);
xmlBufferWriteChar(buf, ">");
}
xmlNodeDump(buf, doc, nodeset->nodeTab[i], 1, (format == 2));
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
xmlBufferWriteChar(buf, "</");
xmlBufferWriteCHAR(buf, septagname);
xmlBufferWriteChar(buf, ">");
}
if (format)
xmlBufferWriteChar(buf, "\n");
}
}
if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
{
xmlBufferWriteChar(buf, "</");
xmlBufferWriteCHAR(buf, toptagname);
xmlBufferWriteChar(buf, ">");
}
result = xmlStrdup(buf->content);
xmlBufferFree(buf);
return result;
}
static xmlChar *
pgxml_texttoxmlchar(text *textstring)
{
xmlChar *res;
int32 txsize;
txsize = VARSIZE(textstring) - VARHDRSZ;
res = (xmlChar *) palloc(txsize + 1);
memcpy((char *) res, VARDATA(textstring), txsize);
res[txsize] = '\0';
return res;
}
PG_FUNCTION_INFO_V1(pgxml_xpath);
Datum
pgxml_xpath(PG_FUNCTION_ARGS)
{
xmlDocPtr doctree;
xmlXPathContextPtr ctxt;
xmlXPathObjectPtr res;
xmlChar *xpath,
*xpresstr,
*toptag,
*septag;
xmlXPathCompExprPtr comppath;
int32 docsize,
ressize;
text *t,
*xpres;
t = PG_GETARG_TEXT_P(0); /* document buffer */
xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */
toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
docsize = VARSIZE(t) - VARHDRSZ;
pgxml_parser_init();
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
if (doctree == NULL)
{ /* not well-formed */
xmlCleanupParser();
PG_RETURN_NULL();
}
ctxt = xmlXPathNewContext(doctree);
ctxt->node = xmlDocGetRootElement(doctree);
/* compile the path */
comppath = xmlXPathCompile(xpath);
if (comppath == NULL)
{
elog(WARNING, "XPath syntax error");
xmlFreeDoc(doctree);
pfree(xpath);
xmlCleanupParser();
PG_RETURN_NULL();
}
/* Now evaluate the path expression. */
res = xmlXPathCompiledEval(comppath, ctxt);
xmlXPathFreeCompExpr(comppath);
if (res == NULL)
{
xmlFreeDoc(doctree);
pfree(xpath);
xmlCleanupParser();
PG_RETURN_NULL(); /* seems appropriate */
}
/* now we dump this node, ?surrounding by tags? */
/* To do this, we look first at the type */
switch (res->type)
{
case XPATH_NODESET:
xpresstr = pgxmlNodeSetToText(res->nodesetval,
doctree,
toptag, septag, 0);
break;
case XPATH_STRING:
xpresstr = xmlStrdup(res->stringval);
break;
default:
elog(WARNING, "Unsupported XQuery result: %d", res->type);
xpresstr = xmlStrdup("<unsupported/>");
}
/* Now convert this result back to text */
ressize = strlen(xpresstr);
xpres = (text *) palloc(ressize + VARHDRSZ);
memcpy(VARDATA(xpres), xpresstr, ressize);
VARATT_SIZEP(xpres) = ressize + VARHDRSZ;
/* Free various storage */
xmlFreeDoc(doctree);
pfree(xpath);
xmlFree(xpresstr);
xmlCleanupParser();
PG_RETURN_TEXT_P(xpres);
}

View File

@ -1,10 +0,0 @@
-- SQL for XML parser
-- Adjust this setting to control where the objects get created.
SET search_path TO public;
CREATE OR REPLACE FUNCTION pgxml_parse(text) RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE c STRICT;
CREATE OR REPLACE FUNCTION pgxml_xpath(text, text, text, text) RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE c STRICT;