Update this branch to match CVS head, includes WIN32 improvements.
authorBruce Momjian <[email protected]>
Sun, 7 Sep 2003 04:37:13 +0000 (04:37 +0000)
committerBruce Momjian <[email protected]>
Sun, 7 Sep 2003 04:37:13 +0000 (04:37 +0000)
376 files changed:
HISTORY
config/ac_func_accept_argtypes.m4
config/python.m4
configure
configure.in
contrib/contrib-global.mk
contrib/tsearch/parser.h
contrib/tsearch/parser.l
contrib/tsearch2/Makefile [new file with mode: 0644]
contrib/tsearch2/docs/tsearch-V2-intro.html [new file with mode: 0644]
contrib/tsearch2/expected/tsearch2.out [new file with mode: 0644]
contrib/tsearch2/ispell/Makefile [new file with mode: 0644]
contrib/tsearch2/query.c [new file with mode: 0644]
contrib/tsearch2/query.h [new file with mode: 0644]
contrib/tsearch2/rewrite.c [new file with mode: 0644]
contrib/tsearch2/snowball/Makefile [new file with mode: 0644]
contrib/tsearch2/sql/tsearch2.sql [new file with mode: 0644]
contrib/tsearch2/wordparser/Makefile [new file with mode: 0644]
contrib/tsearch2/wordparser/parser.h [new file with mode: 0644]
contrib/tsearch2/wordparser/parser.l [new file with mode: 0644]
doc/FAQ
doc/FAQ_german
doc/TODO
doc/src/FAQ/FAQ.html
doc/src/FAQ/FAQ_german.html
doc/src/sgml/Makefile
doc/src/sgml/advanced.sgml
doc/src/sgml/array.sgml
doc/src/sgml/backup.sgml
doc/src/sgml/charset.sgml
doc/src/sgml/client-auth.sgml
doc/src/sgml/datatype.sgml
doc/src/sgml/datetime.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/dfunc.sgml
doc/src/sgml/dml.sgml
doc/src/sgml/ecpg.sgml
doc/src/sgml/extend.sgml
doc/src/sgml/filelist.sgml
doc/src/sgml/func.sgml
doc/src/sgml/indices.sgml
doc/src/sgml/installation.sgml
doc/src/sgml/jdbc.sgml
doc/src/sgml/keywords.sgml
doc/src/sgml/libpgtcl.sgml
doc/src/sgml/libpq.sgml
doc/src/sgml/lobj.sgml
doc/src/sgml/maintenance.sgml
doc/src/sgml/manage-ag.sgml
doc/src/sgml/monitoring.sgml
doc/src/sgml/mvcc.sgml
doc/src/sgml/perform.sgml
doc/src/sgml/plperl.sgml
doc/src/sgml/plpgsql.sgml
doc/src/sgml/plpython.sgml
doc/src/sgml/pltcl.sgml
doc/src/sgml/postgres.sgml
doc/src/sgml/protocol.sgml
doc/src/sgml/queries.sgml
doc/src/sgml/query.sgml
doc/src/sgml/ref/abort.sgml
doc/src/sgml/ref/alter_aggregate.sgml
doc/src/sgml/ref/alter_conversion.sgml
doc/src/sgml/ref/alter_database.sgml
doc/src/sgml/ref/alter_domain.sgml
doc/src/sgml/ref/alter_function.sgml
doc/src/sgml/ref/alter_group.sgml
doc/src/sgml/ref/alter_language.sgml
doc/src/sgml/ref/alter_opclass.sgml
doc/src/sgml/ref/alter_schema.sgml
doc/src/sgml/ref/alter_sequence.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/alter_trigger.sgml
doc/src/sgml/ref/alter_user.sgml
doc/src/sgml/ref/analyze.sgml
doc/src/sgml/ref/begin.sgml
doc/src/sgml/ref/checkpoint.sgml
doc/src/sgml/ref/close.sgml
doc/src/sgml/ref/cluster.sgml
doc/src/sgml/ref/clusterdb.sgml
doc/src/sgml/ref/comment.sgml
doc/src/sgml/ref/commit.sgml
doc/src/sgml/ref/copy.sgml
doc/src/sgml/ref/create_aggregate.sgml
doc/src/sgml/ref/create_cast.sgml
doc/src/sgml/ref/create_constraint.sgml
doc/src/sgml/ref/create_conversion.sgml
doc/src/sgml/ref/create_database.sgml
doc/src/sgml/ref/create_domain.sgml
doc/src/sgml/ref/create_function.sgml
doc/src/sgml/ref/create_group.sgml
doc/src/sgml/ref/create_index.sgml
doc/src/sgml/ref/create_language.sgml
doc/src/sgml/ref/create_opclass.sgml
doc/src/sgml/ref/create_operator.sgml
doc/src/sgml/ref/create_rule.sgml
doc/src/sgml/ref/create_schema.sgml
doc/src/sgml/ref/create_sequence.sgml
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/create_table_as.sgml
doc/src/sgml/ref/create_trigger.sgml
doc/src/sgml/ref/create_type.sgml
doc/src/sgml/ref/create_user.sgml
doc/src/sgml/ref/create_view.sgml
doc/src/sgml/ref/createdb.sgml
doc/src/sgml/ref/createlang.sgml
doc/src/sgml/ref/createuser.sgml
doc/src/sgml/ref/deallocate.sgml
doc/src/sgml/ref/declare.sgml
doc/src/sgml/ref/delete.sgml
doc/src/sgml/ref/drop_aggregate.sgml
doc/src/sgml/ref/drop_cast.sgml
doc/src/sgml/ref/drop_conversion.sgml
doc/src/sgml/ref/drop_database.sgml
doc/src/sgml/ref/drop_domain.sgml
doc/src/sgml/ref/drop_function.sgml
doc/src/sgml/ref/drop_group.sgml
doc/src/sgml/ref/drop_index.sgml
doc/src/sgml/ref/drop_language.sgml
doc/src/sgml/ref/drop_opclass.sgml
doc/src/sgml/ref/drop_operator.sgml
doc/src/sgml/ref/drop_rule.sgml
doc/src/sgml/ref/drop_schema.sgml
doc/src/sgml/ref/drop_sequence.sgml
doc/src/sgml/ref/drop_table.sgml
doc/src/sgml/ref/drop_trigger.sgml
doc/src/sgml/ref/drop_type.sgml
doc/src/sgml/ref/drop_user.sgml
doc/src/sgml/ref/drop_view.sgml
doc/src/sgml/ref/dropdb.sgml
doc/src/sgml/ref/droplang.sgml
doc/src/sgml/ref/dropuser.sgml
doc/src/sgml/ref/ecpg-ref.sgml
doc/src/sgml/ref/end.sgml
doc/src/sgml/ref/execute.sgml
doc/src/sgml/ref/explain.sgml
doc/src/sgml/ref/fetch.sgml
doc/src/sgml/ref/grant.sgml
doc/src/sgml/ref/initdb.sgml
doc/src/sgml/ref/initlocation.sgml
doc/src/sgml/ref/insert.sgml
doc/src/sgml/ref/ipcclean.sgml
doc/src/sgml/ref/listen.sgml
doc/src/sgml/ref/load.sgml
doc/src/sgml/ref/lock.sgml
doc/src/sgml/ref/move.sgml
doc/src/sgml/ref/notify.sgml
doc/src/sgml/ref/pg_config-ref.sgml
doc/src/sgml/ref/pg_controldata.sgml
doc/src/sgml/ref/pg_ctl-ref.sgml
doc/src/sgml/ref/pg_dump.sgml
doc/src/sgml/ref/pg_dumpall.sgml
doc/src/sgml/ref/pg_restore.sgml
doc/src/sgml/ref/pgtclsh.sgml
doc/src/sgml/ref/pgtksh.sgml
doc/src/sgml/ref/postgres-ref.sgml
doc/src/sgml/ref/postmaster.sgml
doc/src/sgml/ref/prepare.sgml
doc/src/sgml/ref/psql-ref.sgml
doc/src/sgml/ref/reindex.sgml
doc/src/sgml/ref/reset.sgml
doc/src/sgml/ref/revoke.sgml
doc/src/sgml/ref/rollback.sgml
doc/src/sgml/ref/select.sgml
doc/src/sgml/ref/select_into.sgml
doc/src/sgml/ref/set.sgml
doc/src/sgml/ref/set_constraints.sgml
doc/src/sgml/ref/set_session_auth.sgml
doc/src/sgml/ref/set_transaction.sgml
doc/src/sgml/ref/show.sgml
doc/src/sgml/ref/start_transaction.sgml
doc/src/sgml/ref/truncate.sgml
doc/src/sgml/ref/unlisten.sgml
doc/src/sgml/ref/update.sgml
doc/src/sgml/ref/vacuum.sgml
doc/src/sgml/ref/vacuumdb.sgml
doc/src/sgml/regress.sgml
doc/src/sgml/release.sgml
doc/src/sgml/rules.sgml
doc/src/sgml/runtime.sgml
doc/src/sgml/spi.sgml
doc/src/sgml/syntax.sgml
doc/src/sgml/trigger.sgml
doc/src/sgml/typeconv.sgml
doc/src/sgml/user-manag.sgml
doc/src/sgml/wal.sgml
doc/src/sgml/xaggr.sgml
doc/src/sgml/xfunc.sgml
doc/src/sgml/xindex.sgml
doc/src/sgml/xoper.sgml
doc/src/sgml/xplang.sgml
doc/src/sgml/xtypes.sgml
src/Makefile.global.in
src/backend/access/hash/hash.c
src/backend/access/hash/hashinsert.c
src/backend/access/hash/hashovfl.c
src/backend/access/hash/hashpage.c
src/backend/access/hash/hashscan.c
src/backend/access/hash/hashsearch.c
src/backend/access/hash/hashutil.c
src/backend/access/nbtree/nbtinsert.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/aclchk.c
src/backend/commands/analyze.c
src/backend/commands/copy.c
src/backend/commands/indexcmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/portalcmds.c
src/backend/commands/tablecmds.c
src/backend/executor/execGrouping.c
src/backend/executor/execQual.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeSubplan.c
src/backend/libpq/hba.c
src/backend/libpq/ip.c
src/backend/libpq/pg_hba.conf.sample
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/util/clauses.c
src/backend/parser/gram.y
src/backend/parser/parse_clause.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_oper.c
src/backend/po/ru.po
src/backend/port/ipc_test.c
src/backend/storage/lmgr/lmgr.c
src/backend/storage/lmgr/lock.c
src/backend/tcop/postgres.c
src/backend/utils/adt/acl.c
src/backend/utils/adt/array_userfuncs.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/cash.c
src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/backend/utils/adt/formatting.c
src/backend/utils/adt/nabstime.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/timestamp.c
src/backend/utils/cache/Makefile
src/backend/utils/cache/lsyscache.c
src/backend/utils/error/elog.c
src/backend/utils/fmgr/dfmgr.c
src/backend/utils/hash/dynahash.c
src/backend/utils/hash/hashfn.c
src/backend/utils/init/globals.c
src/backend/utils/mb/Unicode/UCS_to_GB18030.pl
src/backend/utils/mb/Unicode/gb18030_to_utf8.map
src/backend/utils/mb/conversion_procs/Makefile
src/backend/utils/mb/conversion_procs/proc.mk
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/mmgr/portalmem.c
src/backend/utils/sort/tuplesort.c
src/bin/initdb/Makefile
src/bin/initdb/initdb.sh
src/bin/pg_controldata/po/ru.po
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_restore.c
src/bin/pg_id/pg_id.c
src/bin/pg_resetxlog/pg_resetxlog.c
src/bin/pg_resetxlog/po/ru.po
src/bin/psql/common.c
src/bin/psql/common.h
src/bin/psql/describe.c
src/bin/psql/input.c
src/bin/psql/mbprint.c
src/bin/psql/nls.mk
src/bin/psql/po/de.po
src/bin/psql/po/fr.po
src/bin/psql/po/ru.po
src/bin/psql/po/sv.po
src/bin/psql/prompt.c
src/bin/scripts/Makefile
src/bin/scripts/common.c
src/bin/scripts/po/ru.po [new file with mode: 0644]
src/include/access/hash.h
src/include/catalog/catversion.h
src/include/catalog/pg_amop.h
src/include/catalog/pg_amproc.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/executor/executor.h
src/include/libpq/ip.h
src/include/miscadmin.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/nodes/pg_list.h
src/include/nodes/primnodes.h
src/include/parser/parse_clause.h
src/include/parser/parse_oper.h
src/include/pg_config.h.in
src/include/port.h
src/include/postgres_ext.h
src/include/storage/lmgr.h
src/include/utils/acl.h
src/include/utils/builtins.h
src/include/utils/cash.h
src/include/utils/datetime.h
src/include/utils/errcodes.h [new file with mode: 0644]
src/include/utils/guc.h
src/include/utils/hsearch.h
src/include/utils/lsyscache.h
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/ecpglib/connect.c
src/interfaces/ecpg/ecpglib/error.c
src/interfaces/ecpg/include/sqltypes.h
src/interfaces/ecpg/pgtypeslib/timestamp.c
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/test/test1.pgc
src/interfaces/ecpg/test/test_thread.pgc [new file with mode: 0644]
src/interfaces/jdbc/build.xml
src/interfaces/jdbc/org/postgresql/errors.properties
src/interfaces/jdbc/org/postgresql/errors_de.properties
src/interfaces/jdbc/org/postgresql/errors_it.properties
src/interfaces/jdbc/org/postgresql/errors_nl.properties
src/interfaces/jdbc/org/postgresql/errors_zh_TW.properties
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/ResultSetTest.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java
src/interfaces/libpq/Makefile
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/fe-protocol2.c
src/interfaces/libpq/fe-protocol3.c
src/interfaces/libpq/fe-secure.c
src/interfaces/libpq/libpq-int.h
src/interfaces/libpq/po/es.po
src/interfaces/libpq/po/fr.po
src/interfaces/libpq/po/ru.po
src/interfaces/libpq/po/sv.po
src/interfaces/libpq/win32.c
src/interfaces/libpq/win32.mak
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/plpgsql.h
src/pl/tcl/pltcl.c
src/port/thread.c [new file with mode: 0644]
src/template/bsdi
src/template/freebsd
src/template/linux
src/template/netbsd
src/template/osf
src/template/unixware
src/test/regress/expected/abstime-solaris-1947.out
src/test/regress/expected/abstime.out
src/test/regress/expected/arrays.out
src/test/regress/expected/circle.out
src/test/regress/expected/date.out
src/test/regress/expected/geometry.out
src/test/regress/expected/geometry_1.out
src/test/regress/expected/horology-no-DST-before-1970.out
src/test/regress/expected/horology-solaris-1947.out
src/test/regress/expected/horology.out
src/test/regress/expected/polymorphism.out [new file with mode: 0644]
src/test/regress/expected/portals.out
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/arrays.sql
src/test/regress/sql/circle.sql
src/test/regress/sql/geometry.sql
src/tools/pgindent/pgindent

diff --git a/HISTORY b/HISTORY
index b12404d18e9789dff5ba78759d0d4cc3d2da5cf0..29c12069af5b3f49ed317d21616bc5b2c59a31bf 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -212,6 +212,7 @@ Add new DateStyle values MDY, DMY, and YMD, honor US and European for
   prepared statements) (Tom)
 Assume NaN value to be larger than any other value in MIN()/MAX() (Tom)
 Prevent interval from supressing ':00' seconds display
+New pg_get_triggerdef(prettyprint) and pg_constraint_is_visible() functions
 
      _________________________________________________________________
 
@@ -259,6 +260,10 @@ Allow pqInternalNotice() to accept a format string and args instead of
   just a preformatted message (Tom, Sean Chittenden)
 Allow control SSL negotiation with sslmode values "disable", "allow", 
   "Prefer", and "require" (Jon Jensen)
+Allow new error codes and levels of text (Tom)
+Allow access to the underlying table and column of a query result (Tom)
+Allow access to the current transaction status (Tom)
+Add ability to pass binary data directly to the backend (Tom)
 
      _________________________________________________________________
 
index 47f3dba12f5d1feecbc3e9054c55953049af8aba..b4cf3c694dd80cba6f24acd8f000fb65eb2ae208 100644 (file)
@@ -7,9 +7,10 @@
 dnl @synopsis AC_FUNC_ACCEPT_ARGTYPES
 dnl
 dnl Checks the data types of the three arguments to accept(). Results are
-dnl placed into the symbols ACCEPT_TYPE_ARG[123], consistent with the
-dnl following example:
+dnl placed into the symbols ACCEPT_TYPE_RETURN and ACCEPT_TYPE_ARG[123], 
+dnl consistent with the following example:
 dnl
+dnl       #define ACCEPT_TYPE_RETURN int
 dnl       #define ACCEPT_TYPE_ARG1 int
 dnl       #define ACCEPT_TYPE_ARG2 struct sockaddr *
 dnl       #define ACCEPT_TYPE_ARG3 socklen_t
@@ -36,24 +37,29 @@ dnl
 # Solaris 7 and 8 have arg3 as 'void *' (disguised as 'Psocklen_t'
 # which is *not* 'socklen_t *').  If we detect that, then we assume
 # 'int' as the result, because that ought to work best.
+#
+# On Win32, accept() returns 'unsigned int PASCAL' 
 
 AC_DEFUN([AC_FUNC_ACCEPT_ARGTYPES],
 [AC_MSG_CHECKING([types of arguments for accept()])
- AC_CACHE_VAL(ac_cv_func_accept_arg1,dnl
- [AC_CACHE_VAL(ac_cv_func_accept_arg2,dnl
-  [AC_CACHE_VAL(ac_cv_func_accept_arg3,dnl
-   [for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do
-     for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do
-      for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do
-       AC_TRY_COMPILE(
+ AC_CACHE_VAL(ac_cv_func_accept_return,dnl
+ [AC_CACHE_VAL(ac_cv_func_accept_arg1,dnl
+  [AC_CACHE_VAL(ac_cv_func_accept_arg2,dnl
+   [AC_CACHE_VAL(ac_cv_func_accept_arg3,dnl
+    [for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do
+      for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do
+       for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do
+        for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do
+         AC_TRY_COMPILE(
 [#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
-extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);],
-        [], [ac_not_found=no; break 3], [ac_not_found=yes])
+extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);],
+         [], [ac_not_found=no; break 4], [ac_not_found=yes])
+       done
       done
      done
     done
@@ -63,10 +69,13 @@ extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func
     if test "$ac_cv_func_accept_arg3" = "void"; then
       ac_cv_func_accept_arg3=int
     fi
+    ])dnl AC_CACHE_VAL
    ])dnl AC_CACHE_VAL
   ])dnl AC_CACHE_VAL
  ])dnl AC_CACHE_VAL
- AC_MSG_RESULT([$ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *])
+ AC_MSG_RESULT([$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *])
+ AC_DEFINE_UNQUOTED(ACCEPT_TYPE_RETURN, $ac_cv_func_accept_return,
+                    [Define to the return type of 'accept'])
  AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG1, $ac_cv_func_accept_arg1,
                     [Define to the type of arg 1 of 'accept'])
  AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG2, $ac_cv_func_accept_arg2,
index 2c235121adef916f514ec43510ffd881c9ef7060..f237366d13b909a89d8081db1ee8ebe82ef2cdbc 100644 (file)
@@ -26,19 +26,14 @@ python_version=`${PYTHON} -c "import sys; print sys.version[[:3]]"`
 python_prefix=`${PYTHON} -c "import sys; print sys.prefix"`
 python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"`
 python_configdir="${python_execprefix}/lib/python${python_version}/config"
-python_moduledir="${python_prefix}/lib/python${python_version}/site-packages"
-python_moduleexecdir="${python_execprefix}/lib/python${python_version}/site-packages"
 python_includespec="-I${python_prefix}/include/python${python_version}"
 if test "$python_prefix" != "$python_execprefix"; then
   python_includespec="-I${python_execprefix}/include/python${python_version} $python_includespec"
 fi
 
-AC_SUBST(python_version)[]dnl
 AC_SUBST(python_prefix)[]dnl
 AC_SUBST(python_execprefix)[]dnl
 AC_SUBST(python_configdir)[]dnl
-AC_SUBST(python_moduledir)[]dnl
-AC_SUBST(python_moduleexecdir)[]dnl
 AC_SUBST(python_includespec)[]dnl
 # This should be enough of a message.
 if test "$python_prefix" != "$python_execprefix"; then
@@ -49,19 +44,6 @@ fi
 ])# _PGAC_CHECK_PYTHON_DIRS
 
 
-# PGAC_CHECK_PYTHON_MODULE_SETUP
-# ------------------------------
-# Finds things required to build a Python extension module.
-# This used to do more, that's why it's separate.
-#
-# It would be nice if we could check whether the current setup allows
-# the build of the shared module. Future project.
-AC_DEFUN([PGAC_CHECK_PYTHON_MODULE_SETUP],
-[
-  AC_REQUIRE([_PGAC_CHECK_PYTHON_DIRS])
-])# PGAC_CHECK_PYTHON_MODULE_SETUP
-
-
 # PGAC_CHECK_PYTHON_EMBED_SETUP
 # -----------------------------
 # Courtesy of the INN 2.3.1 package...
index 2ba5879468ff6cb2ccd241a92c84a1fe1b25e5c9..be06d57d51d06917a00629380b5cb516217516f7 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.53 for PostgreSQL 7.4beta1.
+# Generated by GNU Autoconf 2.53 for PostgreSQL 7.4beta2.
 #
 # Report bugs to <[email protected]>.
 #
@@ -258,8 +258,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='PostgreSQL'
 PACKAGE_TARNAME='postgresql'
-PACKAGE_VERSION='7.4beta1'
-PACKAGE_STRING='PostgreSQL 7.4beta1'
+PACKAGE_VERSION='7.4beta2'
+PACKAGE_STRING='PostgreSQL 7.4beta2'
 PACKAGE_BUGREPORT='[email protected]'
 
 ac_unique_file="src/backend/access/common/heaptuple.c"
@@ -769,7 +769,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures PostgreSQL 7.4beta1 to adapt to many kinds of systems.
+\`configure' configures PostgreSQL 7.4beta2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -830,7 +830,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of PostgreSQL 7.4beta1:";;
+     short | recursive ) echo "Configuration of PostgreSQL 7.4beta2:";;
    esac
   cat <<\_ACEOF
 
@@ -860,7 +860,7 @@ Optional Packages:
   --with-tclconfig=DIR    tclConfig.sh and tkConfig.sh are in DIR
   --with-tkconfig=DIR     tkConfig.sh is in DIR
   --with-perl             build Perl modules (PL/Perl)
-  --with-python           build Python interface module
+  --with-python           build Python modules (PL/Python)
   --with-java             build JDBC interface and Java tools
   --with-krb4[=DIR]       build with Kerberos 4 support [/usr/athena]
   --with-krb5[=DIR]       build with Kerberos 5 support [/usr/athena]
@@ -949,7 +949,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-PostgreSQL configure 7.4beta1
+PostgreSQL configure 7.4beta2
 generated by GNU Autoconf 2.53
 
 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@@ -966,7 +966,7 @@ cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by PostgreSQL $as_me 7.4beta1, which was
+It was created by PostgreSQL $as_me 7.4beta2, which was
 generated by GNU Autoconf 2.53.  Invocation command line was
 
   $ $0 $@
@@ -2370,6 +2370,12 @@ fi
 { echo "$as_me:$LINENO: using CFLAGS=$CFLAGS" >&5
 echo "$as_me: using CFLAGS=$CFLAGS" >&6;}
 
+# We already have this in Makefile.win32, but configure needs it too
+if test "$PORTNAME" = "win32"
+then
+       CPPFLAGS="$CPPFLAGS -Isrc/include/port/win32"
+fi
+
 # Check if the compiler still works with the template settings
 echo "$as_me:$LINENO: checking whether the C compiler still works" >&5
 echo $ECHO_N "checking whether the C compiler still works... $ECHO_C" >&6
@@ -2981,7 +2987,7 @@ echo "${ECHO_T}$with_perl" >&6
 
 
 #
-# Optionally build Python interface module
+# Optionally build Python modules (PL/Python)
 #
 echo "$as_me:$LINENO: checking whether to build Python modules" >&5
 echo $ECHO_N "checking whether to build Python modules... $ECHO_C" >&6
@@ -4294,8 +4300,6 @@ python_version=`${PYTHON} -c "import sys; print sys.version[:3]"`
 python_prefix=`${PYTHON} -c "import sys; print sys.prefix"`
 python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"`
 python_configdir="${python_execprefix}/lib/python${python_version}/config"
-python_moduledir="${python_prefix}/lib/python${python_version}/site-packages"
-python_moduleexecdir="${python_execprefix}/lib/python${python_version}/site-packages"
 python_includespec="-I${python_prefix}/include/python${python_version}"
 if test "$python_prefix" != "$python_execprefix"; then
   python_includespec="-I${python_execprefix}/include/python${python_version} $python_includespec"
@@ -4311,9 +4315,6 @@ echo "${ECHO_T}$python_prefix/lib/python${python_version}" >&6
 fi
 
 
-
-
-
 echo "$as_me:$LINENO: checking how to link an embedded Python application" >&5
 echo $ECHO_N "checking how to link an embedded Python application... $ECHO_C" >&6
 
@@ -10815,19 +10816,23 @@ _ACEOF
 fi
 echo "$as_me:$LINENO: checking types of arguments for accept()" >&5
 echo $ECHO_N "checking types of arguments for accept()... $ECHO_C" >&6
- if test "${ac_cv_func_accept_arg1+set}" = set; then
+ if test "${ac_cv_func_accept_return+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-   if test "${ac_cv_func_accept_arg2+set}" = set; then
+   if test "${ac_cv_func_accept_arg1+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-    if test "${ac_cv_func_accept_arg3+set}" = set; then
+    if test "${ac_cv_func_accept_arg2+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-     for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do
-     for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do
-      for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do
-       cat >conftest.$ac_ext <<_ACEOF
+     if test "${ac_cv_func_accept_arg3+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do
+      for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do
+       for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do
+        for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do
+         cat >conftest.$ac_ext <<_ACEOF
 #line $LINENO "configure"
 #include "confdefs.h"
 #ifdef HAVE_SYS_TYPES_H
@@ -10836,7 +10841,7 @@ else
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
-extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);
+extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);
 #ifdef F77_DUMMY_MAIN
 #  ifdef __cplusplus
      extern "C"
@@ -10863,13 +10868,14 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_not_found=no; break 3
+  ac_not_found=no; break 4
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
 ac_not_found=yes
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
+       done
       done
      done
     done
 fi
 
 fi
- echo "$as_me:$LINENO: result: $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&5
-echo "${ECHO_T}$ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&6
+
+fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&5
+echo "${ECHO_T}$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define ACCEPT_TYPE_RETURN $ac_cv_func_accept_return
+_ACEOF
+
 
 cat >>confdefs.h <<_ACEOF
 #define ACCEPT_TYPE_ARG1 $ac_cv_func_accept_arg1
@@ -11198,6 +11211,7 @@ fi
 
 
 
+HAVE_IPV6=no
 echo "$as_me:$LINENO: checking for struct sockaddr_in6" >&5
 echo $ECHO_N "checking for struct sockaddr_in6... $ECHO_C" >&6
 if test "${ac_cv_type_struct_sockaddr_in6+set}" = set; then
@@ -11319,11 +11333,13 @@ cat >>confdefs.h <<\_ACEOF
 #define HAVE_IPV6 1
 _ACEOF
 
+                                                         HAVE_IPV6=yes
 fi
 
 fi
 
 
+
 echo "$as_me:$LINENO: checking for PS_STRINGS" >&5
 echo $ECHO_N "checking for PS_STRINGS... $ECHO_C" >&6
 if test "${pgac_cv_var_PS_STRINGS+set}" = set; then
@@ -13102,6 +13118,7 @@ fi
 #
 # For each platform, we need to know about any special compile and link
 # libraries, and whether the normal C function names are thread-safe.
+# See the comment at the top of src/port/thread.c for more information.
 #
 if test "$enable_thread_safety" = yes; then
 if test "${ac_cv_header_pthread_h+set}" = set; then
@@ -13208,8 +13225,8 @@ fi
 if test $ac_cv_header_pthread_h = yes; then
   :
 else
-  { { echo "$as_me:$LINENO: error: pthread.h not found, required for --with-threads" >&5
-echo "$as_me: error: pthread.h not found, required for --with-threads" >&2;}
+  { { echo "$as_me:$LINENO: error: pthread.h not found, required for --enable-thread-safetys" >&5
+echo "$as_me: error: pthread.h not found, required for --enable-thread-safetys" >&2;}
    { (exit 1); exit 1; }; }
 fi
 
@@ -13221,12 +13238,14 @@ Cannot enable threads on your platform.
 Please report your platform threading info to the PostgreSQL mailing lists
 so it can be added to the next release.  Report all compile flags, link flags,
 functions, or libraries required for threading support.
+See the comment at the top of src/port/thread.c for more information.
 " >&5
 echo "$as_me: error:
 Cannot enable threads on your platform.
 Please report your platform threading info to the PostgreSQL mailing lists
 so it can be added to the next release.  Report all compile flags, link flags,
 functions, or libraries required for threading support.
+See the comment at the top of src/port/thread.c for more information.
 " >&2;}
    { (exit 1); exit 1; }; }
 fi
@@ -13254,22 +13273,88 @@ _CFLAGS="$CFLAGS"
 _LIBS="$LIBS"
 CFLAGS="$CFLAGS $THREAD_CFLAGS"
 LIBS="$LIBS $THREAD_LIBS"
+echo "$as_me:$LINENO: checking for strerror_r" >&5
+echo $ECHO_N "checking for strerror_r... $ECHO_C" >&6
+if test "${ac_cv_func_strerror_r+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strerror_r (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror_r ();
+char (*f) ();
 
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_strerror_r) || defined (__stub___strerror_r)
+choke me
+#else
+f = strerror_r;
+#endif
 
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_strerror_r=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_strerror_r=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strerror_r" >&5
+echo "${ECHO_T}$ac_cv_func_strerror_r" >&6
+if test $ac_cv_func_strerror_r = yes; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: strerror_r not found, required on this platform for --enable-thread-safety" >&5
+echo "$as_me: error: strerror_r not found, required on this platform for --enable-thread-safety" >&2;}
+   { (exit 1); exit 1; }; }
+fi
 
-for ac_func in strerror_r getpwuid_r gethostbyname_r
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
+echo "$as_me:$LINENO: checking for getpwuid_r" >&5
+echo $ECHO_N "checking for getpwuid_r... $ECHO_C" >&6
+if test "${ac_cv_func_getpwuid_r+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
 #line $LINENO "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.  */
+    which can conflict with char getpwuid_r (); below.  */
 #include <assert.h>
 /* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
@@ -13277,7 +13362,7 @@ extern "C"
 #endif
 /* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
-char $ac_func ();
+char getpwuid_r ();
 char (*f) ();
 
 #ifdef F77_DUMMY_MAIN
@@ -13292,10 +13377,10 @@ main ()
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+#if defined (__stub_getpwuid_r) || defined (__stub___getpwuid_r)
 choke me
 #else
-f = $ac_func;
+f = getpwuid_r;
 #endif
 
   ;
@@ -13314,23 +13399,95 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  eval "$as_ac_var=yes"
+  ac_cv_func_getpwuid_r=yes
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-eval "$as_ac_var=no"
+ac_cv_func_getpwuid_r=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+echo "$as_me:$LINENO: result: $ac_cv_func_getpwuid_r" >&5
+echo "${ECHO_T}$ac_cv_func_getpwuid_r" >&6
+if test $ac_cv_func_getpwuid_r = yes; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: getpwuid_r not found, required on this platform for --enable-thread-safety" >&5
+echo "$as_me: error: getpwuid_r not found, required on this platform for --enable-thread-safety" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+echo "$as_me:$LINENO: checking for gethostbyname_r" >&5
+echo $ECHO_N "checking for gethostbyname_r... $ECHO_C" >&6
+if test "${ac_cv_func_gethostbyname_r+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char gethostbyname_r (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostbyname_r ();
+char (*f) ();
 
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_gethostbyname_r) || defined (__stub___gethostbyname_r)
+choke me
+#else
+f = gethostbyname_r;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_gethostbyname_r=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_gethostbyname_r=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname_r" >&5
+echo "${ECHO_T}$ac_cv_func_gethostbyname_r" >&6
+if test $ac_cv_func_gethostbyname_r = yes; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: gethostbyname_r not found, required on this platform for --enable-thread-safety" >&5
+echo "$as_me: error: gethostbyname_r not found, required on this platform for --enable-thread-safety" >&2;}
+   { (exit 1); exit 1; }; }
 fi
-done
 
 CFLAGS="$_CFLAGS"
 LIBS="$_LIBS"
@@ -17838,7 +17995,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by PostgreSQL $as_me 7.4beta1, which was
+This file was extended by PostgreSQL $as_me 7.4beta2, which was
 generated by GNU Autoconf 2.53.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17900,7 +18057,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-PostgreSQL config.status 7.4beta1
+PostgreSQL config.status 7.4beta2
 configured by $0, generated by GNU Autoconf 2.53,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -18144,15 +18301,13 @@ s,@perl_privlibexp@,$perl_privlibexp,;t t
 s,@perl_useshrplib@,$perl_useshrplib,;t t
 s,@perl_embed_ldflags@,$perl_embed_ldflags,;t t
 s,@PYTHON@,$PYTHON,;t t
-s,@python_version@,$python_version,;t t
 s,@python_prefix@,$python_prefix,;t t
 s,@python_execprefix@,$python_execprefix,;t t
 s,@python_configdir@,$python_configdir,;t t
-s,@python_moduledir@,$python_moduledir,;t t
-s,@python_moduleexecdir@,$python_moduleexecdir,;t t
 s,@python_includespec@,$python_includespec,;t t
 s,@python_libspec@,$python_libspec,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
+s,@HAVE_IPV6@,$HAVE_IPV6,;t t
 s,@THREAD_CFLAGS@,$THREAD_CFLAGS,;t t
 s,@THREAD_LIBS@,$THREAD_LIBS,;t t
 s,@HAVE_POSIX_SIGNALS@,$HAVE_POSIX_SIGNALS,;t t
index bf2f465a554ff49f4a7314289969fff4d5c90b0c..3f73d4c0391659d5d5495e0a1dccb0e1d123058e 100644 (file)
@@ -21,7 +21,7 @@ dnl The GNU folks apparently haven't heard that some people don't use
 dnl Texinfo. Use this sorcery to use "docdir" instead of "infodir".
 m4_define([info], [doc])
 m4_define([infodir], [docdir])
-AC_INIT([PostgreSQL], [7.4beta1], [[email protected]])
+AC_INIT([PostgreSQL], [7.4beta2], [[email protected]])
 m4_undefine([infodir])
 m4_undefine([info])
 AC_SUBST(docdir)
@@ -238,6 +238,12 @@ if test "$enable_debug" = yes && test "$ac_cv_prog_cc_g" = yes; then
 fi
 AC_MSG_NOTICE([using CFLAGS=$CFLAGS])
 
+# We already have this in Makefile.win32, but configure needs it too
+if test "$PORTNAME" = "win32"
+then
+       CPPFLAGS="$CPPFLAGS -Isrc/include/port/win32"
+fi
+
 # Check if the compiler still works with the template settings
 AC_MSG_CHECKING([whether the C compiler still works])
 AC_TRY_LINK([], [return 0;],
@@ -362,10 +368,10 @@ AC_MSG_RESULT([$with_perl])
 AC_SUBST(with_perl)
 
 #
-# Optionally build Python interface module
+# Optionally build Python modules (PL/Python)
 #
 AC_MSG_CHECKING([whether to build Python modules])
-PGAC_ARG_BOOL(with, python, no, [  --with-python           build Python interface module])
+PGAC_ARG_BOOL(with, python, no, [  --with-python           build Python modules (PL/Python)])
 AC_MSG_RESULT([$with_python])
 AC_SUBST(with_python)
 
@@ -608,7 +614,6 @@ fi
 
 if test "$with_python" = yes; then
   PGAC_PATH_PYTHON
-  PGAC_CHECK_PYTHON_MODULE_SETUP
   PGAC_CHECK_PYTHON_EMBED_SETUP
 fi
 
@@ -833,12 +838,15 @@ AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat setproc
 
 AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
 
+HAVE_IPV6=no
 AC_CHECK_TYPE([struct sockaddr_in6],
               [AC_CHECK_FUNC(inet_ntop,
-                             [AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if you have support for IPv6.])])],
+                             [AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if you have support for IPv6.])
+                                                         HAVE_IPV6=yes])],
               [],
 [$ac_includes_default
 #include <netinet/in.h>])
+AC_SUBST(HAVE_IPV6)
 
 AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS],
 [AC_TRY_LINK(
@@ -978,9 +986,10 @@ AC_FUNC_FSEEKO
 #
 # For each platform, we need to know about any special compile and link
 # libraries, and whether the normal C function names are thread-safe.
+# See the comment at the top of src/port/thread.c for more information.
 #
 if test "$enable_thread_safety" = yes; then
-AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --with-threads])])
+AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --enable-thread-safetys])])
 
 if test "$SUPPORTS_THREADS" != yes; then
 AC_MSG_ERROR([
@@ -988,6 +997,7 @@ Cannot enable threads on your platform.
 Please report your platform threading info to the PostgreSQL mailing lists
 so it can be added to the next release.  Report all compile flags, link flags,
 functions, or libraries required for threading support.
+See the comment at the top of src/port/thread.c for more information.
 ])
 fi
 else
@@ -1014,7 +1024,12 @@ _CFLAGS="$CFLAGS"
 _LIBS="$LIBS"
 CFLAGS="$CFLAGS $THREAD_CFLAGS"
 LIBS="$LIBS $THREAD_LIBS"
-AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r])
+AC_CHECK_FUNC(strerror_r,
+       [], [AC_MSG_ERROR([strerror_r not found, required on this platform for --enable-thread-safety])])
+AC_CHECK_FUNC(getpwuid_r,
+       [], [AC_MSG_ERROR([getpwuid_r not found, required on this platform for --enable-thread-safety])])
+AC_CHECK_FUNC(gethostbyname_r,
+       [], [AC_MSG_ERROR([gethostbyname_r not found, required on this platform for --enable-thread-safety])])
 CFLAGS="$_CFLAGS"
 LIBS="$_LIBS"
 fi
index a93c75900c9bcd0f8d94f6a92ba6a6e074529371..324f09ad6ae15048cd14f6ea20409559700e307c 100644 (file)
@@ -127,7 +127,7 @@ endif
 
 uninstall:
 ifneq (,$(DATA)$(DATA_built))
-       rm -f $(addprefix $(DESTDIR)$(datadir)/contrib/, $(DATA) $(DATA_built))
+       rm -f $(addprefix $(DESTDIR)$(datadir)/contrib/, $(notdir $(DATA) $(DATA_built)))
 endif
 ifdef MODULES
        rm -f $(addprefix $(DESTDIR)$(pkglibdir)/, $(addsuffix $(DLSUFFIX), $(MODULES)))
index f3aa0b8c06b7994f3744b8d2a498a2765a1e4636..469b9c043ffa293e077cce9febdd596fe9b4b253 100644 (file)
@@ -5,7 +5,6 @@ char       *token;
 int                    tokenlen;
 int                    tsearch_yylex(void);
 void           start_parse_str(char *, int);
-void           start_parse_fh(FILE *, int);
 void           end_parse(void);
 
 #endif
index 4323bda7ef003dd269757c38046db07135904986..2bf3dcba076bc13672fcd3d71215607fcb0b2430 100644 (file)
@@ -22,36 +22,6 @@ char *s     = NULL;  /* to return WHOLE hyphenated-word */
 
 YY_BUFFER_STATE buf = NULL; /* buffer to parse; it need for parse from string */
 
-int lrlimit = -1;      /* for limiting read from filehandle ( -1 - unlimited read ) */
-int bytestoread = 0;   /* for limiting read from filehandle */
-
-/* redefine macro for read limited length */
-#define YY_INPUT(buf,result,max_size) \
-       if ( yy_current_buffer->yy_is_interactive ) { \
-                int c = '*', n; \
-                for ( n = 0; n < max_size && \
-                             (c = getc( tsearch_yyin )) != EOF && c != '\n'; ++n ) \
-                        buf[n] = (char) c; \
-                if ( c == '\n' ) \
-                        buf[n++] = (char) c; \
-                if ( c == EOF && ferror( tsearch_yyin ) ) \
-                        YY_FATAL_ERROR( "input in flex scanner failed" ); \
-                result = n; \
-        }  else { \
-               if ( lrlimit == 0 ) \
-                       result=YY_NULL; \
-               else { \
-                       if ( lrlimit>0 ) { \
-                               bytestoread = ( lrlimit > max_size ) ? max_size : lrlimit; \
-                               lrlimit -= bytestoread; \
-                       } else \
-                               bytestoread = max_size; \
-                       if ( ((result = fread( buf, 1, bytestoread, tsearch_yyin )) == 0) \
-                               && ferror( tsearch_yyin ) ) \
-                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
-               } \
-       }
-
 %}
 
 %option 8bit
@@ -327,13 +297,4 @@ void start_parse_str(char* str, int limit) {
        BEGIN INITIAL;
 }
 
-/* start parse from filehandle */
-void start_parse_fh( FILE* fh, int limit ) {
-       if (buf) end_parse();
-       lrlimit = ( limit ) ? limit : -1;
-       buf = tsearch_yy_create_buffer( fh, YY_BUF_SIZE );
-       tsearch_yy_switch_to_buffer( buf );
-       BEGIN INITIAL;
-}
-
 
diff --git a/contrib/tsearch2/Makefile b/contrib/tsearch2/Makefile
new file mode 100644 (file)
index 0000000..dfa0c4e
--- /dev/null
@@ -0,0 +1,47 @@
+# $Header$
+
+subdir = contrib/tsearch2
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+
+MODULE_big = tsearch2
+OBJS = dict_ex.o dict.o snmap.o stopword.o common.o prs_dcfg.o \
+       dict_snowball.o dict_ispell.o dict_syn.o \
+       wparser.o wparser_def.o \
+       ts_cfg.o tsvector.o rewrite.o crc32.o query.o gistidx.o \
+       tsvector_op.o rank.o ts_stat.o
+
+SUBDIRS     := snowball ispell wordparser
+SUBDIROBJS  := $(SUBDIRS:%=%/SUBSYS.o)
+
+OBJS:= $(OBJS) $(SUBDIROBJS)
+
+$(SUBDIROBJS): $(SUBDIRS:%=%-recursive) ;
+
+$(SUBDIRS:%=%-recursive):
+       $(MAKE) -C $(subst -recursive,,$@) SUBSYS.o
+
+PG_CPPFLAGS = -I$(srcdir)/snowball -I$(srcdir)/ispell -I$(srcdir)/wordparser
+
+DATA = stopword/english.stop stopword/russian.stop
+DATA_built = tsearch2.sql untsearch2.sql
+DOCS = README.tsearch2
+REGRESS = tsearch2
+
+SHLIB_LINK := -lm
+
+tsearch2.sql: tsearch.sql.in
+       sed -e 's,MODULE_PATHNAME,$$libdir/$(MODULE_big),g' \
+           -e 's,DATA_PATH,$(datadir)/contrib,g' $< >$@
+
+untsearch2.sql: untsearch.sql.in
+       cp $< $@
+
+.PHONY: subclean
+clean: subclean
+
+subclean:
+       for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean || exit; done
+include $(top_srcdir)/contrib/contrib-global.mk
diff --git a/contrib/tsearch2/docs/tsearch-V2-intro.html b/contrib/tsearch2/docs/tsearch-V2-intro.html
new file mode 100644 (file)
index 0000000..ed2bc41
--- /dev/null
@@ -0,0 +1,1011 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>tsearch-v2-intro</title>
+  
+<link type="text/css" rel="stylesheet" href="tsearch-V2-intro_files/tsearch.txt"></head>
+
+
+<body>
+  <div class="content">
+    <h2>Tsearch2 - Introduction</h2>
+
+    <p><a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/docs/tsearch-V2-intro.html">
+    [Online version]</a> of this document is available.</p>
+
+    <p>The tsearch2 module is available to add as an extension to
+    the PostgreSQL database to allow for Full Text Indexing. This
+    document is an introduction to installing, configuring, using
+    and maintaining the database with the tsearch2 module
+    activated.</p>
+
+    <p>Please, note, tsearch2 module is fully incompatible with old
+    tsearch, which is deprecated in 7.4 and will be obsoleted in
+    7.5.</p>
+
+    <h3>USING TSEARCH2 AND POSTGRESQL FOR A WEB BASED SEARCH
+    ENGINE</h3>
+
+    <p>This documentation is provided as a short guide on how to
+    quickly get up and running with tsearch2 and PostgreSQL, for
+    those who want to implement a full text indexed based search
+    engine. It is not meant to be a complete in-depth guide into
+    the full ins and outs of the contrib/tsearch2 module, and is
+    primarily aimed at beginners who want to speed up searching of
+    large text fields, or those migrating from other database
+    systems such as MS-SQL.</p>
+
+    <p>The README.tsearch2 file included in the contrib/tsearch2
+    directory contains a brief overview and history behind tsearch.
+    This can also be found online <a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/">[right
+    here]</a>.</p>
+
+    <p>Further in depth documentation such as a full function
+    reference, and user guide can be found online at the <a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/docs/">[tsearch
+    documentation home]</a>.</p>
+
+    <h3>ACKNOWLEDGEMENTS</h3>
+
+    <p>Robert John Shepherd originally wrote this documentation for
+    the previous version of tsearch module (v1) included with the
+    postgres release. I took his documentation and updated it to
+    comply with the tsearch2 modifications.</p>
+
+    <p>Robert's original acknowledgements:</p>
+
+    <p>"Thanks to Oleg Bartunov for taking the time to answer many
+    of my questions regarding this module, and also to Teodor
+    Sigaev for clearing up the process of making your own
+    dictionaries. Plus of course a big thanks to the pair of them
+    for writing this module in the first place!"</p>
+
+    <p>I would also like to extend my thanks to the developers, and
+    Oleg Bartunov for all of his direction and help with the new
+    features of tsearch2.</p>
+
+    <h3>OVERVIEW</h3>
+
+    <p>MS-SQL provides a full text indexing (FTI) system which
+    enables the fast searching of text based fields, very useful
+    for websites (and other applications) that require a results
+    set based on key words. PostgreSQL ships with a contributed
+    module called tsearch2, which implements a special type of
+    index that can also be used for full text indexing. Further
+    more, unlike MS' offering which requires regular incremental
+    rebuilds of the text indexes themselves, tsearch2 indexes are
+    always up-to-date and keeping them so induces very little
+    overhead.</p>
+
+    <p>Before we get into the details, it is recommended that you
+    have installed and tested PostgreSQL, are reasonably familiar
+    with databases, the SQL query language and also understand the
+    basics of connecting to PostgreSQL from the local shell. This
+    document isn't intended for the complete PostgreSQL newbie, but
+    anyone with a reasonable grasp of the basics should be able to
+    follow it.</p>
+
+    <h3>INSTALLATION</h3>
+
+    <p>Starting with PostgreSQL version 7.4 tsearch2 is now
+    included in the contrib directory with the PostgreSQL sources.
+    contrib/tsearch2 is where you will find everything needed to
+    install and use tsearch2. Please note that tsearch2 will also
+    work with PostgreSQL version 7.3.x, but it is not the module
+    included with the source distribution. You will have to
+    download the module separately and install it in the same
+    fashion.</p>
+
+    <p>I installed the tsearch2 module to a PostgreSQL 7.3 database
+    from the contrib directory without squashing the original (old)
+    tsearch module. What I did was move the modules tsearch src
+    driectory into the contrib tree under the name tsearchV2.</p>
+
+    <p>Step one is to download the tsearch V2 module :</p>
+
+    <p><a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/">[http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/]</a>
+    (check Development History for latest stable version !)</p>
+    <pre>        tar -zxvf tsearch-v2.tar.gz
+        mv tsearch2 PGSQL_SRC/contrib/
+        cd PGSQL_SRC/contrib/tsearch2
+</pre>
+
+    <p>If you are installing from PostgreSQL version 7.4 or higher,
+    you can skip those steps and just change to the
+    contrib/tsearch2 directory in the source tree and continue from
+    there.</p>
+
+    <p>Then continue with the regular building and installation
+    process</p>
+    <pre>        gmake
+        gmake install
+        gmake installcheck
+</pre>
+
+    <p>That is pretty much all you have to do, unless of course you
+    get errors. However if you get those, you better go check with
+    the mailing lists over at <a href="http://www.postgresql.org/">http://www.postgresql.org</a> or
+    <a href="http://openfts.sourceforge.net/">http://openfts.sourceforge.net/</a>
+    since its never failed for me.</p>
+
+    <p>The directory in the contib/ and the directory from the
+    archive is called tsearch2. Tsearch2 is completely incompatible
+    with the previous version of tsearch. This means that both
+    versions can be installed into a single database, and migration
+    the new version may be much easier.</p>
+
+    <p>NOTE: the previous version of tsearch found in the
+    contrib/tsearch directory is depricated. ALthough it is still
+    available and included within PostgreSQL version 7.4. It will
+    be removed in version 7.5.</p>
+
+    <h3>ADDING TSEARCH2 FUNCTIONALITY TO A DATABASE</h3>
+
+    <p>We should create a database to use as an example for the
+    remainder of this file. We can call the database "ftstest". You
+    can create it from the command line like this:</p>
+    <pre>        #createdb ftstest
+</pre>
+
+    <p>If you thought installation was easy, this next bit is even
+    easier. Change to the PGSQL_SRC/contrib/tsearch2 directory and
+    type:</p>
+    <pre>        psql ftstest &lt; tsearch2.sql
+</pre>
+
+    <p>The file "tsearch2.sql" holds all the wonderful little
+    goodies you need to do full text indexing. It defines numerous
+    functions and operators, and creates the needed tables in the
+    database. There will be 4 new tables created after running the
+    tsearch2.sql file : pg_ts_dict, pg_ts_parser, pg_ts_cfg,
+    pg_ts_cfgmap are added.</p>
+
+    <p>You can check out the tables if you like:</p>
+    <pre>        #psql ftstest
+        ftstest=# \d
+                    List of relations
+         Schema |     Name     | Type  |  Owner
+        --------+--------------+-------+----------
+         public | pg_ts_cfg    | table | kopciuch
+         public | pg_ts_cfgmap | table | kopciuch
+         public | pg_ts_dict   | table | kopciuch
+         public | pg_ts_parser | table | kopciuch
+        (4 rows)
+</pre>
+
+    <h3>TYPES AND FUNCTIONS PROVIDED BY TSEARCH2</h3>
+
+    <p>The first thing we can do is try out some of the types that
+    are provided for us. Lets look at the tsvector type provided
+    for us:</p>
+    <pre>        SELECT 'Our first string used today'::tsvector;
+                        tsvector
+        ---------------------------------------
+         'Our' 'used' 'first' 'today' 'string'
+        (1 row)
+</pre>
+
+    <p>The results are the words used within our string. Notice
+    they are not in any particular order. The tsvector type returns
+    a string of space separated words.</p>
+    <pre>        SELECT 'Our first string used today first string'::tsvector;
+                            tsvector
+        -----------------------------------------------
+         'Our' 'used' 'again' 'first' 'today' 'string'
+        (1 row)
+</pre>
+
+    <p>Notice the results string has each unique word ('first' and
+    'string' only appear once in the tsvector value). Which of
+    course makes sense if you are searching the full text ... you
+    only need to know each unique word in the text.</p>
+
+    <p>Those examples were just casting a text field to that of
+    type tsvector. Lets check out one of the new functions created
+    by the tsearch2 module.</p>
+
+    <p>The function to_tsvector has 3 possible signatures:</p>
+    <pre>        to_tsvector(oid, text);
+        to_tsvector(text, text);
+        to_tsvector(text);
+</pre>
+
+    <p>We will use the second method using two text fields. The
+    overloaded methods provide us with a way to specifiy the way
+    the searchable text is broken up into words (Stemming process).
+    Right now we will specify the 'default' configuration. See the
+    section on TSEARCH2 CONFIGURATION to learn more about this.</p>
+    <pre>        SELECT to_tsvector('default',
+                           'Our first string used today first string');
+                        to_tsvector
+        --------------------------------------------
+         'use':4 'first':2,6 'today':5 'string':3,7
+        (1 row)
+</pre>
+
+    <p>The result returned from this function is of type tsvector.
+    The results came about by this reasoning: All of the words in
+    the text passed in are stemmed, or not used because they are
+    stop words defined in our configuration. Each lower case
+    morphed word is returned with all of the positons in the
+    text.</p>
+
+    <p>In this case the word "Our" is a stop word in the default
+    configuration. That means it will not be included in the
+    result. The word "first" is found at positions 2 and 6
+    (although "Our" is a stop word, it's position is maintained).
+    The word(s) positioning is maintained exactly as in the
+    original string. The word "used" is morphed to the word "use"
+    based on the default configuration for word stemming, and is
+    found at position 4. The rest of the results follow the same
+    logic. Just a reminder again ... the order of the 'word'
+    position in the output is not in any kind of order. (ie 'use':4
+    appears first)</p>
+
+    <p>If you want to view the output of the tsvector fields
+    without their positions, you can do so with the function
+    "strip(tsvector)".</p>
+    <pre>        SELECT strip(to_tsvector('default',
+                     'Our first string used today first string'));
+                    strip
+        --------------------------------
+         'use' 'first' 'today' 'string'
+</pre>
+
+    <p>If you wish to know the number of unique words returned in
+    the tsvector you can do so by using the function
+    "length(tsvector)"</p>
+    <pre>        SELECT length(to_tsvector('default',
+                      'Our first string used today first string'));
+         length
+        --------
+              4
+        (1 row)
+</pre>
+
+    <p>Lets take a look at the function to_tsquery. It also has 3
+    signatures which follow the same rational as the to_tsvector
+    function:</p>
+    <pre>        to_tsquery(oid, text);
+        to_tsquery(text, text);
+        to_tsquery(text);
+</pre>
+
+    <p>Lets try using the function with a single word :</p>
+    <pre>        SELECT to_tsquery('default', 'word');
+         to_tsquery
+        -----------
+         'word'
+         (1 row)
+</pre>
+
+    <p>I call the function the same way I would a to_tsvector
+    function, specifying the 'default' configuration for morphing,
+    and the result is the stemmed output 'word'.</p>
+
+    <p>Lets attempt to use the function with a string of multiple
+    words:</p>
+    <pre>        SELECT to_tsquery('default', 'this is many words');
+        ERROR:  Syntax error
+</pre>
+
+    <p>The function can not accept a space separated string. The
+    intention of the to_tsquery function is to return a type of
+    "tsquery" used for searching a tsvector field. What we need to
+    do is search for one to many words with some kind of logic (for
+    now simple boolean).</p>
+    <pre>        SELECT to_tsquery('default', 'searching|sentence');
+              to_tsquery
+        ----------------------
+         'search' | 'sentenc'
+        (1 row)
+</pre>
+
+    <p>Notice that the words are separated by the boolean logic
+    "OR", the text could contain boolean operators &amp;,|,!,()
+    with their usual meaning.</p>
+
+    <p>You can not use words defined as being a stop word in your
+    configuration. The function will not fail ... you will just get
+    no result, and a NOTICE like this:</p>
+    <pre>        SELECT to_tsquery('default', 'a|is&amp;not|!the');
+        NOTICE:  Query contains only stopword(s)
+                 or doesn't contain lexem(s), ignored
+         to_tsquery
+        -----------
+        (1 row)
+</pre>
+
+    <p>That is a beginning to using the types, and functions
+    defined in the tsearch2 module. There are numerous more
+    functions that I have not touched on. You can read through the
+    tsearch2.sql file built when compiling to get more familiar
+    with what is included.</p>
+
+    <h3>INDEXING FIELDS IN A TABLE</h3>
+
+    <p>The next stage is to add a full text index to an existing
+    table. In this example we already have a table defined as
+    follows:</p>
+    <pre>        CREATE TABLE tblMessages
+        (
+                intIndex        int4,
+                strTopic        varchar(100),
+                strMessage      text
+        );
+</pre>
+
+    <p>We are assuming there are several rows with some kind of
+    data in them. Any data will do, just do several inserts with
+    test strings for a topic, and a message. here is some test data
+    I inserted. (yes I know it's completely useless stuff ;-) but
+    it will serve our purpose right now).</p>
+    <pre>        INSERT INTO tblMessages
+               VALUES ('1', 'Testing Topic', 'Testing message data input');
+        INSERT INTO tblMessages
+               VALUES ('2', 'Movie', 'Breakfast at Tiffany\'s');
+        INSERT INTO tblMessages
+               VALUES ('3', 'Famous Author', 'Stephen King');
+        INSERT INTO tblMessages
+               VALUES ('4', 'Political Topic',
+                            'Nelson Mandella is released from prison');
+        INSERT INTO tblMessages
+               VALUES ('5', 'Nursery rhyme phrase',
+                            'Little jack horner sat in a corner');
+        INSERT INTO tblMessages
+               VALUES ('6', 'Gettysburg address quotation',
+                            'Four score and seven years ago'
+                            ' our fathers brought forth on this'
+                            ' continent a new nation, conceived in'
+                            ' liberty and dedicated to the proposition'
+                            ' that all men are created equal');
+        INSERT INTO tblMessages
+               VALUES ('7', 'Classic Rock Bands',
+                            'Led Zeppelin Grateful Dead and The Sex Pistols');
+        INSERT INTO tblMessages
+               VALUES ('8', 'My birth address',
+                            '18 Sommervile road, Regina, Saskatchewan');
+        INSERT INTO tblMessages
+               VALUES ('9', 'Joke', 'knock knock : who\'s there?'
+                                    ' I will not finish this joke');
+        INSERT INTO tblMessages
+               VALUES ('10', 'Computer information',
+                             'My computer is a pentium III 400 mHz'
+                             ' with 192 megabytes of RAM');
+</pre>
+
+    <p>The next stage is to create a special text index which we
+    will use for FTI, so we can search our table of messages for
+    words or a phrase. We do this using the SQL command:</p>
+    <pre>        ALTER TABLE tblMessages ADD COLUMN idxFTI tsvector;
+</pre>
+
+    <p>Note that unlike traditional indexes, this is actually a new
+    field in the same table, which is then used (through the magic
+    of the tsearch2 operators and functions) by a special index we
+    will create in a moment.</p>
+
+    <p>The general rule for the initial insertion of data will
+    follow four steps:</p>
+    <pre>    1. update table
+    2. vacuum full analyze
+    3. create index
+    4. vacuum full analyze
+</pre>
+
+    <p>The data can be updated into the table, the vacuum full
+    analyze will reclaim unused space. The index can be created on
+    the table after the data has been inserted. Having the index
+    created prior to the update will slow down the process. It can
+    be done in that manner, this way is just more efficient. After
+    the index has been created on the table, vacuum full analyze is
+    run again to update postgres's statistics (ie having the index
+    take effect).</p>
+    <pre>        UPDATE tblMessages SET idxFTI=to_tsvector('default', strMessage);
+        VACUUM FULL ANALYZE;
+</pre>
+
+    <p>Note that this only inserts the field strMessage as a
+    tsvector, so if you want to also add strTopic to the
+    information stored, you should instead do the following, which
+    effectively concatenates the two fields into one before being
+    inserted into the table:</p>
+    <pre>        UPDATE tblMessages
+            SET idxFTI=to_tsvector('default',coalesce(strTopic,'') ||' '|| coalesce(strMessage,''));
+        VACUUM FULL ANALYZE;
+</pre>
+
+    <p><strong>Using the coalesce function makes sure this
+    concatenation also works with NULL fields.</strong></p>
+
+    <p>We need to create the index on the column idxFTI. Keep in
+    mind that the database will update the index when some action
+    is taken. In this case we _need_ the index (The whole point of
+    Full Text INDEXINGi ;-)), so don't worry about any indexing
+    overhead. We will create an index based on the gist function.
+    GiST is an index structure for Generalized Search Tree.</p>
+    <pre>        CREATE INDEX idxFTI_idx ON tblMessages USING gist(idxFTI);
+        VACUUM FULL ANALYZE;
+</pre>
+
+    <p>After you have converted all of your data and indexed the
+    column, you can select some rows to see what actually happened.
+    I will not display output here but you can play around
+    yourselves and see what happened.</p>
+
+    <p>The last thing to do is set up a trigger so every time a row
+    in this table is changed, the text index is automatically
+    updated. This is easily done using:</p>
+    <pre>        CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages
+            FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxFTI, strMessage);
+</pre>
+
+    <p>Or if you are indexing both strMessage and strTopic you
+    should instead do:</p>
+    <pre>        CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages
+            FOR EACH ROW EXECUTE PROCEDURE
+                tsearch2(idxFTI, strTopic, strMessage);
+</pre>
+
+    <p>Before you ask, the tsearch2 function accepts multiple
+    fields as arguments so there is no need to concatenate the two
+    into one like we did before.</p>
+
+    <p>If you want to do something specific with columns, you may
+    write your very own trigger function using plpgsql or other
+    procedural languages (but not SQL, unfortunately) and use it
+    instead of <em>tsearch2</em> trigger.</p>
+
+    <p>You could however call other stored procedures from within
+    the tsearch2 function. Lets say we want to create a function to
+    remove certain characters (like the @ symbol from all
+    text).</p>
+    <pre>       CREATE FUNCTION dropatsymbol(text) 
+                     RETURNS text AS 'select replace($1, \'@\', \' \');' LANGUAGE SQL;
+</pre>
+
+    <p>Now we can use this function within the tsearch2 function on
+    the trigger.</p>
+    <pre>      DROP TRIGGER tsvectorupdate ON tblmessages;
+        CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages
+            FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxFTI, dropatsymbol, strMessage);
+        INSERT INTO tblmessages VALUES (69, 'Attempt for dropatsymbol', '[email protected]');
+</pre>
+
+    <p>If at this point you receive an error stating: ERROR: Can't
+    find tsearch config by locale</p>
+
+    <p>Do not worry. You have done nothing wrong. And tsearch2 is
+    not broken. All that has happened here is that the
+    configuration is setup to use a configuration based on the
+    locale of the server. All you have to do is change your default
+    configuration, or add a new one for your specific locale. See
+    the section on TSEARCH2 CONFIGURATION.</p>
+    <pre class="real">   SELECT * FROM tblmessages WHERE intindex = 69;
+
+         intindex |         strtopic         |  strmessage   |        idxfti
+        ----------+--------------------------+---------------+-----------------------   
+                69 | Attempt for dropatsymbol | [email protected] | 'test':1 'test.com':2
+        (1 row)
+</pre>Notice that the string content was passed throught the stored
+procedure dropatsymbol. The '@' character was replaced with a
+single space ... and the output from the procedure was then stored
+in the tsvector column.
+
+    <p>This could be useful for removing other characters from
+    indexed text, or any kind of preprocessing needed to be done on
+    the text prior to insertion into the index.</p>
+
+    <h3>QUERYING A TABLE</h3>
+
+    <p>There are some examples in the README.tsearch2 file for
+    querying a table. One major difference between tsearch and
+    tsearch2 is the operator ## is no longer available. Only the
+    operator @@ is defined, using the types tsvector on one side
+    and tsquery on the other side.</p>
+
+    <p>Lets search the indexed data for the word "Test". I indexed
+    based on the the concatenation of the strTopic, and the
+    strMessage:</p>
+    <pre>        SELECT intindex, strtopic FROM tblmessages
+                                  WHERE idxfti @@ 'test'::tsquery;
+         intindex |   strtopic
+        ----------+---------------
+                1 | Testing Topic
+        (1 row)
+</pre>
+
+    <p>The only result that matched was the row with a topic
+    "Testing Topic". Notice that the word I search for was all
+    lowercase. Let's see what happens when I query for uppercase
+    "Test".</p>
+    <pre>        SELECT intindex, strtopic FROM tblmessages
+                                  WHERE idxfti @@ 'Test'::tsquery;
+         intindex | strtopic
+        ----------+----------
+        (0 rows)
+</pre>
+
+    <p>We get zero rows returned. The reason is because when the
+    text was inserted, it was morphed to my default configuration
+    (because of the call to to_tsvector in the UPDATE statement).
+    If there was no morphing done, and the tsvector field(s)
+    contained the word 'Text', a match would have been found.</p>
+
+    <p>Most likely the best way to query the field is to use the
+    to_tsquery function on the right hand side of the @@ operator
+    like this:</p>
+    <pre>        SELECT intindex, strtopic FROM tblmessages
+               WHERE idxfti @@ to_tsquery('default', 'Test | Zeppelin');
+         intindex |      strtopic
+        ----------+--------------------
+                1 | Testing Topic
+                7 | Classic Rock Bands
+        (2 rows)
+</pre>
+
+    <p>That query searched for all instances of "Test" OR
+    "Zeppelin". It returned two rows: the "Testing Topic" row, and
+    the "Classic Rock Bands" row. The to_tsquery function performed
+    the correct morphology upon the parameters, and searched the
+    tsvector field appropriately.</p>
+
+    <p>The last example here relates to searching for a phrase, for
+    example "minority report". This poses a problem with regard to
+    tsearch2, as it doesn't index phrases, only words. But there is
+    a way around which doesn't appear to have a significant impact
+    on query time, and that is to use a query such as the
+    following:</p>
+    <pre>        SELECT intindex, strTopic FROM tblmessages
+                WHERE idxfti @@ to_tsquery('default', 'gettysburg &amp; address')
+                AND strMessage ~* '.*men are created equal.*';
+         intindex |           strtopic
+        ----------+------------------------------
+                6 | Gettysburg address quotation
+        (1 row)
+        SELECT intindex, strTopic FROM tblmessages
+                WHERE idxfti @@ to_tsquery('default', 'gettysburg &amp; address')
+                AND strMessage ~* '.*something that does not exist.*';
+         intindex | strtopic
+        ----------+----------
+        (0 rows)
+</pre>
+
+    <p>Of course if your indexing both strTopic and strMessage, and
+    want to search for this phrase on both, then you will have to
+    get out the brackets and extend this query a little more.</p>
+
+    <h3>TSEARCH2 CONFIGURATION</h3>
+
+    <p>Some words such as "and", "the", and "who" are automatically
+    not indexed, since they belong to a pre-existing dictionary of
+    "Stop Words" which tsearch2 does not perform indexing on. If
+    someone needs to search for "The Who" in your database, they
+    are going to have a tough time coming up with any results,
+    since both are ignored in the indexes. But there is a
+    solution.</p>
+
+    <p>Lets say we want to add a word into the stop word list for
+    english stemming. We could edit the file
+    :'/usr/local/pgsql/share/english.stop' and add a word to the
+    list. I edited mine to exclude my name from indexing:</p>
+    <pre>    - Edit /usr/local/pgsql/share/english.stop
+    - Add 'andy' to the list
+    - Save the file.
+</pre>
+
+    <p>When you connect to the database, the dict_init procedure is
+    run during initialization. And in my configuration it will read
+    the stop words from the file I just edited. If you were
+    connected to the DB while editing the stop words, you will need
+    to end the current session and re-connect. When you re-connect
+    to the database, 'andy' is no longer indexed:</p>
+    <pre>        SELECT to_tsvector('default', 'Andy');
+         to_tsvector
+        ------------
+        (1 row)
+</pre>
+
+    <p>Originally I would get the result :</p>
+    <pre>        SELECT to_tsvector('default', 'Andy');
+         to_tsvector
+        ------------
+         'andi':1
+        (1 row)
+</pre>
+
+    <p>But since I added it as a stop word, it would be ingnored on
+    the indexing. The stop word added was used in the dictionary
+    "en_stem". If I were to use a different configuration such as
+    'simple', the results would be different. There are no stop
+    words for the simple dictionary. It will just convert to lower
+    case, and index every unique word.</p>
+    <pre>        SELECT to_tsvector('simple', 'Andy andy The the in out');
+                     to_tsvector
+        -------------------------------------
+         'in':5 'out':6 'the':3,4 'andy':1,2
+        (1 row)
+</pre>
+
+    <p>All this talk about which configuration to use is leading us
+    into the actual configuration of tsearch2. In the examples in
+    this document the configuration has always been specified when
+    using the tsearch2 functions:</p>
+    <pre>        SELECT to_tsvector('default', 'Testing the default config');
+        SELECT to_tsvector('simple', 'Example of simple Config');
+</pre>
+
+    <p>The pg_ts_cfg table holds each configuration you can use
+    with the tsearch2 functions. As you can see the ts_name column
+    contains both the 'default' configurations based on the 'C'
+    locale. And the 'simple' configuration which is not based on
+    any locale.</p>
+    <pre>        SELECT * from pg_ts_cfg;
+             ts_name     | prs_name |    locale
+        -----------------+----------+--------------
+         default         | default  | C
+         default_russian | default  | ru_RU.KOI8-R
+         simple          | default  |
+        (3 rows)
+</pre>
+
+    <p>Each row in the pg_ts_cfg table contains the name of the
+    tsearch2 configuration, the name of the parser to use, and the
+    locale mapped to the configuration. There is only one parser to
+    choose from the table pg_ts_parser called 'default'. More
+    parsers could be written, but for our needs we will use the
+    default.</p>
+
+    <p>There are 3 configurations installed by tsearch2 initially.
+    If your locale is set to 'en_US' for example (like my laptop),
+    then as you can see there is currently no dictionary configured
+    to use with that locale. You can either set up a new
+    configuration or just use one that already exists. If I do not
+    specify which configuration to use in the to_tsvector function,
+    I receive the following error.</p>
+    <pre>        SELECT to_tsvector('learning tsearch is like going to school');
+        ERROR:  Can't find tsearch config by locale
+</pre>
+
+    <p>We will create a new configuration for use with the server
+    encoding 'en_US'. The first step is to add a new configuration
+    into the pg_ts_cfg table. We will call the configuration
+    'default_english', with the default parser and use the locale
+    'en_US'.</p>
+    <pre>        INSERT INTO pg_ts_cfg (ts_name, prs_name, locale)
+               VALUES ('default_english', 'default', 'en_US');
+</pre>
+
+    <p>We have only declared that there is a configuration called
+    'default_english'. We need to set the configuration of how
+    'default_english' will work. The next step is creating a new
+    dictionary to use. The configuration of the dictionary is
+    completlely different in tsearch2. In the prior versions to
+    make changes, you would have to re-compile your changes into
+    the tsearch.so. All of the configuration has now been moved
+    into the system tables created by executing the SQL code from
+    tsearch2.sql</p>
+
+    <p>Lets take a first look at the pg_ts_dict table</p>
+    <pre>        ftstest=# \d pg_ts_dict
+                Table "public.pg_ts_dict"
+         Column      |  Type   | Modifiers
+        -----------------+---------+-----------
+         dict_name       | text    | not null
+         dict_init       | oid     |
+         dict_initoption | text    |
+         dict_lexize     | oid     | not null
+         dict_comment    | text    |
+        Indexes: pg_ts_dict_idx unique btree (dict_name)
+</pre>
+
+    <p>The dict_name column is the name of the dictionary, for
+    example 'simple', 'en_stem' or 'ru_stem'. The dict_init column
+    is an OID of a stored procedure to run for initialization of
+    that dictionary, for example 'snb_en_init' or 'snb_ru_init'.
+    The dict_init option is used for options passed to the init
+    function for the stored procedure. In the cases of 'en_stem' or
+    'ru_stem' it is a path to a stopword file for that dictionary,
+    for example '/usr/local/pgsql/share/english.stop'. This is
+    however dictated by the dictionary. ISpell dictionaries may
+    require different options. The dict_lemmatize column is another
+    OID of a stored procedure to the function used to lemmitize,
+    for example 'snb_lemmatize'. The dict_comment column is just a
+    comment.</p>
+
+    <p>Next we will configure the use of a new dictionary based on
+    ISpell. We will assume you have ISpell installed on you
+    machine. (in /usr/local/lib)</p>
+
+    <p>There has been some confusion in the past as to which files
+    are used from ISpell. ISpell operates using a hash file. This
+    is a binary file created by the ISpell command line utility
+    "buildhash". This utility accepts a file containing the words
+    from the dictionary, and the affixes file and the output is the
+    hash file. The default installation of ISPell installs the
+    english hash file english.hash, which is the exact same file as
+    american.hash. ISpell uses this as the fallback dictionary to
+    use.</p>
+
+    <p>This hash file is not what tsearch2 requires as the ISpell
+    interface. The file(s) needed are those used to create the
+    hash. Tsearch uses the dictionary words for morphology, so the
+    listing is needed not spellchecking. Regardless, these files
+    are included in the ISpell sources, and you can use them to
+    integrate into tsearch2. This is not complicated, but is not
+    very obvious to begin with. The tsearch2 ISpell interface needs
+    only the listing of dictionary words, it will parse and load
+    those words, and use the ISpell dictionary for lexem
+    processing.</p>
+
+    <p>I found the ISPell make system to be very finicky. Their
+    documentation actually states this to be the case. So I just
+    did things the command line way. In the ISpell source tree
+    under langauges/english there are several files in this
+    directory. For a complete description, please read the ISpell
+    README. Basically for the english dictionary there is the
+    option to create the small, medium, large and extra large
+    dictionaries. The medium dictionary is recommended. If the make
+    system is configured correctly, it would build and install the
+    english.has file from the medium size dictionary. Since we are
+    only concerned with the dictionary word listing ... it can be
+    created from the /languages/english directory with the
+    following command:</p>
+    <pre>   sort -u -t/ +0f -1 +0 -T /usr/tmp -o english.med english.0 english.1
+</pre>
+
+    <p>This will create a file called english.med. You can copy
+    this file to whever you like. I place mine in /usr/local/lib so
+    it coincides with the ISpell hash files. You can now add the
+    tsearch2 configuration entry for the ISpell english dictionary.
+    We will also continue to use the english word stop file that
+    was installed for the en_stem dictionary. You could use a
+    different one if you like. The ISpell configuration is based on
+    the "ispell_template" dictionary installed by default with
+    tsearch2. We will use the OIDs to the stored procedures from
+    the row where the dict_name = 'ispell_template'.</p>
+    <pre>        INSERT INTO pg_ts_dict
+               (SELECT 'en_ispell',
+                       dict_init,
+                       'DictFile="/usr/local/lib/english.med",'
+                       'AffFile="/usr/local/lib/english.aff",'
+                       'StopFile="/usr/local/pgsql/share/english.stop"',
+                       dict_lexize
+                FROM pg_ts_dict
+                WHERE dict_name = 'ispell_template');
+</pre>
+
+    <p>Now that we have a dictionary we can specify it's use in a
+    query to get a lexem. For this we will use the lexize function.
+    The lexize function takes the name of the dictionary to use as
+    an argument. Just as the other tsearch2 functions operate.</p>
+    <pre>   SELECT lexize('en_ispell', 'program');
+          lexize
+        -----------
+         {program}
+        (1 row)
+</pre>
+
+    <p>If you wanted to always use the ISpell english dictionary
+    you have installed, you can configure tsearch2 to always use a
+    specific dictionary.</p>
+    <pre>  SELCECT set_curdict('en_ispell');
+</pre>
+
+    <p>Lexize is meant to turn a word into a lexem. It is possible
+    to receive more than one lexem returned for a single word.</p>
+    <pre> SELECT lexize('en_ispell', 'conditionally');
+           lexize
+        -----------------------------
+         {conditionally,conditional}
+        (1 row)
+</pre>
+
+    <p>The lexize function is not meant to take a full string as an
+    argument to return lexems for. If you passed in an entire
+    sentence, it attempts to find that entire sentence in the
+    dictionary. SInce the dictionary contains only words, you will
+    receive an empty result set back.</p>
+    <pre>      SELECT lexize('en_ispell', 'This is a senctece to lexize');
+         lexize
+        --------
+        
+        (1 row)
+        
+If you parse a lexem from a word not in the dictionary, then you will receive an empty result. This makes sense because the word "tsearch" is not int the english dictionary. You can create your own additions to the dictionary if you like. This may be useful for scientific or technical glossaries that need to be indexed. SELECT lexize('en_ispell', 'tsearch'); lexize -------- (1 row)
+</pre>
+
+    <p>This is not to say that tsearch will be ignored when adding
+    text information to the the tsvector index column. This will be
+    explained in greater detail with the table pg_ts_cfgmap.</p>
+
+    <p>Next we need to set up the configuration for mapping the
+    dictionay use to the lexxem parsings. This will be done by
+    altering the pg_ts_cfgmap table. We will insert several rows,
+    specifying to using the new dictionary we installed and
+    configured for use within tsearch2. There are several type of
+    lexims we would be concerned with forcing the use of the ISpell
+    dictionary.</p>
+    <pre>        INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
+               VALUES ('default_english', 'lhword', '{en_ispell,en_stem}');
+        INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
+               VALUES ('default_english', 'lpart_hword', '{en_ispell,en_stem}');
+        INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
+               VALUES ('default_english', 'lword', '{en_ispell,en_stem}');
+</pre>
+
+    <p>We have just inserted 3 records to the configuration
+    mapping, specifying that the lexem types for "lhword,
+    lpart_hword and lword" are to be stemmed using the 'en_ispell'
+    dictionary we added into pg_ts_dict, when using the
+    configuration ' default_english' which we added to
+    pg_ts_cfg.</p>
+
+    <p>There are several other lexem types used that we do not need
+    to specify as using the ISpell dictionary. We can simply insert
+    values using the 'simple' stemming process dictionary.</p>
+    <pre>        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'url', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'host', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'sfloat', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'uri', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'int', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'float', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'email', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'word', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'hword', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'nlword', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'nlpart_hword', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'part_hword', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'nlhword', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'file', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'uint', '{simple}');
+        INSERT INTO pg_ts_cfgmap
+               VALUES ('default_english', 'version', '{simple}');
+</pre>
+
+    <p>Our addition of a configuration for 'default_english' is now
+    complete. We have successfully created a new tsearch2
+    configuration. At the same time we have also set the new
+    configuration to be our default for en_US locale.</p>
+    <pre>        SELECT to_tsvector('default_english',
+                           'learning tsearch is like going to school');
+                           to_tsvector
+        --------------------------------------------------
+         'go':5 'like':4 'learn':1 'school':7 'tsearch':2
+        SELECT to_tsvector('learning tsearch is like going to school');
+                            to_tsvector
+        --------------------------------------------------
+         'go':5 'like':4 'learn':1 'school':7 'tsearch':2
+        (1 row)
+</pre>
+
+    <p>Notice here that words like "tsearch" are still parsed and
+    indexed in the tsvector column. There is a lexem returned for
+    the word becuase in the configuration mapping table, we specify
+    words to be used from the 'en_ispell' dictionary first, but as
+    a fallback to use the 'en_stem' dictionary. Therefore a lexem
+    is not returned from en_ispell, but is returned from en_stem,
+    and added to the tsvector.</p>
+    <pre> SELECT to_tsvector('learning tsearch is like going to computer school');
+                                to_tsvector
+        ---------------------------------------------------------------------------
+         'go':5 'like':4 'learn':1 'school':8 'compute':7 'tsearch':2 'computer':7
+        (1 row)
+</pre>
+
+    <p>Notice in this last example I added the word "computer" to
+    the text to be converted into a tsvector. Because we have setup
+    our default configuration to use the ISpell english dictionary,
+    the words are lexized, and computer returns 2 lexems at the
+    same position. 'compute':7 and 'computer':7 are now both
+    indexed for the word computer.</p>
+
+    <p>You can create additional dictionarynlists, or use the extra
+    large dictionary from ISpell. You can read through the ISpell
+    documents, and source tree to make modifications as you see
+    fit.</p>
+
+    <p>In the case that you already have a configuration set for
+    the locale, and you are changing it to your new dictionary
+    configuration. You will have to set the old locale to NULL. If
+    we are using the 'C' locale then we would do this:</p>
+    <pre>        UPDATE pg_ts_cfg SET locale=NULL WHERE locale = 'C';
+</pre>
+
+    <p>That about wraps up the configuration of tsearch2. There is
+    much more you can do with the tables provided. This was just an
+    introduction to get things working rather quickly.</p>
+
+    <h3>ADDING NEW DICTIONARIES TO TSEARCH2</h3>
+
+    <p>To aid in the addition of new dictionaries to the tsearch2
+    module you can use another additional module in combination
+    with tsearch2. The gendict module is included into tsearch2
+    distribution and is available from gendict/ subdirectory.</p>
+
+    <p>I will not go into detail about installation and
+    instructions on how to use gendict to it's fullest extent right
+    now. You can read the README.gendict ... it has all of the
+    instructions and information you will need.</p>
+
+    <h3>BACKING UP AND RESTORING DATABASES THAT FEATURE
+    TSEARCH2</h3>
+
+    <p>Believe it or not, this isn't as straight forward as it
+    should be, and you will have problems trying to backup and
+    restore any database which uses tsearch2 unless you take the
+    steps shown below. And before you ask using pg_dumpall will
+    result in failure every time. These took a lot of trial and
+    error to get working, but the process as laid down below has
+    been used a dozen times now in live production environments so
+    it should work fine.</p>
+
+    <p>HOWEVER never rely on anyone elses instructions to backup
+    and restore a database system, always develop and understand
+    your own methodology, and test it numerous times before you
+    need to do it for real.</p>
+
+    <p>To Backup a PostgreSQL database that uses the tsearch2
+    module:</p>
+
+    <p>1) Backup any global database objects such as users and
+    groups (this step is usually only necessary when you will be
+    restoring to a virgin system)</p>
+    <pre>        pg_dumpall -g &gt; GLOBALobjects.sql
+</pre>
+
+    <p>2) Backup the full database schema using pg_dump</p>
+    <pre>        pg_dump -s DATABASE &gt; DATABASEschema.sql
+</pre>
+
+    <p>3) Backup the full database using pg_dump</p>
+    <pre>        pg_dump -Fc DATABASE &gt; DATABASEdata.tar
+</pre>
+
+    <p>To Restore a PostgreSQL database that uses the tsearch2
+    module:</p>
+
+    <p>1) Create the blank database</p>
+    <pre>        createdb DATABASE
+</pre>
+
+    <p>2) Restore any global database objects such as users and
+    groups (this step is usually only necessary when you will be
+    restoring to a virgin system)</p>
+    <pre>        psql DATABASE &lt; GLOBALobjects.sql
+</pre>
+
+    <p>3) Create the tsearch2 objects, functions and operators</p>
+    <pre>        psql DATABASE &lt; tsearch2.sql
+</pre>
+
+    <p>4) Edit the backed up database schema and delete all SQL
+    commands which create tsearch2 related functions, operators and
+    data types, BUT NOT fields in table definitions that specify
+    tsvector types. If your not sure what these are, they are the
+    ones listed in tsearch2.sql. Then restore the edited schema to
+    the database</p>
+    <pre>        psql DATABASE &lt; DATABASEschema.sql
+</pre>
+
+    <p>5) Restore the data for the database</p>
+    <pre>        pg_restore -N -a -d DATABASE DATABASEdata.tar
+</pre>
+
+    <p>If you get any errors in step 4, it will most likely be
+    because you forgot to remove an object that was created in
+    tsearch2.sql. Any errors in step 5 will mean the database
+    schema was probably restored wrongly.</p>
+  </div>
+</body></html>
\ No newline at end of file
diff --git a/contrib/tsearch2/expected/tsearch2.out b/contrib/tsearch2/expected/tsearch2.out
new file mode 100644 (file)
index 0000000..8571e59
--- /dev/null
@@ -0,0 +1,2093 @@
+--
+-- first, define the datatype.  Turn off echoing so that expected file
+-- does not depend on contents of seg.sql.
+--
+\set ECHO none
+psql:tsearch2.sql:13: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pg_ts_dict_pkey" for table "pg_ts_dict"
+psql:tsearch2.sql:145: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pg_ts_parser_pkey" for table "pg_ts_parser"
+psql:tsearch2.sql:244: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pg_ts_cfg_pkey" for table "pg_ts_cfg"
+psql:tsearch2.sql:251: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pg_ts_cfgmap_pkey" for table "pg_ts_cfgmap"
+psql:tsearch2.sql:339: NOTICE:  type "tsvector" is not yet defined
+DETAIL:  Creating a shell type definition.
+psql:tsearch2.sql:344: NOTICE:  argument type tsvector is only a shell
+psql:tsearch2.sql:398: NOTICE:  type "tsquery" is not yet defined
+DETAIL:  Creating a shell type definition.
+psql:tsearch2.sql:403: NOTICE:  argument type tsquery is only a shell
+psql:tsearch2.sql:545: NOTICE:  type "gtsvector" is not yet defined
+DETAIL:  Creating a shell type definition.
+psql:tsearch2.sql:550: NOTICE:  argument type gtsvector is only a shell
+--tsvector
+SELECT '1'::tsvector;
+ tsvector 
+----------
+ '1'
+(1 row)
+
+SELECT '1 '::tsvector;
+ tsvector 
+----------
+ '1'
+(1 row)
+
+SELECT ' 1'::tsvector;
+ tsvector 
+----------
+ '1'
+(1 row)
+
+SELECT ' 1 '::tsvector;
+ tsvector 
+----------
+ '1'
+(1 row)
+
+SELECT '1 2'::tsvector;
+ tsvector 
+----------
+ '1' '2'
+(1 row)
+
+SELECT '\'1 2\''::tsvector;
+ tsvector 
+----------
+ '1 2'
+(1 row)
+
+SELECT '\'1 \\\'2\''::tsvector;
+ tsvector 
+----------
+ '1 \'2'
+(1 row)
+
+SELECT '\'1 \\\'2\'3'::tsvector;
+  tsvector   
+-------------
+ '3' '1 \'2'
+(1 row)
+
+SELECT '\'1 \\\'2\' 3'::tsvector;
+  tsvector   
+-------------
+ '3' '1 \'2'
+(1 row)
+
+SELECT '\'1 \\\'2\' \' 3\' 4 '::tsvector;
+     tsvector     
+------------------
+ '4' ' 3' '1 \'2'
+(1 row)
+
+select '\'w\':4A,3B,2C,1D,5 a:8';
+       ?column?        
+-----------------------
+ 'w':4A,3B,2C,1D,5 a:8
+(1 row)
+
+select 'a:3A b:2a'::tsvector || 'ba:1234 a:1B';
+          ?column?          
+----------------------------
+ 'a':3A,4B 'b':2A 'ba':1237
+(1 row)
+
+select setweight('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd zxc:81,567,222A'::tsvector, 'c');
+                        setweight                         
+----------------------------------------------------------
+ 'a':1C,3C 'w':5C,6C,12C,13C 'asd':1C 'zxc':81C,222C,567C
+(1 row)
+
+select strip('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd'::tsvector);
+     strip     
+---------------
+ 'a' 'w' 'asd'
+(1 row)
+
+--tsquery
+SELECT '1'::tsquery;
+ tsquery 
+---------
+ '1'
+(1 row)
+
+SELECT '1 '::tsquery;
+ tsquery 
+---------
+ '1'
+(1 row)
+
+SELECT ' 1'::tsquery;
+ tsquery 
+---------
+ '1'
+(1 row)
+
+SELECT ' 1 '::tsquery;
+ tsquery 
+---------
+ '1'
+(1 row)
+
+SELECT '\'1 2\''::tsquery;
+ tsquery 
+---------
+ '1 2'
+(1 row)
+
+SELECT '\'1 \\\'2\''::tsquery;
+ tsquery 
+---------
+ '1 \'2'
+(1 row)
+
+SELECT '!1'::tsquery;
+ tsquery 
+---------
+ !'1'
+(1 row)
+
+SELECT '1|2'::tsquery;
+  tsquery  
+-----------
+ '1' | '2'
+(1 row)
+
+SELECT '1|!2'::tsquery;
+  tsquery   
+------------
+ '1' | !'2'
+(1 row)
+
+SELECT '!1|2'::tsquery;
+  tsquery   
+------------
+ !'1' | '2'
+(1 row)
+
+SELECT '!1|!2'::tsquery;
+   tsquery   
+-------------
+ !'1' | !'2'
+(1 row)
+
+SELECT '!(!1|!2)'::tsquery;
+     tsquery      
+------------------
+ !( !'1' | !'2' )
+(1 row)
+
+SELECT '!(!1|2)'::tsquery;
+     tsquery     
+-----------------
+ !( !'1' | '2' )
+(1 row)
+
+SELECT '!(1|!2)'::tsquery;
+     tsquery     
+-----------------
+ !( '1' | !'2' )
+(1 row)
+
+SELECT '!(1|2)'::tsquery;
+    tsquery     
+----------------
+ !( '1' | '2' )
+(1 row)
+
+SELECT '1&2'::tsquery;
+  tsquery  
+-----------
+ '1' & '2'
+(1 row)
+
+SELECT '!1&2'::tsquery;
+  tsquery   
+------------
+ !'1' & '2'
+(1 row)
+
+SELECT '1&!2'::tsquery;
+  tsquery   
+------------
+ '1' & !'2'
+(1 row)
+
+SELECT '!1&!2'::tsquery;
+   tsquery   
+-------------
+ !'1' & !'2'
+(1 row)
+
+SELECT '(1&2)'::tsquery;
+  tsquery  
+-----------
+ '1' & '2'
+(1 row)
+
+SELECT '1&(2)'::tsquery;
+  tsquery  
+-----------
+ '1' & '2'
+(1 row)
+
+SELECT '!(1)&2'::tsquery;
+  tsquery   
+------------
+ !'1' & '2'
+(1 row)
+
+SELECT '!(1&2)'::tsquery;
+    tsquery     
+----------------
+ !( '1' & '2' )
+(1 row)
+
+SELECT '1|2&3'::tsquery;
+     tsquery     
+-----------------
+ '1' | '2' & '3'
+(1 row)
+
+SELECT '1|(2&3)'::tsquery;
+     tsquery     
+-----------------
+ '1' | '2' & '3'
+(1 row)
+
+SELECT '(1|2)&3'::tsquery;
+       tsquery       
+---------------------
+ ( '1' | '2' ) & '3'
+(1 row)
+
+SELECT '1|2&!3'::tsquery;
+     tsquery      
+------------------
+ '1' | '2' & !'3'
+(1 row)
+
+SELECT '1|!2&3'::tsquery;
+     tsquery      
+------------------
+ '1' | !'2' & '3'
+(1 row)
+
+SELECT '!1|2&3'::tsquery;
+     tsquery      
+------------------
+ !'1' | '2' & '3'
+(1 row)
+
+SELECT '!1|(2&3)'::tsquery;
+     tsquery      
+------------------
+ !'1' | '2' & '3'
+(1 row)
+
+SELECT '!(1|2)&3'::tsquery;
+       tsquery        
+----------------------
+ !( '1' | '2' ) & '3'
+(1 row)
+
+SELECT '(!1|2)&3'::tsquery;
+       tsquery        
+----------------------
+ ( !'1' | '2' ) & '3'
+(1 row)
+
+SELECT '1|(2|(4|(5|6)))'::tsquery;
+                 tsquery                 
+-----------------------------------------
+ '1' | ( '2' | ( '4' | ( '5' | '6' ) ) )
+(1 row)
+
+SELECT '1|2|4|5|6'::tsquery;
+                 tsquery                 
+-----------------------------------------
+ ( ( ( '1' | '2' ) | '4' ) | '5' ) | '6'
+(1 row)
+
+SELECT '1&(2&(4&(5&6)))'::tsquery;
+           tsquery           
+-----------------------------
+ '1' & '2' & '4' & '5' & '6'
+(1 row)
+
+SELECT '1&2&4&5&6'::tsquery;
+           tsquery           
+-----------------------------
+ '1' & '2' & '4' & '5' & '6'
+(1 row)
+
+SELECT '1&(2&(4&(5|6)))'::tsquery;
+             tsquery             
+---------------------------------
+ '1' & '2' & '4' & ( '5' | '6' )
+(1 row)
+
+SELECT '1&(2&(4&(5|!6)))'::tsquery;
+             tsquery              
+----------------------------------
+ '1' & '2' & '4' & ( '5' | !'6' )
+(1 row)
+
+SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::tsquery;
+                 tsquery                  
+------------------------------------------
+ '1' & '2' & ' 4' & ( '|5' | '6 \' !|&' )
+(1 row)
+
+SELECT '\'the wether\':dc & \' sKies \':BC & a:d b:a';
+                 ?column?                 
+------------------------------------------
+ 'the wether':dc & ' sKies ':BC & a:d b:a
+(1 row)
+
+select lexize('simple', 'ASD56 hsdkf');
+     lexize      
+-----------------
+ {"asd56 hsdkf"}
+(1 row)
+
+select lexize('en_stem', 'SKIES Problems identity');
+          lexize          
+--------------------------
+ {"skies problems ident"}
+(1 row)
+
+select * from token_type('default');
+ tokid |    alias     |               descr               
+-------+--------------+-----------------------------------
+     1 | lword        | Latin word
+     2 | nlword       | Non-latin word
+     3 | word         | Word
+     4 | email        | Email
+     5 | url          | URL
+     6 | host         | Host
+     7 | sfloat       | Scientific notation
+     8 | version      | VERSION
+     9 | part_hword   | Part of hyphenated word
+    10 | nlpart_hword | Non-latin part of hyphenated word
+    11 | lpart_hword  | Latin part of hyphenated word
+    12 | blank        | Space symbols
+    13 | tag          | HTML Tag
+    14 | http         | HTTP head
+    15 | hword        | Hyphenated word
+    16 | lhword       | Latin hyphenated word
+    17 | nlhword      | Non-latin hyphenated word
+    18 | uri          | URI
+    19 | file         | File or path name
+    20 | float        | Decimal notation
+    21 | int          | Signed integer
+    22 | uint         | Unsigned integer
+    23 | entity       | HTML Entity
+(23 rows)
+
+select * from parse('default', '345 [email protected] \' 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 [email protected] 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');
+ tokid |                token                 
+-------+--------------------------------------
+    22 | 345
+    12 |  
+     4 | [email protected]
+    12 |  
+    12 | '
+    12 |  
+    14 | http://
+     6 | www.com
+    12 | /
+    12 |  
+    14 | http://
+     5 | aew.werc.ewr/?ad=qwe&dw
+     6 | aew.werc.ewr
+    18 | /?ad=qwe&dw
+    12 |  
+     5 | 1aew.werc.ewr/?ad=qwe&dw
+     6 | 1aew.werc.ewr
+    18 | /?ad=qwe&dw
+    12 |  
+     6 | 2aew.werc.ewr
+    12 |  
+    14 | http://
+     5 | 3aew.werc.ewr/?ad=qwe&dw
+     6 | 3aew.werc.ewr
+    18 | /?ad=qwe&dw
+    12 |  
+    14 | http://
+     6 | 4aew.werc.ewr
+    12 |  
+    14 | http://
+     5 | 5aew.werc.ewr:8100/?
+     6 | 5aew.werc.ewr
+    18 | :8100/?
+    12 |   
+     1 | ad
+    12 | =
+     1 | qwe
+    12 | &
+     1 | dw
+    12 |  
+     5 | 6aew.werc.ewr:8100/?ad=qwe&dw
+     6 | 6aew.werc.ewr
+    18 | :8100/?ad=qwe&dw
+    12 |  
+     5 | 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32
+     6 | 7aew.werc.ewr
+    18 | :8100/?ad=qwe&dw=%20%32
+    12 |  
+     7 | +4.0e-10
+    12 |  
+     1 | qwe
+    12 |  
+     1 | qwe
+    12 |  
+     1 | qwqwe
+    12 |  
+    20 | 234.435
+    12 |  
+    22 | 455
+    12 |  
+    20 | 5.005
+    12 |  
+     4 | [email protected]
+    12 |  
+    16 | qwe-wer
+    11 | qwe
+    12 | -
+    11 | wer
+    12 |  
+     1 | asdf
+    12 |  
+    13 |  
+     1 | qwer
+    12 |  
+     1 | jf
+    12 |  
+     1 | sdjk
+    13 |  
+    12 |  
+     3 | ewr1
+    12 | >
+    12 |  
+     3 | ewri2
+    12 |  
+    13 |  
+    12 | 
+
+    19 | /usr/local/fff
+    12 |  
+    19 | /awdf/dwqe/4325
+    12 |  
+    19 | rewt/ewr
+    12 |  
+     1 | wefjn
+    12 |  
+    19 | /wqe-324/ewr
+    12 |  
+     6 | gist.h
+    12 |  
+     6 | gist.h.c
+    12 |  
+     6 | gist.c
+    12 | .
+    12 |  
+     1 | readline
+    12 |  
+    20 | 4.2
+    12 |  
+    20 | 4.2
+    12 | .
+    12 |  
+    20 | 4.2
+    12 | ,
+    12 |  
+    15 | readline-4
+    11 | readline
+    12 | -
+    20 | 4.2
+    12 |  
+    15 | readline-4
+    11 | readline
+    12 | -
+    20 | 4.2
+    12 | .
+    12 |  
+    22 | 234
+    12 |  
+
+    13 |  
+    12 |  
+     1 | wow
+    12 |   
+    12 | <
+    12 |  
+     1 | jqw
+    12 |  
+    12 | <
+    12 | >
+    12 |  
+     1 | qwerty
+(138 rows)
+
+SELECT to_tsvector('default', '345 [email protected] \' 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 [email protected] 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');
+                                                                                                                                                                                                                                                                                                                                                                                                                                               to_tsvector                                                                                                                                                                                                                                                                                                                                                                                                                                                
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 'ad':18 'dw':20 'jf':40 '234':62 '345':1 '4.2':53,54,55,58,61 '455':32 'jqw':64 'qwe':19,28,29,36 'wer':37 'wow':63 'asdf':38 'ewr1':42 'qwer':39 'sdjk':41 '5.005':33 'ewri2':43 'qwqwe':30 'wefjn':47 'gist.c':51 'gist.h':49 'qwerti':65 '234.435':31 ':8100/?':17 'qwe-wer':35 'readlin':52,57,60 'www.com':3 '+4.0e-10':27 'gist.h.c':50 'rewt/ewr':46 '[email protected]':2 'readline-4':56,59 '/?ad=qwe&dw':6,9,13 '/wqe-324/ewr':48 'aew.werc.ewr':5 '1aew.werc.ewr':8 '2aew.werc.ewr':10 '3aew.werc.ewr':12 '4aew.werc.ewr':14 '5aew.werc.ewr':16 '6aew.werc.ewr':22 '7aew.werc.ewr':25 '/usr/local/fff':44 '/awdf/dwqe/4325':45 ':8100/?ad=qwe&dw':23 '[email protected]':34 '5aew.werc.ewr:8100/?':15 ':8100/?ad=qwe&dw=%20%32':26 'aew.werc.ewr/?ad=qwe&dw':4 '1aew.werc.ewr/?ad=qwe&dw':7 '3aew.werc.ewr/?ad=qwe&dw':11 '6aew.werc.ewr:8100/?ad=qwe&dw':21 '7aew.werc.ewr:8100/?ad=qwe&dw=%20%32':24
+(1 row)
+
+SELECT length(to_tsvector('default', '345 qw'));
+ length 
+--------
+      2
+(1 row)
+
+SELECT length(to_tsvector('default', '345 [email protected] \' 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 [email protected] 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'));
+ length 
+--------
+     53
+(1 row)
+
+select to_tsquery('default', 'qwe & sKies '); 
+  to_tsquery   
+---------------
+ 'qwe' & 'sky'
+(1 row)
+
+select to_tsquery('simple', 'qwe & sKies '); 
+   to_tsquery    
+-----------------
+ 'qwe' & 'skies'
+(1 row)
+
+select to_tsquery('default', '\'the wether\':dc & \'           sKies \':BC ');
+       to_tsquery       
+------------------------
+ 'wether':CD & 'sky':BC
+(1 row)
+
+select to_tsquery('asd&(and|fghj)');
+   to_tsquery   
+----------------
+ 'asd' & 'fghj'
+(1 row)
+
+select to_tsquery('(asd&and)|fghj');
+   to_tsquery   
+----------------
+ 'asd' | 'fghj'
+(1 row)
+
+select to_tsquery('(asd&!and)|fghj');
+   to_tsquery   
+----------------
+ 'asd' | 'fghj'
+(1 row)
+
+select to_tsquery('(the|and&(i&1))&fghj');
+  to_tsquery  
+--------------
+ '1' & 'fghj'
+(1 row)
+
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca';
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:B';
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:A';
+ ?column? 
+----------
+ t
+(1 row)
+
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:C';
+ ?column? 
+----------
+ f
+(1 row)
+
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:CB';
+ ?column? 
+----------
+ t
+(1 row)
+
+CREATE TABLE test_tsvector( t text, a tsvector );
+\copy test_tsvector from 'data/test_tsearch.data'
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
+ count 
+-------
+   158
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr&qh';
+ count 
+-------
+    17
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq&yt';
+ count 
+-------
+     6
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq|yt';
+ count 
+-------
+    98
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq&yt)|(wr&qh)';
+ count 
+-------
+    23
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq|yt)&(wr|qh)';
+ count 
+-------
+    39
+(1 row)
+
+create index wowidx on test_tsvector using gist (a);
+set enable_seqscan=off;
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
+ count 
+-------
+   158
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr&qh';
+ count 
+-------
+    17
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq&yt';
+ count 
+-------
+     6
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq|yt';
+ count 
+-------
+    98
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq&yt)|(wr&qh)';
+ count 
+-------
+    23
+(1 row)
+
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq|yt)&(wr|qh)';
+ count 
+-------
+    39
+(1 row)
+
+select set_curcfg('default');
+ set_curcfg 
+------------
+(1 row)
+
+CREATE TRIGGER tsvectorupdate
+BEFORE UPDATE OR INSERT ON test_tsvector
+FOR EACH ROW EXECUTE PROCEDURE tsearch2(a, t);
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+ count 
+-------
+     0
+(1 row)
+
+INSERT INTO test_tsvector (t) VALUES ('345 qwerty');
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+ count 
+-------
+     1
+(1 row)
+
+UPDATE test_tsvector SET t = null WHERE t = '345 qwerty';
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+ count 
+-------
+     0
+(1 row)
+
+drop trigger tsvectorupdate on test_tsvector;
+create function wow(text) returns text as 'select $1 || \' copyright\'; ' language sql;
+create trigger tsvectorupdate before update or insert on test_tsvector
+for each row execute procedure tsearch2(a, wow, t);
+insert into test_tsvector (t) values ('345 qwerty');
+select count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+ count 
+-------
+     1
+(1 row)
+
+select count(*) FROM test_tsvector WHERE a @@ to_tsquery('copyright');
+ count 
+-------
+     1
+(1 row)
+
+select rank(' a:1 s:2C d g'::tsvector, 'a | s');
+ rank 
+------
+ 0.28
+(1 row)
+
+select rank(' a:1 s:2B d g'::tsvector, 'a | s');
+ rank 
+------
+ 0.46
+(1 row)
+
+select rank(' a:1 s:2 d g'::tsvector, 'a | s');
+ rank 
+------
+ 0.19
+(1 row)
+
+select rank(' a:1 s:2C d g'::tsvector, 'a & s');
+   rank   
+----------
+ 0.140153
+(1 row)
+
+select rank(' a:1 s:2B d g'::tsvector, 'a & s');
+   rank   
+----------
+ 0.198206
+(1 row)
+
+select rank(' a:1 s:2 d g'::tsvector, 'a & s');
+   rank    
+-----------
+ 0.0991032
+(1 row)
+
+insert into test_tsvector (t) values ('foo bar foo the over foo qq bar');
+select * from stat('select a from test_tsvector') order by ndoc desc, nentry desc, word;
+   word    | ndoc | nentry 
+-----------+------+--------
+ qq        |  109 |    109
+ qt        |  102 |    102
+ qe        |  100 |    100
+ qh        |   98 |     98
+ qw        |   98 |     98
+ qa        |   97 |     97
+ ql        |   94 |     94
+ qs        |   94 |     94
+ qi        |   92 |     92
+ qr        |   92 |     92
+ qj        |   91 |     91
+ qd        |   87 |     87
+ qz        |   87 |     87
+ qc        |   86 |     86
+ qn        |   86 |     86
+ qv        |   85 |     85
+ qo        |   84 |     84
+ qy        |   84 |     84
+ wp        |   84 |     84
+ qf        |   81 |     81
+ qk        |   80 |     80
+ wt        |   80 |     80
+ qu        |   79 |     79
+ qg        |   78 |     78
+ wb        |   78 |     78
+ qx        |   77 |     77
+ wr        |   77 |     77
+ ws        |   73 |     73
+ wy        |   73 |     73
+ wa        |   72 |     72
+ wf        |   70 |     70
+ wg        |   70 |     70
+ wi        |   70 |     70
+ wu        |   70 |     70
+ wc        |   69 |     69
+ wj        |   69 |     69
+ qp        |   68 |     68
+ wh        |   68 |     68
+ wv        |   68 |     68
+ qb        |   66 |     66
+ eu        |   65 |     65
+ we        |   65 |     65
+ wl        |   65 |     65
+ wq        |   65 |     65
+ wk        |   64 |     64
+ ee        |   63 |     63
+ eo        |   63 |     63
+ qm        |   63 |     63
+ wn        |   63 |     63
+ ef        |   62 |     62
+ eh        |   62 |     62
+ ex        |   62 |     62
+ re        |   62 |     62
+ rl        |   62 |     62
+ rr        |   62 |     62
+ eb        |   61 |     61
+ ek        |   61 |     61
+ ww        |   61 |     61
+ ea        |   60 |     60
+ ei        |   60 |     60
+ em        |   60 |     60
+ eq        |   60 |     60
+ ew        |   60 |     60
+ ro        |   60 |     60
+ rw        |   60 |     60
+ tl        |   60 |     60
+ eg        |   59 |     59
+ en        |   59 |     59
+ ez        |   59 |     59
+ rj        |   59 |     59
+ ry        |   59 |     59
+ tw        |   59 |     59
+ tx        |   59 |     59
+ ej        |   58 |     58
+ es        |   58 |     58
+ ra        |   58 |     58
+ rd        |   58 |     58
+ rg        |   58 |     58
+ rx        |   58 |     58
+ tb        |   58 |     58
+ wd        |   58 |     58
+ ed        |   57 |     57
+ tc        |   57 |     57
+ wx        |   57 |     57
+ er        |   56 |     56
+ wm        |   56 |     56
+ wo        |   56 |     56
+ yw        |   56 |     56
+ ep        |   55 |     55
+ rk        |   55 |     55
+ rp        |   55 |     55
+ rz        |   55 |     55
+ ta        |   55 |     55
+ rq        |   54 |     54
+ yn        |   54 |     54
+ ec        |   53 |     53
+ el        |   53 |     53
+ ru        |   53 |     53
+ rv        |   53 |     53
+ tz        |   53 |     53
+ un        |   53 |     53
+ wz        |   53 |     53
+ ys        |   53 |     53
+ oe        |   52 |     52
+ tn        |   52 |     52
+ tq        |   52 |     52
+ ty        |   52 |     52
+ uq        |   52 |     52
+ yg        |   52 |     52
+ ym        |   52 |     52
+ oi        |   51 |     51
+ to        |   51 |     51
+ yi        |   51 |     51
+ pn        |   50 |     50
+ rb        |   50 |     50
+ ri        |   50 |     50
+ rn        |   50 |     50
+ ti        |   50 |     50
+ tv        |   50 |     50
+ um        |   50 |     50
+ ut        |   50 |     50
+ ya        |   50 |     50
+ et        |   49 |     49
+ ix        |   49 |     49
+ ox        |   49 |     49
+ q3        |   49 |     49
+ yf        |   49 |     49
+ yl        |   49 |     49
+ yo        |   49 |     49
+ yr        |   49 |     49
+ ev        |   48 |     48
+ ey        |   48 |     48
+ ot        |   48 |     48
+ rc        |   48 |     48
+ rm        |   48 |     48
+ th        |   48 |     48
+ uo        |   48 |     48
+ ia        |   47 |     47
+ q1        |   47 |     47
+ rh        |   47 |     47
+ yq        |   47 |     47
+ yz        |   47 |     47
+ av        |   46 |     46
+ im        |   46 |     46
+ os        |   46 |     46
+ tk        |   46 |     46
+ yy        |   46 |     46
+ ir        |   45 |     45
+ iv        |   45 |     45
+ iw        |   45 |     45
+ oj        |   45 |     45
+ pl        |   45 |     45
+ pv        |   45 |     45
+ te        |   45 |     45
+ tu        |   45 |     45
+ uv        |   45 |     45
+ ux        |   45 |     45
+ yd        |   45 |     45
+ yx        |   45 |     45
+ ij        |   44 |     44
+ pa        |   44 |     44
+ se        |   44 |     44
+ tg        |   44 |     44
+ ue        |   44 |     44
+ yb        |   44 |     44
+ yt        |   44 |     44
+ if        |   43 |     43
+ ik        |   43 |     43
+ in        |   43 |     43
+ ph        |   43 |     43
+ pj        |   43 |     43
+ q5        |   43 |     43
+ rt        |   43 |     43
+ ub        |   43 |     43
+ ud        |   43 |     43
+ uh        |   43 |     43
+ uj        |   43 |     43
+ w7        |   43 |     43
+ ye        |   43 |     43
+ yv        |   43 |     43
+ db        |   42 |     42
+ do        |   42 |     42
+ id        |   42 |     42
+ ie        |   42 |     42
+ ii        |   42 |     42
+ of        |   42 |     42
+ pr        |   42 |     42
+ q4        |   42 |     42
+ rf        |   42 |     42
+ td        |   42 |     42
+ uk        |   42 |     42
+ up        |   42 |     42
+ yh        |   42 |     42
+ yk        |   42 |     42
+ io        |   41 |     41
+ it        |   41 |     41
+ pb        |   41 |     41
+ q0        |   41 |     41
+ q7        |   41 |     41
+ rs        |   41 |     41
+ tj        |   41 |     41
+ ur        |   41 |     41
+ ig        |   40 |     40
+ iu        |   40 |     40
+ iy        |   40 |     40
+ od        |   40 |     40
+ q6        |   40 |     40
+ tt        |   40 |     40
+ ug        |   40 |     40
+ ul        |   40 |     40
+ us        |   40 |     40
+ uu        |   40 |     40
+ uz        |   40 |     40
+ ah        |   39 |     39
+ ar        |   39 |     39
+ as        |   39 |     39
+ dl        |   39 |     39
+ dt        |   39 |     39
+ hk        |   39 |     39
+ iq        |   39 |     39
+ is        |   39 |     39
+ oc        |   39 |     39
+ ov        |   39 |     39
+ oy        |   39 |     39
+ uf        |   39 |     39
+ ui        |   39 |     39
+ aa        |   38 |     38
+ ad        |   38 |     38
+ fh        |   38 |     38
+ gm        |   38 |     38
+ ic        |   38 |     38
+ jd        |   38 |     38
+ om        |   38 |     38
+ or        |   38 |     38
+ oz        |   38 |     38
+ pm        |   38 |     38
+ q8        |   38 |     38
+ sf        |   38 |     38
+ sm        |   38 |     38
+ sv        |   38 |     38
+ uc        |   38 |     38
+ ak        |   37 |     37
+ aq        |   37 |     37
+ di        |   37 |     37
+ e4        |   37 |     37
+ fi        |   37 |     37
+ fx        |   37 |     37
+ ha        |   37 |     37
+ hp        |   37 |     37
+ ih        |   37 |     37
+ og        |   37 |     37
+ po        |   37 |     37
+ pw        |   37 |     37
+ sn        |   37 |     37
+ su        |   37 |     37
+ sw        |   37 |     37
+ w6        |   37 |     37
+ yj        |   37 |     37
+ yu        |   37 |     37
+ ag        |   36 |     36
+ am        |   36 |     36
+ at        |   36 |     36
+ e1        |   36 |     36
+ ff        |   36 |     36
+ gx        |   36 |     36
+ he        |   36 |     36
+ hj        |   36 |     36
+ ib        |   36 |     36
+ iz        |   36 |     36
+ lm        |   36 |     36
+ ok        |   36 |     36
+ pk        |   36 |     36
+ pp        |   36 |     36
+ pu        |   36 |     36
+ sp        |   36 |     36
+ tf        |   36 |     36
+ tm        |   36 |     36
+ ay        |   35 |     35
+ dy        |   35 |     35
+ fu        |   35 |     35
+ ku        |   35 |     35
+ lh        |   35 |     35
+ lq        |   35 |     35
+ o6        |   35 |     35
+ ob        |   35 |     35
+ on        |   35 |     35
+ op        |   35 |     35
+ pd        |   35 |     35
+ ps        |   35 |     35
+ si        |   35 |     35
+ sl        |   35 |     35
+ sx        |   35 |     35
+ tp        |   35 |     35
+ tr        |   35 |     35
+ w3        |   35 |     35
+ y1        |   35 |     35
+ al        |   34 |     34
+ ap        |   34 |     34
+ az        |   34 |     34
+ dc        |   34 |     34
+ dd        |   34 |     34
+ dz        |   34 |     34
+ e0        |   34 |     34
+ fj        |   34 |     34
+ fp        |   34 |     34
+ gd        |   34 |     34
+ gg        |   34 |     34
+ gk        |   34 |     34
+ go        |   34 |     34
+ ho        |   34 |     34
+ jc        |   34 |     34
+ oa        |   34 |     34
+ oh        |   34 |     34
+ oo        |   34 |     34
+ pe        |   34 |     34
+ px        |   34 |     34
+ sd        |   34 |     34
+ sq        |   34 |     34
+ sy        |   34 |     34
+ ab        |   33 |     33
+ ae        |   33 |     33
+ af        |   33 |     33
+ aw        |   33 |     33
+ e5        |   33 |     33
+ fk        |   33 |     33
+ gu        |   33 |     33
+ gy        |   33 |     33
+ hb        |   33 |     33
+ hm        |   33 |     33
+ hy        |   33 |     33
+ jl        |   33 |     33
+ jr        |   33 |     33
+ ls        |   33 |     33
+ oq        |   33 |     33
+ pt        |   33 |     33
+ sa        |   33 |     33
+ sh        |   33 |     33
+ sj        |   33 |     33
+ so        |   33 |     33
+ sz        |   33 |     33
+ t7        |   33 |     33
+ uw        |   33 |     33
+ w8        |   33 |     33
+ y0        |   33 |     33
+ yp        |   33 |     33
+ dh        |   32 |     32
+ dp        |   32 |     32
+ dq        |   32 |     32
+ e7        |   32 |     32
+ fn        |   32 |     32
+ fo        |   32 |     32
+ fr        |   32 |     32
+ ga        |   32 |     32
+ gq        |   32 |     32
+ hh        |   32 |     32
+ il        |   32 |     32
+ ip        |   32 |     32
+ jv        |   32 |     32
+ lc        |   32 |     32
+ ol        |   32 |     32
+ pc        |   32 |     32
+ q9        |   32 |     32
+ ds        |   31 |     31
+ e9        |   31 |     31
+ fd        |   31 |     31
+ fe        |   31 |     31
+ ft        |   31 |     31
+ gs        |   31 |     31
+ hl        |   31 |     31
+ hs        |   31 |     31
+ jb        |   31 |     31
+ kc        |   31 |     31
+ kw        |   31 |     31
+ mj        |   31 |     31
+ q2        |   31 |     31
+ r3        |   31 |     31
+ sb        |   31 |     31
+ sk        |   31 |     31
+ ts        |   31 |     31
+ ua        |   31 |     31
+ yc        |   31 |     31
+ zw        |   31 |     31
+ ao        |   30 |     30
+ du        |   30 |     30
+ fw        |   30 |     30
+ gj        |   30 |     30
+ hu        |   30 |     30
+ kh        |   30 |     30
+ kl        |   30 |     30
+ kv        |   30 |     30
+ ld        |   30 |     30
+ lf        |   30 |     30
+ pq        |   30 |     30
+ py        |   30 |     30
+ sc        |   30 |     30
+ sr        |   30 |     30
+ uy        |   30 |     30
+ vg        |   30 |     30
+ w2        |   30 |     30
+ xg        |   30 |     30
+ xo        |   30 |     30
+ au        |   29 |     29
+ cx        |   29 |     29
+ fv        |   29 |     29
+ gh        |   29 |     29
+ gl        |   29 |     29
+ gt        |   29 |     29
+ hw        |   29 |     29
+ ji        |   29 |     29
+ km        |   29 |     29
+ la        |   29 |     29
+ ou        |   29 |     29
+ r0        |   29 |     29
+ w0        |   29 |     29
+ y9        |   29 |     29
+ zm        |   29 |     29
+ zs        |   29 |     29
+ zy        |   29 |     29
+ ax        |   28 |     28
+ cd        |   28 |     28
+ dj        |   28 |     28
+ dn        |   28 |     28
+ dr        |   28 |     28
+ ht        |   28 |     28
+ jf        |   28 |     28
+ lo        |   28 |     28
+ lr        |   28 |     28
+ na        |   28 |     28
+ ng        |   28 |     28
+ r8        |   28 |     28
+ ss        |   28 |     28
+ xt        |   28 |     28
+ y6        |   28 |     28
+ aj        |   27 |     27
+ ca        |   27 |     27
+ cg        |   27 |     27
+ df        |   27 |     27
+ dg        |   27 |     27
+ dv        |   27 |     27
+ gc        |   27 |     27
+ gn        |   27 |     27
+ gr        |   27 |     27
+ hd        |   27 |     27
+ i8        |   27 |     27
+ jn        |   27 |     27
+ jt        |   27 |     27
+ lp        |   27 |     27
+ o9        |   27 |     27
+ ow        |   27 |     27
+ r9        |   27 |     27
+ t8        |   27 |     27
+ u5        |   27 |     27
+ w4        |   27 |     27
+ xm        |   27 |     27
+ zz        |   27 |     27
+ a2        |   26 |     26
+ ac        |   26 |     26
+ ai        |   26 |     26
+ cm        |   26 |     26
+ cu        |   26 |     26
+ cw        |   26 |     26
+ dk        |   26 |     26
+ e2        |   26 |     26
+ fc        |   26 |     26
+ fg        |   26 |     26
+ fl        |   26 |     26
+ fs        |   26 |     26
+ ge        |   26 |     26
+ gv        |   26 |     26
+ hc        |   26 |     26
+ hi        |   26 |     26
+ hx        |   26 |     26
+ jj        |   26 |     26
+ jm        |   26 |     26
+ kg        |   26 |     26
+ kk        |   26 |     26
+ kn        |   26 |     26
+ ko        |   26 |     26
+ kt        |   26 |     26
+ ln        |   26 |     26
+ mx        |   26 |     26
+ pg        |   26 |     26
+ r4        |   26 |     26
+ t6        |   26 |     26
+ u1        |   26 |     26
+ u4        |   26 |     26
+ vi        |   26 |     26
+ vr        |   26 |     26
+ w1        |   26 |     26
+ w9        |   26 |     26
+ xk        |   26 |     26
+ xs        |   26 |     26
+ zf        |   26 |     26
+ bb        |   25 |     25
+ dm        |   25 |     25
+ dw        |   25 |     25
+ e8        |   25 |     25
+ fb        |   25 |     25
+ gw        |   25 |     25
+ h8        |   25 |     25
+ hf        |   25 |     25
+ hg        |   25 |     25
+ hn        |   25 |     25
+ hv        |   25 |     25
+ i0        |   25 |     25
+ i3        |   25 |     25
+ jg        |   25 |     25
+ jo        |   25 |     25
+ jx        |   25 |     25
+ kq        |   25 |     25
+ lw        |   25 |     25
+ lx        |   25 |     25
+ o3        |   25 |     25
+ p7        |   25 |     25
+ pf        |   25 |     25
+ pi        |   25 |     25
+ pz        |   25 |     25
+ r2        |   25 |     25
+ r5        |   25 |     25
+ t9        |   25 |     25
+ u7        |   25 |     25
+ ve        |   25 |     25
+ vu        |   25 |     25
+ y5        |   25 |     25
+ y8        |   25 |     25
+ zt        |   25 |     25
+ an        |   24 |     24
+ bj        |   24 |     24
+ dx        |   24 |     24
+ fm        |   24 |     24
+ fz        |   24 |     24
+ gb        |   24 |     24
+ gi        |   24 |     24
+ gp        |   24 |     24
+ hr        |   24 |     24
+ hz        |   24 |     24
+ i5        |   24 |     24
+ jq        |   24 |     24
+ kb        |   24 |     24
+ ke        |   24 |     24
+ kf        |   24 |     24
+ kp        |   24 |     24
+ lv        |   24 |     24
+ lz        |   24 |     24
+ o8        |   24 |     24
+ r1        |   24 |     24
+ s7        |   24 |     24
+ sg        |   24 |     24
+ u3        |   24 |     24
+ vj        |   24 |     24
+ vt        |   24 |     24
+ w5        |   24 |     24
+ zj        |   24 |     24
+ be        |   23 |     23
+ bi        |   23 |     23
+ bn        |   23 |     23
+ cn        |   23 |     23
+ cy        |   23 |     23
+ da        |   23 |     23
+ e6        |   23 |     23
+ fa        |   23 |     23
+ js        |   23 |     23
+ ki        |   23 |     23
+ kz        |   23 |     23
+ li        |   23 |     23
+ mt        |   23 |     23
+ mz        |   23 |     23
+ nu        |   23 |     23
+ o2        |   23 |     23
+ p5        |   23 |     23
+ p8        |   23 |     23
+ r7        |   23 |     23
+ t0        |   23 |     23
+ t1        |   23 |     23
+ t3        |   23 |     23
+ vm        |   23 |     23
+ xh        |   23 |     23
+ xx        |   23 |     23
+ zp        |   23 |     23
+ zr        |   23 |     23
+ a3        |   22 |     22
+ bg        |   22 |     22
+ de        |   22 |     22
+ e3        |   22 |     22
+ fq        |   22 |     22
+ i2        |   22 |     22
+ i7        |   22 |     22
+ ja        |   22 |     22
+ jk        |   22 |     22
+ jy        |   22 |     22
+ kr        |   22 |     22
+ kx        |   22 |     22
+ ly        |   22 |     22
+ nb        |   22 |     22
+ nh        |   22 |     22
+ ns        |   22 |     22
+ s3        |   22 |     22
+ u2        |   22 |     22
+ vn        |   22 |     22
+ xe        |   22 |     22
+ y4        |   22 |     22
+ zh        |   22 |     22
+ zo        |   22 |     22
+ zq        |   22 |     22
+ a1        |   21 |     21
+ bl        |   21 |     21
+ bo        |   21 |     21
+ cb        |   21 |     21
+ ch        |   21 |     21
+ co        |   21 |     21
+ cq        |   21 |     21
+ cv        |   21 |     21
+ d7        |   21 |     21
+ g8        |   21 |     21
+ je        |   21 |     21
+ jp        |   21 |     21
+ jz        |   21 |     21
+ lg        |   21 |     21
+ me        |   21 |     21
+ nc        |   21 |     21
+ p4        |   21 |     21
+ st        |   21 |     21
+ vb        |   21 |     21
+ vw        |   21 |     21
+ vz        |   21 |     21
+ xj        |   21 |     21
+ xq        |   21 |     21
+ xu        |   21 |     21
+ xy        |   21 |     21
+ zb        |   21 |     21
+ bv        |   20 |     20
+ bz        |   20 |     20
+ cj        |   20 |     20
+ cp        |   20 |     20
+ cs        |   20 |     20
+ d8        |   20 |     20
+ ju        |   20 |     20
+ k0        |   20 |     20
+ ks        |   20 |     20
+ ky        |   20 |     20
+ l1        |   20 |     20
+ lb        |   20 |     20
+ lj        |   20 |     20
+ lu        |   20 |     20
+ nm        |   20 |     20
+ nw        |   20 |     20
+ nz        |   20 |     20
+ o7        |   20 |     20
+ p6        |   20 |     20
+ vh        |   20 |     20
+ vp        |   20 |     20
+ vs        |   20 |     20
+ xb        |   20 |     20
+ xr        |   20 |     20
+ z3        |   20 |     20
+ zv        |   20 |     20
+ bq        |   19 |     19
+ br        |   19 |     19
+ by        |   19 |     19
+ cl        |   19 |     19
+ d2        |   19 |     19
+ f1        |   19 |     19
+ f4        |   19 |     19
+ gf        |   19 |     19
+ hq        |   19 |     19
+ k9        |   19 |     19
+ ka        |   19 |     19
+ kd        |   19 |     19
+ kj        |   19 |     19
+ md        |   19 |     19
+ mi        |   19 |     19
+ ml        |   19 |     19
+ my        |   19 |     19
+ nj        |   19 |     19
+ ny        |   19 |     19
+ o1        |   19 |     19
+ s4        |   19 |     19
+ s8        |   19 |     19
+ t5        |   19 |     19
+ u0        |   19 |     19
+ xl        |   19 |     19
+ zg        |   19 |     19
+ zi        |   19 |     19
+ a5        |   18 |     18
+ b9        |   18 |     18
+ bh        |   18 |     18
+ bx        |   18 |     18
+ d3        |   18 |     18
+ fy        |   18 |     18
+ g2        |   18 |     18
+ i4        |   18 |     18
+ i6        |   18 |     18
+ i9        |   18 |     18
+ jw        |   18 |     18
+ lk        |   18 |     18
+ mb        |   18 |     18
+ mv        |   18 |     18
+ nd        |   18 |     18
+ nr        |   18 |     18
+ nt        |   18 |     18
+ t2        |   18 |     18
+ xf        |   18 |     18
+ xv        |   18 |     18
+ zc        |   18 |     18
+ zd        |   18 |     18
+ a7        |   17 |     17
+ bc        |   17 |     17
+ bd        |   17 |     17
+ ce        |   17 |     17
+ cf        |   17 |     17
+ cr        |   17 |     17
+ g9        |   17 |     17
+ j0        |   17 |     17
+ j5        |   17 |     17
+ mp        |   17 |     17
+ mr        |   17 |     17
+ mw        |   17 |     17
+ nk        |   17 |     17
+ no        |   17 |     17
+ o0        |   17 |     17
+ o4        |   17 |     17
+ s0        |   17 |     17
+ s1        |   17 |     17
+ t4        |   17 |     17
+ u9        |   17 |     17
+ vf        |   17 |     17
+ vx        |   17 |     17
+ x3        |   17 |     17
+ xi        |   17 |     17
+ xn        |   17 |     17
+ xz        |   17 |     17
+ zl        |   17 |     17
+ zn        |   17 |     17
+ a0        |   16 |     16
+ bu        |   16 |     16
+ bw        |   16 |     16
+ ci        |   16 |     16
+ ck        |   16 |     16
+ d0        |   16 |     16
+ d4        |   16 |     16
+ d6        |   16 |     16
+ f5        |   16 |     16
+ g1        |   16 |     16
+ gz        |   16 |     16
+ h4        |   16 |     16
+ jh        |   16 |     16
+ l4        |   16 |     16
+ lt        |   16 |     16
+ mg        |   16 |     16
+ mh        |   16 |     16
+ mo        |   16 |     16
+ ni        |   16 |     16
+ nl        |   16 |     16
+ nq        |   16 |     16
+ p2        |   16 |     16
+ u8        |   16 |     16
+ v9        |   16 |     16
+ vl        |   16 |     16
+ vo        |   16 |     16
+ xp        |   16 |     16
+ y3        |   16 |     16
+ y7        |   16 |     16
+ z7        |   16 |     16
+ za        |   16 |     16
+ zx        |   16 |     16
+ bf        |   15 |     15
+ bp        |   15 |     15
+ cc        |   15 |     15
+ g0        |   15 |     15
+ j2        |   15 |     15
+ j9        |   15 |     15
+ l6        |   15 |     15
+ le        |   15 |     15
+ ll        |   15 |     15
+ m8        |   15 |     15
+ ma        |   15 |     15
+ mu        |   15 |     15
+ nf        |   15 |     15
+ r6        |   15 |     15
+ s5        |   15 |     15
+ vd        |   15 |     15
+ vk        |   15 |     15
+ xa        |   15 |     15
+ xw        |   15 |     15
+ y2        |   15 |     15
+ z8        |   15 |     15
+ ze        |   15 |     15
+ zu        |   15 |     15
+ a6        |   14 |     14
+ bk        |   14 |     14
+ bt        |   14 |     14
+ c0        |   14 |     14
+ f8        |   14 |     14
+ g3        |   14 |     14
+ g4        |   14 |     14
+ g7        |   14 |     14
+ h6        |   14 |     14
+ h7        |   14 |     14
+ h9        |   14 |     14
+ i1        |   14 |     14
+ k1        |   14 |     14
+ k2        |   14 |     14
+ k6        |   14 |     14
+ k7        |   14 |     14
+ mc        |   14 |     14
+ nn        |   14 |     14
+ p9        |   14 |     14
+ u6        |   14 |     14
+ xd        |   14 |     14
+ z6        |   14 |     14
+ zk        |   14 |     14
+ a4        |   13 |     13
+ a9        |   13 |     13
+ bm        |   13 |     13
+ cz        |   13 |     13
+ f2        |   13 |     13
+ f3        |   13 |     13
+ f6        |   13 |     13
+ g6        |   13 |     13
+ h2        |   13 |     13
+ j1        |   13 |     13
+ k5        |   13 |     13
+ m1        |   13 |     13
+ mf        |   13 |     13
+ mq        |   13 |     13
+ np        |   13 |     13
+ nx        |   13 |     13
+ o5        |   13 |     13
+ p0        |   13 |     13
+ p1        |   13 |     13
+ s6        |   13 |     13
+ s9        |   13 |     13
+ v6        |   13 |     13
+ va        |   13 |     13
+ vc        |   13 |     13
+ xc        |   13 |     13
+ z0        |   13 |     13
+ c9        |   12 |     12
+ d1        |   12 |     12
+ h0        |   12 |     12
+ h1        |   12 |     12
+ j8        |   12 |     12
+ k4        |   12 |     12
+ l5        |   12 |     12
+ l9        |   12 |     12
+ m2        |   12 |     12
+ m6        |   12 |     12
+ m9        |   12 |     12
+ n7        |   12 |     12
+ nv        |   12 |     12
+ p3        |   12 |     12
+ vq        |   12 |     12
+ vy        |   12 |     12
+ x1        |   12 |     12
+ x2        |   12 |     12
+ z5        |   12 |     12
+ c1        |   11 |     11
+ c3        |   11 |     11
+ ct        |   11 |     11
+ f9        |   11 |     11
+ g5        |   11 |     11
+ j6        |   11 |     11
+ l8        |   11 |     11
+ n1        |   11 |     11
+ v7        |   11 |     11
+ vv        |   11 |     11
+ x5        |   11 |     11
+ x8        |   11 |     11
+ z2        |   11 |     11
+ b0        |   10 |     10
+ b2        |   10 |     10
+ b8        |   10 |     10
+ c6        |   10 |     10
+ f0        |   10 |     10
+ f7        |   10 |     10
+ h5        |   10 |     10
+ j3        |   10 |     10
+ j4        |   10 |     10
+ j7        |   10 |     10
+ l7        |   10 |     10
+ m0        |   10 |     10
+ m7        |   10 |     10
+ mm        |   10 |     10
+ mn        |   10 |     10
+ n8        |   10 |     10
+ v1        |   10 |     10
+ x0        |   10 |     10
+ x6        |   10 |     10
+ x7        |   10 |     10
+ x9        |   10 |     10
+ a8        |    9 |      9
+ b1        |    9 |      9
+ b4        |    9 |      9
+ b5        |    9 |      9
+ b6        |    9 |      9
+ ba        |    9 |      9
+ bs        |    9 |      9
+ c5        |    9 |      9
+ d5        |    9 |      9
+ k8        |    9 |      9
+ l0        |    9 |      9
+ m5        |    9 |      9
+ mk        |    9 |      9
+ ms        |    9 |      9
+ n3        |    9 |      9
+ n4        |    9 |      9
+ n6        |    9 |      9
+ ne        |    9 |      9
+ v0        |    9 |      9
+ v3        |    9 |      9
+ v5        |    9 |      9
+ v8        |    9 |      9
+ b3        |    8 |      8
+ b7        |    8 |      8
+ c2        |    8 |      8
+ c7        |    8 |      8
+ c8        |    8 |      8
+ d9        |    8 |      8
+ k3        |    8 |      8
+ l3        |    8 |      8
+ m3        |    8 |      8
+ m4        |    8 |      8
+ n0        |    8 |      8
+ n5        |    8 |      8
+ v4        |    8 |      8
+ x4        |    8 |      8
+ z1        |    8 |      8
+ z9        |    8 |      8
+ l2        |    7 |      7
+ s2        |    7 |      7
+ z4        |    7 |      7
+ 1l        |    6 |      6
+ 1o        |    6 |      6
+ 1t        |    6 |      6
+ 2e        |    6 |      6
+ 2o        |    6 |      6
+ c4        |    6 |      6
+ h3        |    6 |      6
+ n2        |    6 |      6
+ n9        |    6 |      6
+ v2        |    6 |      6
+ 2l        |    5 |      5
+ 2u        |    5 |      5
+ 3k        |    5 |      5
+ 4p        |    5 |      5
+ 18        |    4 |      4
+ 1a        |    4 |      4
+ 1i        |    4 |      4
+ 2s        |    4 |      4
+ 3q        |    4 |      4
+ 3y        |    4 |      4
+ 5y        |    4 |      4
+ 1f        |    3 |      3
+ 1h        |    3 |      3
+ 1m        |    3 |      3
+ 1p        |    3 |      3
+ 1s        |    3 |      3
+ 1v        |    3 |      3
+ 1x        |    3 |      3
+ 27        |    3 |      3
+ 2a        |    3 |      3
+ 2b        |    3 |      3
+ 2h        |    3 |      3
+ 2n        |    3 |      3
+ 2p        |    3 |      3
+ 2v        |    3 |      3
+ 2y        |    3 |      3
+ 3d        |    3 |      3
+ 3w        |    3 |      3
+ 3z        |    3 |      3
+ 4a        |    3 |      3
+ 4d        |    3 |      3
+ 4v        |    3 |      3
+ 4z        |    3 |      3
+ 5e        |    3 |      3
+ 5i        |    3 |      3
+ 5k        |    3 |      3
+ 5o        |    3 |      3
+ 5t        |    3 |      3
+ 6b        |    3 |      3
+ 6d        |    3 |      3
+ 6o        |    3 |      3
+ 6w        |    3 |      3
+ 7a        |    3 |      3
+ 7h        |    3 |      3
+ 7r        |    3 |      3
+ 93        |    3 |      3
+ 10        |    2 |      2
+ 12        |    2 |      2
+ 15        |    2 |      2
+ 16        |    2 |      2
+ 19        |    2 |      2
+ 1b        |    2 |      2
+ 1d        |    2 |      2
+ 1g        |    2 |      2
+ 1j        |    2 |      2
+ 1n        |    2 |      2
+ 1r        |    2 |      2
+ 1u        |    2 |      2
+ 1w        |    2 |      2
+ 1y        |    2 |      2
+ 20        |    2 |      2
+ 25        |    2 |      2
+ 2d        |    2 |      2
+ 2i        |    2 |      2
+ 2j        |    2 |      2
+ 2k        |    2 |      2
+ 2q        |    2 |      2
+ 2r        |    2 |      2
+ 2t        |    2 |      2
+ 2w        |    2 |      2
+ 2z        |    2 |      2
+ 3b        |    2 |      2
+ 3f        |    2 |      2
+ 3h        |    2 |      2
+ 3o        |    2 |      2
+ 3p        |    2 |      2
+ 3r        |    2 |      2
+ 3s        |    2 |      2
+ 3v        |    2 |      2
+ 42        |    2 |      2
+ 43        |    2 |      2
+ 4f        |    2 |      2
+ 4g        |    2 |      2
+ 4h        |    2 |      2
+ 4j        |    2 |      2
+ 4m        |    2 |      2
+ 4r        |    2 |      2
+ 4s        |    2 |      2
+ 4t        |    2 |      2
+ 4u        |    2 |      2
+ 5c        |    2 |      2
+ 5f        |    2 |      2
+ 5h        |    2 |      2
+ 5p        |    2 |      2
+ 5q        |    2 |      2
+ 5z        |    2 |      2
+ 6a        |    2 |      2
+ 6h        |    2 |      2
+ 6q        |    2 |      2
+ 6r        |    2 |      2
+ 6t        |    2 |      2
+ 6y        |    2 |      2
+ 70        |    2 |      2
+ 7c        |    2 |      2
+ 7g        |    2 |      2
+ 7k        |    2 |      2
+ 7o        |    2 |      2
+ 7u        |    2 |      2
+ 8j        |    2 |      2
+ 8w        |    2 |      2
+ 9f        |    2 |      2
+ 9y        |    2 |      2
+ copyright |    2 |      2
+ foo       |    1 |      3
+ bar       |    1 |      2
+ 0e        |    1 |      1
+ 0h        |    1 |      1
+ 0p        |    1 |      1
+ 0w        |    1 |      1
+ 0z        |    1 |      1
+ 11        |    1 |      1
+ 13        |    1 |      1
+ 14        |    1 |      1
+ 17        |    1 |      1
+ 1k        |    1 |      1
+ 1q        |    1 |      1
+ 1z        |    1 |      1
+ 24        |    1 |      1
+ 26        |    1 |      1
+ 28        |    1 |      1
+ 2f        |    1 |      1
+ 30        |    1 |      1
+ 345       |    1 |      1
+ 37        |    1 |      1
+ 39        |    1 |      1
+ 3a        |    1 |      1
+ 3e        |    1 |      1
+ 3g        |    1 |      1
+ 3i        |    1 |      1
+ 3m        |    1 |      1
+ 3t        |    1 |      1
+ 3u        |    1 |      1
+ 40        |    1 |      1
+ 41        |    1 |      1
+ 44        |    1 |      1
+ 45        |    1 |      1
+ 48        |    1 |      1
+ 4b        |    1 |      1
+ 4c        |    1 |      1
+ 4i        |    1 |      1
+ 4k        |    1 |      1
+ 4n        |    1 |      1
+ 4o        |    1 |      1
+ 4q        |    1 |      1
+ 4w        |    1 |      1
+ 4y        |    1 |      1
+ 51        |    1 |      1
+ 55        |    1 |      1
+ 56        |    1 |      1
+ 5a        |    1 |      1
+ 5d        |    1 |      1
+ 5g        |    1 |      1
+ 5j        |    1 |      1
+ 5l        |    1 |      1
+ 5s        |    1 |      1
+ 5u        |    1 |      1
+ 5x        |    1 |      1
+ 64        |    1 |      1
+ 68        |    1 |      1
+ 6c        |    1 |      1
+ 6f        |    1 |      1
+ 6g        |    1 |      1
+ 6i        |    1 |      1
+ 6k        |    1 |      1
+ 6n        |    1 |      1
+ 6p        |    1 |      1
+ 6s        |    1 |      1
+ 6u        |    1 |      1
+ 6x        |    1 |      1
+ 72        |    1 |      1
+ 7f        |    1 |      1
+ 7j        |    1 |      1
+ 7n        |    1 |      1
+ 7p        |    1 |      1
+ 7w        |    1 |      1
+ 7y        |    1 |      1
+ 7z        |    1 |      1
+ 80        |    1 |      1
+ 82        |    1 |      1
+ 85        |    1 |      1
+ 8d        |    1 |      1
+ 8i        |    1 |      1
+ 8l        |    1 |      1
+ 8n        |    1 |      1
+ 8p        |    1 |      1
+ 8t        |    1 |      1
+ 8x        |    1 |      1
+ 95        |    1 |      1
+ 97        |    1 |      1
+ 9a        |    1 |      1
+ 9e        |    1 |      1
+ 9h        |    1 |      1
+ 9r        |    1 |      1
+ 9w        |    1 |      1
+ qwerti    |    1 |      1
+(1146 rows)
+
+select reset_tsearch();
+NOTICE:  TSearch cache cleaned
+ reset_tsearch 
+---------------
+(1 row)
+
+select to_tsquery('default', 'skies & books');
+   to_tsquery   
+----------------
+ 'sky' & 'book'
+(1 row)
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea&thousand&years'));
+ rank_cd 
+---------
+     1.2
+(1 row)
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('granite&sea'));
+ rank_cd  
+----------
+ 0.880303
+(1 row)
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea'));
+ rank_cd 
+---------
+       2
+(1 row)
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea&thousand&years'));
+                                                                                             get_covers                                                                                             
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ eros took {1 sea thousand year }1 {2 thousand year trace granit featur cliff crag scarp base took sea }2 hour one night hour storm place sculptur granit seam upon woman face e j pratt 1882 1964 
+(1 row)
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('granite&sea'));
+                                                                                                get_covers                                                                                                
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ eros took {1 sea thousand year thousand year trace {2 granit }1 featur cliff crag scarp base took {3 sea }2 hour one night hour storm place sculptur granit }3 seam upon woman face e j pratt 1882 1964 
+(1 row)
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea'));
+                                                                                             get_covers                                                                                             
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ eros took {1 sea }1 thousand year thousand year trace granit featur cliff crag scarp base took {2 sea }2 hour one night hour storm place sculptur granit seam upon woman face e j pratt 1882 1964 
+(1 row)
+
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('sea&thousand&years'));
+                                                       headline                                                        
+-----------------------------------------------------------------------------------------------------------------------
+ <b>sea</b> a <b>thousand</b> <b>years</b>,
+A <b>thousand</b> <b>years</b> to trace
+The granite features of this cliff
+(1 row)
+
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('granite&sea'));
+                                           headline                                           
+----------------------------------------------------------------------------------------------
+ <b>sea</b> an hour one night
+An hour of storm to place
+The sculpture of these <b>granite</b>
+(1 row)
+
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('sea'));
+                                         headline                                          
+-------------------------------------------------------------------------------------------
+ <b>sea</b> a thousand years,
+A thousand years to trace
+The granite features of this cliff
+(1 row)
+
+--check debug
+select * from ts_debug('Tsearch module for PostgreSQL 7.3.3');
+ ts_name | tok_type | description |   token    | dict_name |   tsvector   
+---------+----------+-------------+------------+-----------+--------------
+ default | lword    | Latin word  | Tsearch    | {en_stem} | 'tsearch'
+ default | lword    | Latin word  | module     | {en_stem} | 'modul'
+ default | lword    | Latin word  | for        | {en_stem} | 
+ default | lword    | Latin word  | PostgreSQL | {en_stem} | 'postgresql'
+ default | version  | VERSION     | 7.3.3      | {simple}  | '7.3.3'
+(5 rows)
+
diff --git a/contrib/tsearch2/ispell/Makefile b/contrib/tsearch2/ispell/Makefile
new file mode 100644 (file)
index 0000000..1864387
--- /dev/null
@@ -0,0 +1,20 @@
+# $Header$
+
+subdir = contrib/tsearch2/ispell
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+
+PG_CPPFLAGS = -I$(srcdir)/.. $(CPPFLAGS)
+override CFLAGS += $(CFLAGS_SL)
+
+SUBOBJS = spell.o 
+
+all: SUBSYS.o
+
+SUBSYS.o: $(SUBOBJS)
+       $(LD) $(LDREL) $(LDOUT) $@ $^
+
+EXTRA_CLEAN = SUBSYS.o $(SUBOBJS)
+
+include $(top_srcdir)/contrib/contrib-global.mk
diff --git a/contrib/tsearch2/query.c b/contrib/tsearch2/query.c
new file mode 100644 (file)
index 0000000..00537f4
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * IO definitions for tsquery and mtsquery. This type
+ * are identical, but for parsing mtsquery 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 <[email protected]>
+ */
+#include "postgres.h"
+
+#include <float.h>
+#include <ctype.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 "ts_cfg.h"
+#include "tsvector.h"
+#include "crc32.h"
+#include "query.h"
+#include "rewrite.h"
+#include "common.h"
+
+
+PG_FUNCTION_INFO_V1(tsquery_in);
+Datum          tsquery_in(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(tsquery_out);
+Datum          tsquery_out(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(exectsq);
+Datum          exectsq(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(rexectsq);
+Datum          rexectsq(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(tsquerytree);
+Datum          tsquerytree(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(to_tsquery);
+Datum          to_tsquery(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(to_tsquery_name);
+Datum          to_tsquery_name(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(to_tsquery_current);
+Datum          to_tsquery_current(PG_FUNCTION_ARGS);
+
+/* parser's states */
+#define WAITOPERAND 1
+#define WAITOPERATOR   2
+
+/*
+ * node of query tree, also used
+ * for storing polish notation in parser
+ */
+typedef struct NODE
+{
+       int2            weight;
+       int2            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 temprorary 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;
+
+       /* tscfg */
+       int                     cfg_id;
+}      QPRS_STATE;
+
+static char *
+get_weight(char *buf, int2 *weight)
+{
+       *weight = 0;
+
+       if (*buf != ':')
+               return buf;
+
+       buf++;
+       while (*buf)
+       {
+               switch (tolower(*buf))
+               {
+                       case 'a':
+                               *weight |= 1 << 3;
+                               break;
+                       case 'b':
+                               *weight |= 1 << 2;
+                               break;
+                       case 'c':
+                               *weight |= 1 << 1;
+                               break;
+                       case 'd':
+                               *weight |= 1;
+                               break;
+                       default:
+                               return buf;
+               }
+               buf++;
+       }
+
+       return buf;
+}
+
+/*
+ * get token from query string
+ */
+static int4
+gettoken_query(QPRS_STATE * state, int4 *val, int4 *lenval, char **strval, int2 *weight)
+{
+       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) == ':')
+                               {
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("error at start of operand")));
+                               }
+                               else if (*(state->buf) != ' ')
+                               {
+                                       state->valstate.prsbuf = state->buf;
+                                       state->state = WAITOPERATOR;
+                                       if (gettoken_tsvector(&(state->valstate)))
+                                       {
+                                               *strval = state->valstate.word;
+                                               *lenval = state->valstate.curpos - state->valstate.word;
+                                               state->buf = get_weight(state->valstate.prsbuf, weight);
+                                               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, int2 weight)
+{
+       NODE       *tmp = (NODE *) palloc(sizeof(NODE));
+
+       tmp->weight = weight;
+       tmp->type = type;
+       tmp->val = val;
+       if (distance >= MAXSTRPOS)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("value is too big")));
+       if (lenval >= MAXSTRLEN)
+               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 tsquery parsing
+ */
+static void
+pushval_asis(QPRS_STATE * state, int type, char *strval, int lenval, int2 weight)
+{
+       if (lenval >= MAXSTRLEN)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("word is too long")));
+
+       pushquery(state, type, crc32_sz((uint8 *) strval, lenval),
+                         state->curop - state->op, lenval, weight);
+
+       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 morph parsing
+ */
+static void
+pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval, int2 weight)
+{
+       int4            count = 0;
+       PRSTEXT         prs;
+
+       prs.lenwords = 32;
+       prs.curwords = 0;
+       prs.pos = 0;
+       prs.words = (WORD *) palloc(sizeof(WORD) * prs.lenwords);
+
+       parsetext_v2(findcfg(state->cfg_id), &prs, strval, lenval);
+
+       for (count = 0; count < prs.curwords; count++)
+       {
+               pushval_asis(state, VAL, prs.words[count].word, prs.words[count].len, weight);
+               pfree(prs.words[count].word);
+               if (count)
+                       pushquery(state, OPR, (int4) '&', 0, 0, 0);
+       }
+       pfree(prs.words);
+
+       /* XXX */
+       if (prs.curwords == 0)
+               pushval_asis(state, VALSTOP, 0, 0, 0);
+}
+
+#define STACKDEPTH     32
+/*
+ * make polish notaion of query
+ */
+static int4
+makepol(QPRS_STATE * state, void (*pushval) (QPRS_STATE *, int, char *, int, int2))
+{
+       int4            val,
+                               type;
+       int4            lenval;
+       char       *strval;
+       int4            stack[STACKDEPTH];
+       int4            lenstack = 0;
+       int2            weight;
+
+       while ((type = gettoken_query(state, &val, &lenval, &strval, &weight)) != END)
+       {
+               switch (type)
+               {
+                       case VAL:
+                               (*pushval) (state, VAL, strval, lenval, weight);
+                               while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
+                                                                       stack[lenstack - 1] == (int4) '!'))
+                               {
+                                       lenstack--;
+                                       pushquery(state, OPR, stack[lenstack], 0, 0, 0);
+                               }
+                               break;
+                       case OPR:
+                               if (lenstack && val == (int4) '|')
+                                       pushquery(state, OPR, val, 0, 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, 0);
+                               }
+                               break;
+                       case CLOSE:
+                               while (lenstack)
+                               {
+                                       lenstack--;
+                                       pushquery(state, OPR, stack[lenstack], 0, 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, 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;
+}
+
+/*
+ * check weight info
+ */
+static bool
+checkclass_str(CHKVAL * chkval, WordEntry * val, ITEM * item)
+{
+       WordEntryPos *ptr = (WordEntryPos *) (chkval->values + val->pos + SHORTALIGN(val->len) + sizeof(uint16));
+       uint16          len = *((uint16 *) (chkval->values + val->pos + SHORTALIGN(val->len)));
+
+       while (len--)
+       {
+               if (item->weight & (1 << ptr->weight))
+                       return true;
+               ptr++;
+       }
+       return false;
+}
+
+/*
+ * 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 (val->weight && StopMiddle->haspos) ?
+                               checkclass_str((CHKVAL *) checkval, StopMiddle, val) : true;
+               else if (difference < 0)
+                       StopLow = StopMiddle + 1;
+               else
+                       StopHigh = StopMiddle;
+       }
+
+       return (false);
+}
+
+/*
+ * check for boolean condition
+ */
+bool
+TS_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) ?
+                       ((TS_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
+                       : true;
+       }
+       else if (curitem->val == (int4) '&')
+       {
+               if (TS_execute(curitem + curitem->left, checkval, calcnot, chkcond))
+                       return TS_execute(curitem + 1, checkval, calcnot, chkcond);
+               else
+                       return false;
+       }
+       else
+       {                                                       /* |-operator */
+               if (TS_execute(curitem + curitem->left, checkval, calcnot, chkcond))
+                       return true;
+               else
+                       return TS_execute(curitem + 1, checkval, calcnot, chkcond);
+       }
+       return false;
+}
+
+/*
+ * boolean operations
+ */
+Datum
+rexectsq(PG_FUNCTION_ARGS)
+{
+       return DirectFunctionCall2(
+                                                          exectsq,
+                                                          PG_GETARG_DATUM(1),
+                                                          PG_GETARG_DATUM(0)
+               );
+}
+
+Datum
+exectsq(PG_FUNCTION_ARGS)
+{
+       tsvector   *val = (tsvector *) 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 = TS_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(DEBUG3, (ptr[*pos].type == OPR) ?
+                "%d  %c" : "%d  %d", *pos, ptr[*pos].val);
+#endif
+       if (ptr[*pos].type == VAL || ptr[*pos].type == VALSTOP)
+       {
+               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, int2), int cfg_id)
+{
+       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;
+       state.cfg_id = cfg_id;
+
+       /* 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].weight = state.str->weight;
+               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(DEBUG3, "POR: %s", pbuf);
+#endif
+
+       return query;
+}
+
+/*
+ * in without morphology
+ */
+Datum
+tsquery_in(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0), pushval_asis, 0));
+}
+
+/*
+ * 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 + 5);
+               *(in->cur) = '\'';
+               in->cur++;
+               while (*op)
+               {
+                       if (*op == '\'')
+                       {
+                               *(in->cur) = '\\';
+                               in->cur++;
+                       }
+                       *(in->cur) = *op;
+                       op++;
+                       in->cur++;
+               }
+               *(in->cur) = '\'';
+               in->cur++;
+               if (in->curpol->weight)
+               {
+                       *(in->cur) = ':';
+                       in->cur++;
+                       if (in->curpol->weight & (1 << 3))
+                       {
+                               *(in->cur) = 'A';
+                               in->cur++;
+                       }
+                       if (in->curpol->weight & (1 << 2))
+                       {
+                               *(in->cur) = 'B';
+                               in->cur++;
+                       }
+                       if (in->curpol->weight & (1 << 1))
+                       {
+                               *(in->cur) = 'C';
+                               in->cur++;
+                       }
+                       if (in->curpol->weight & 1)
+                       {
+                               *(in->cur) = 'D';
+                               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
+tsquery_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
+tsquerytree(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_v2(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);
+}
+
+Datum
+to_tsquery(PG_FUNCTION_ARGS)
+{
+       text       *in = PG_GETARG_TEXT_P(1);
+       char       *str;
+       QUERYTYPE  *query;
+       ITEM       *res;
+       int4            len;
+
+       str = text2char(in);
+       PG_FREE_IF_COPY(in, 1);
+
+       query = queryin(str, pushval_morph, PG_GETARG_INT32(0));
+       res = clean_fakeval_v2(GETQUERY(query), &len);
+       if (!res)
+       {
+               query->len = HDRSIZEQT;
+               query->size = 0;
+               PG_RETURN_POINTER(query);
+       }
+       memcpy((void *) GETQUERY(query), (void *) res, len * sizeof(ITEM));
+       pfree(res);
+       PG_RETURN_POINTER(query);
+}
+
+Datum
+to_tsquery_name(PG_FUNCTION_ARGS)
+{
+       text       *name = PG_GETARG_TEXT_P(0);
+       Datum           res = DirectFunctionCall2(
+                                                                                 to_tsquery,
+                                                                               Int32GetDatum(name2id_cfg(name)),
+                                                                                 PG_GETARG_DATUM(1)
+       );
+
+       PG_FREE_IF_COPY(name, 1);
+       PG_RETURN_DATUM(res);
+}
+
+Datum
+to_tsquery_current(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_DATUM(DirectFunctionCall2(
+                                                                               to_tsquery,
+                                                                               Int32GetDatum(get_currcfg()),
+                                                                               PG_GETARG_DATUM(0)
+                                                                               ));
+}
diff --git a/contrib/tsearch2/query.h b/contrib/tsearch2/query.h
new file mode 100644 (file)
index 0000000..a65dbca
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __QUERY_H__
+#define __QUERY_H__
+/*
+#define BS_DEBUG
+*/
+
+
+/*
+ * item in polish notation with back link
+ * to left operand
+ */
+typedef struct ITEM
+{
+       int8            type;
+       int8            weight;
+       int2            left;
+       int4            val;
+       /* user-friendly value, must correlate with WordEntry */
+       uint32
+                               unused:1,
+                               length:11,
+                               distance:20;
+}      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 VALSTOP                        6               /* for stop words */
+
+bool TS_execute(ITEM * curitem, void *checkval,
+                  bool calcnot, bool (*chkcond) (void *checkval, ITEM * val));
+
+#endif
diff --git a/contrib/tsearch2/rewrite.c b/contrib/tsearch2/rewrite.c
new file mode 100644 (file)
index 0000000..4d7294c
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Rewrite routines of query tree
+ * Teodor Sigaev <[email protected]>
+ */
+
+#include "postgres.h"
+
+#include <float.h>
+
+#include "access/gist.h"
+#include "access/itup.h"
+#include "access/rtree.h"
+#include "storage/bufpage.h"
+#include "utils/array.h"
+#include "utils/builtins.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 usefull 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_v2(ITEM * ptr, int4 *len)
+{
+       NODE       *root = maketree(ptr);
+
+       return plaintree(clean_NOT_intree(root), len);
+}
+
+#define V_UNKNOWN      0
+#define V_TRUE         1
+#define V_FALSE                2
+#define V_STOP         3
+
+/*
+ * 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 == VALSTOP)
+       {
+               pfree(node);
+               *result = V_STOP;
+               return NULL;
+       }
+
+
+       if (node->valnode->val == (int4) '!')
+       {
+               node->right = clean_fakeval_intree(node->right, &rresult);
+               if (!node->right)
+               {
+                       *result = V_STOP;
+                       freetree(node);
+                       return NULL;
+               }
+       }
+       else
+       {
+               NODE       *res = node;
+
+               node->left = clean_fakeval_intree(node->left, &lresult);
+               node->right = clean_fakeval_intree(node->right, &rresult);
+               if (lresult == V_STOP && rresult == V_STOP)
+               {
+                       freetree(node);
+                       *result = V_STOP;
+                       return NULL;
+               }
+               else if (lresult == V_STOP)
+               {
+                       res = node->right;
+                       pfree(node);
+               }
+               else if (rresult == V_STOP)
+               {
+                       res = node->left;
+                       pfree(node);
+               }
+               return res;
+       }
+       return node;
+}
+
+ITEM *
+clean_fakeval_v2(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 lexem(s), ignored");
+               *len = 0;
+               return NULL;
+       }
+
+       return plaintree(resroot, len);
+}
diff --git a/contrib/tsearch2/snowball/Makefile b/contrib/tsearch2/snowball/Makefile
new file mode 100644 (file)
index 0000000..49e550c
--- /dev/null
@@ -0,0 +1,20 @@
+# $Header$
+
+subdir = contrib/tsearch2/snowball
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+
+PG_CPPFLAGS = -I$(srcdir)/..
+override CFLAGS += $(CFLAGS_SL)
+
+SUBOBJS = english_stem.o api.o russian_stem.o utilities.o
+
+all: SUBSYS.o
+
+SUBSYS.o: $(SUBOBJS)
+       $(LD) $(LDREL) $(LDOUT) $@ $^
+
+EXTRA_CLEAN = SUBSYS.o $(SUBOBJS)
+
+include $(top_srcdir)/contrib/contrib-global.mk
diff --git a/contrib/tsearch2/sql/tsearch2.sql b/contrib/tsearch2/sql/tsearch2.sql
new file mode 100644 (file)
index 0000000..d4f1021
--- /dev/null
@@ -0,0 +1,249 @@
+--
+-- first, define the datatype.  Turn off echoing so that expected file
+-- does not depend on contents of seg.sql.
+--
+\set ECHO none
+\i tsearch2.sql
+\set ECHO all
+
+--tsvector
+SELECT '1'::tsvector;
+SELECT '1 '::tsvector;
+SELECT ' 1'::tsvector;
+SELECT ' 1 '::tsvector;
+SELECT '1 2'::tsvector;
+SELECT '\'1 2\''::tsvector;
+SELECT '\'1 \\\'2\''::tsvector;
+SELECT '\'1 \\\'2\'3'::tsvector;
+SELECT '\'1 \\\'2\' 3'::tsvector;
+SELECT '\'1 \\\'2\' \' 3\' 4 '::tsvector;
+select '\'w\':4A,3B,2C,1D,5 a:8';
+select 'a:3A b:2a'::tsvector || 'ba:1234 a:1B';
+select setweight('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd zxc:81,567,222A'::tsvector, 'c');
+select strip('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd'::tsvector);
+
+
+--tsquery
+SELECT '1'::tsquery;
+SELECT '1 '::tsquery;
+SELECT ' 1'::tsquery;
+SELECT ' 1 '::tsquery;
+SELECT '\'1 2\''::tsquery;
+SELECT '\'1 \\\'2\''::tsquery;
+SELECT '!1'::tsquery;
+SELECT '1|2'::tsquery;
+SELECT '1|!2'::tsquery;
+SELECT '!1|2'::tsquery;
+SELECT '!1|!2'::tsquery;
+SELECT '!(!1|!2)'::tsquery;
+SELECT '!(!1|2)'::tsquery;
+SELECT '!(1|!2)'::tsquery;
+SELECT '!(1|2)'::tsquery;
+SELECT '1&2'::tsquery;
+SELECT '!1&2'::tsquery;
+SELECT '1&!2'::tsquery;
+SELECT '!1&!2'::tsquery;
+SELECT '(1&2)'::tsquery;
+SELECT '1&(2)'::tsquery;
+SELECT '!(1)&2'::tsquery;
+SELECT '!(1&2)'::tsquery;
+SELECT '1|2&3'::tsquery;
+SELECT '1|(2&3)'::tsquery;
+SELECT '(1|2)&3'::tsquery;
+SELECT '1|2&!3'::tsquery;
+SELECT '1|!2&3'::tsquery;
+SELECT '!1|2&3'::tsquery;
+SELECT '!1|(2&3)'::tsquery;
+SELECT '!(1|2)&3'::tsquery;
+SELECT '(!1|2)&3'::tsquery;
+SELECT '1|(2|(4|(5|6)))'::tsquery;
+SELECT '1|2|4|5|6'::tsquery;
+SELECT '1&(2&(4&(5&6)))'::tsquery;
+SELECT '1&2&4&5&6'::tsquery;
+SELECT '1&(2&(4&(5|6)))'::tsquery;
+SELECT '1&(2&(4&(5|!6)))'::tsquery;
+SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::tsquery;
+SELECT '\'the wether\':dc & \' sKies \':BC & a:d b:a';
+
+select lexize('simple', 'ASD56 hsdkf');
+select lexize('en_stem', 'SKIES Problems identity');
+
+select * from token_type('default');
+select * from parse('default', '345 [email protected] \' 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 [email protected] 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 to_tsvector('default', '345 [email protected] \' 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 [email protected] 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 length(to_tsvector('default', '345 qw'));
+
+SELECT length(to_tsvector('default', '345 [email protected] \' 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 [email protected] 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 to_tsquery('default', 'qwe & sKies '); 
+select to_tsquery('simple', 'qwe & sKies '); 
+select to_tsquery('default', '\'the wether\':dc & \'           sKies \':BC ');
+select to_tsquery('asd&(and|fghj)');
+select to_tsquery('(asd&and)|fghj');
+select to_tsquery('(asd&!and)|fghj');
+select to_tsquery('(the|and&(i&1))&fghj');
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca';
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:B';
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:A';
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:C';
+select 'a b:89  ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:CB';
+
+CREATE TABLE test_tsvector( t text, a tsvector );
+
+\copy test_tsvector from 'data/test_tsearch.data'
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr&qh';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq&yt';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq|yt';
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq&yt)|(wr&qh)';
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq|yt)&(wr|qh)';
+
+create index wowidx on test_tsvector using gist (a);
+set enable_seqscan=off;
+
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'wr&qh';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq&yt';
+SELECT count(*) FROM test_tsvector WHERE a @@ 'eq|yt';
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq&yt)|(wr&qh)';
+SELECT count(*) FROM test_tsvector WHERE a @@ '(eq|yt)&(wr|qh)';
+
+select set_curcfg('default');
+
+CREATE TRIGGER tsvectorupdate
+BEFORE UPDATE OR INSERT ON test_tsvector
+FOR EACH ROW EXECUTE PROCEDURE tsearch2(a, t);
+
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+
+INSERT INTO test_tsvector (t) VALUES ('345 qwerty');
+
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+
+UPDATE test_tsvector SET t = null WHERE t = '345 qwerty';
+
+SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+
+drop trigger tsvectorupdate on test_tsvector;
+create function wow(text) returns text as 'select $1 || \' copyright\'; ' language sql;
+create trigger tsvectorupdate before update or insert on test_tsvector
+for each row execute procedure tsearch2(a, wow, t);
+insert into test_tsvector (t) values ('345 qwerty');
+select count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
+select count(*) FROM test_tsvector WHERE a @@ to_tsquery('copyright');
+
+select rank(' a:1 s:2C d g'::tsvector, 'a | s');
+select rank(' a:1 s:2B d g'::tsvector, 'a | s');
+select rank(' a:1 s:2 d g'::tsvector, 'a | s');
+select rank(' a:1 s:2C d g'::tsvector, 'a & s');
+select rank(' a:1 s:2B d g'::tsvector, 'a & s');
+select rank(' a:1 s:2 d g'::tsvector, 'a & s');
+
+insert into test_tsvector (t) values ('foo bar foo the over foo qq bar');
+select * from stat('select a from test_tsvector') order by ndoc desc, nentry desc, word;
+
+select reset_tsearch();
+select to_tsquery('default', 'skies & books');
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea&thousand&years'));
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('granite&sea'));
+
+select rank_cd(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea'));
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea&thousand&years'));
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('granite&sea'));
+
+select get_covers(to_tsvector('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+'), to_tsquery('sea'));
+
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('sea&thousand&years'));
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('granite&sea'));
+select headline('Erosion It took the sea a thousand years,
+A thousand years to trace
+The granite features of this cliff
+In crag and scarp and base.
+It took the sea an hour one night
+An hour of storm to place
+The sculpture of these granite seams,
+Upon a woman s face. E.  J.  Pratt  (1882 1964)
+', to_tsquery('sea'));
+
+--check debug
+select * from ts_debug('Tsearch module for PostgreSQL 7.3.3');
diff --git a/contrib/tsearch2/wordparser/Makefile b/contrib/tsearch2/wordparser/Makefile
new file mode 100644 (file)
index 0000000..1cf16c1
--- /dev/null
@@ -0,0 +1,27 @@
+# $Header$
+
+subdir = contrib/tsearch2/wordparser
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+
+PG_CPPFLAGS = -I$(srcdir)/..
+override CFLAGS += $(CFLAGS_SL)
+
+SUBOBJS =  parser.o deflex.o
+
+all: SUBSYS.o
+
+parser.c: parser.l
+ifdef FLEX
+       $(FLEX) $(FLEXFLAGS) -8 -Ptsearch2_yy -o'$@' $<
+else
+       @$(missing) flex $< $@
+endif
+
+SUBSYS.o: $(SUBOBJS)
+       $(LD) $(LDREL) $(LDOUT) $@ $^
+
+EXTRA_CLEAN = SUBSYS.o $(SUBOBJS) parser.c
+
+include $(top_srcdir)/contrib/contrib-global.mk
diff --git a/contrib/tsearch2/wordparser/parser.h b/contrib/tsearch2/wordparser/parser.h
new file mode 100644 (file)
index 0000000..1ce1874
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __PARSER_H__
+#define __PARSER_H__
+
+char      *token;
+int                    tokenlen;
+int                    tsearch2_yylex(void);
+void           start_parse_str(char *, int);
+void           end_parse(void);
+
+#endif
diff --git a/contrib/tsearch2/wordparser/parser.l b/contrib/tsearch2/wordparser/parser.l
new file mode 100644 (file)
index 0000000..23cfeda
--- /dev/null
@@ -0,0 +1,308 @@
+%{
+#include "postgres.h"
+
+#include "deflex.h"
+#include "parser.h"
+#include "common.h"
+
+/* Avoid exit() on fatal scanner errors */
+#define fprintf(file, fmt, msg)  ts_error(ERROR, fmt, msg)
+
+/* postgres allocation function */
+#define free    pfree
+#define malloc  palloc
+#define realloc repalloc
+
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup  pstrdup
+
+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 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; 
+       *tsearch2_yytext=' '; *(tsearch2_yytext+1) = '\0'; 
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return SPACE;
+}
+
+"<!--" { BEGIN INCOMMENT; }
+
+<INCOMMENT>"-->"       { 
+       BEGIN INITIAL;
+       *tsearch2_yytext=' '; *(tsearch2_yytext+1) = '\0'; 
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return SPACE;
+}
+
+
+"<"[\![:alpha:]]       { BEGIN INTAG; }
+
+"</"[[:alpha:]]        { BEGIN INTAG; }
+
+<INTAG>"\""    { BEGIN QINTAG; }
+
+<QINTAG>"\\\"" ;
+
+<QINTAG>"\""   { BEGIN INTAG; }
+
+<INTAG>">"     { 
+       BEGIN INITIAL;
+       token = tsearch2_yytext;
+       *tsearch2_yytext=' '; 
+       token = tsearch2_yytext;
+       tokenlen = 1;
+       return TAG;
+}
+
+<QINTAG,INTAG,INCOMMENT,INSCRIPT>.|\n  ;
+
+\&(quot|amp|nbsp|lt|gt)\;   {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return HTMLENTITY;
+}
+
+\&\#[0-9][0-9]?[0-9]?\; {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return HTMLENTITY;
+}
+[-_\.[:alnum:]]+@{HOSTNAME}  /* Emails */ { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return EMAIL; 
+}
+
+[+-]?[0-9]+(\.[0-9]+)?[eEdD][+-]?[0-9]+  /* float */   { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return SCIENTIFIC; 
+}
+
+[0-9]+\.[0-9]+\.[0-9\.]*[0-9] {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return VERSIONNUMBER;
+}
+
+[+-]?[0-9]+\.[0-9]+ {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return DECIMAL;
+}
+
+[+-][0-9]+ { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return SIGNEDINT; 
+}
+
+<DELIM,INITIAL>[0-9]+ { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return UNSIGNEDINT; 
+}
+
+http"://"        { 
+       BEGIN URL; 
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return HTTP;
+}
+
+ftp"://"        { 
+       BEGIN URL; 
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return HTTP;
+}
+
+<URL,INITIAL>{HOSTNAME}[/:]{URI} { 
+       BEGIN SERVER;
+       if (s) { free(s); s=NULL; } 
+       s = strdup( tsearch2_yytext ); 
+       tokenlen = tsearch2_yyleng;
+       yyless( 0 ); 
+       token = s;
+       return FURL;
+}
+
+<SERVER,URL,INITIAL>{HOSTNAME} {
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return HOST;
+}
+
+<SERVER>[/:]{URI}      {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return URI;
+}
+
+[[:alnum:]\./_-]+"/"[[:alnum:]\./_-]+ {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return FILEPATH;
+}
+
+({CYRALPHA}+-)+{CYRALPHA}+ /* composite-word */        {
+       BEGIN DELIM;
+       if (s) { free(s); s=NULL; } 
+       s = strdup( tsearch2_yytext );
+       tokenlen = tsearch2_yyleng;
+       yyless( 0 );
+       token = s;
+       return CYRHYPHENWORD;
+}
+
+([[:alpha:]]+-)+[[:alpha:]]+ /* composite-word */      {
+        BEGIN DELIM;
+       if (s) { free(s); s=NULL; } 
+       s = strdup( tsearch2_yytext );
+       tokenlen = tsearch2_yyleng;
+       yyless( 0 );
+       token = s;
+       return LATHYPHENWORD;
+}
+
+({ALNUM}+-)+{ALNUM}+ /* composite-word */      {
+       BEGIN DELIM;
+       if (s) { free(s); s=NULL; } 
+       s = strdup( tsearch2_yytext );
+       tokenlen = tsearch2_yyleng;
+       yyless( 0 );
+       token = s;
+       return HYPHENWORD;
+}
+
+<DELIM>[0-9]+\.[0-9]+\.[0-9\.]*[0-9] {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return VERSIONNUMBER;
+}
+
+<DELIM>\+?[0-9]+\.[0-9]+ {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return DECIMAL;
+}
+
+<DELIM>{CYRALPHA}+  /* one word in composite-word */   { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return CYRPARTHYPHENWORD; 
+}
+
+<DELIM>[[:alpha:]]+  /* one word in composite-word */  { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return LATPARTHYPHENWORD; 
+}
+
+<DELIM>{ALNUM}+  /* one word in composite-word */      { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return PARTHYPHENWORD; 
+}
+
+<DELIM>-  { 
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return SPACE;
+}
+
+<DELIM,SERVER,URL>.|\n /* return in basic state */     {
+       BEGIN INITIAL;
+       yyless( 0 );
+}
+
+{CYRALPHA}+ /* normal word */  { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return CYRWORD; 
+}
+
+[[:alpha:]]+ /* normal word */ { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return LATWORD; 
+}
+
+{ALNUM}+ /* normal word */     { 
+       token = tsearch2_yytext; 
+       tokenlen = tsearch2_yyleng;
+       return UWORD; 
+}
+
+[ \r\n\t]+ {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return SPACE;
+}
+
+. {
+       token = tsearch2_yytext;
+       tokenlen = tsearch2_yyleng;
+       return SPACE;
+} 
+
+%%
+
+/* clearing after parsing from string */
+void end_parse() {
+       if (s) { free(s); s=NULL; } 
+       tsearch2_yy_delete_buffer( buf );
+       buf = NULL;
+} 
+
+/* start parse from string */
+void start_parse_str(char* str, int limit) {
+       if (buf) end_parse();
+       buf = tsearch2_yy_scan_bytes( str, limit );
+       tsearch2_yy_switch_to_buffer( buf );
+       BEGIN INITIAL;
+}
+
+
+
diff --git a/doc/FAQ b/doc/FAQ
index 66d3c9bbb8a74c1fd962f5bc63ae9a3ead817ae1..c0d611066017b9a8dd844e39a5d75387e7b19715 100644 (file)
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,7 +1,7 @@
 
                 Frequently Asked Questions (FAQ) for PostgreSQL
                                        
-   Last updated: Fri Jul 25 18:07:30 EDT 2003
+   Last updated: Fri Sep 5 12:42:57 EDT 2003
    
    Current maintainer: Bruce Momjian ([email protected])
    
    
    A native port to MS Win NT/2000/XP is currently being worked on. For
    more details on the current status of PostgreSQL on Windows see
-   http://techdocs.postgresql.org/guides/Windows.
+   http://techdocs.postgresql.org/guides/Windows and
+   http://candle.pha.pa.us/main/writings/pgsql/win32.html.
    
    There is also a Novell Netware 6 port at http://forge.novell.com.
    
@@ -916,7 +917,8 @@ BYTEA           bytea           variable-length byte array (null-byte safe)
 
    Finally, you could use the OID returned from the INSERT statement to
    look up the default value, though this is probably the least portable
-   approach. In Perl, using DBI with Edmund Mergl's DBD::Pg module, the
+   approach, and the oid value will wrap around when it reaches 4
+   billion. In Perl, using DBI with Edmund Mergl's DBD::Pg module, the
    oid value is made available via $sth->{pg_oid_status} after
    $sth->execute().
    
index 6d3aa8e75f6a2fac90041a8dc188ba73af7d2682..32cb546415261acc6ca36769d28571b8dd8d3e76 100644 (file)
@@ -5,8 +5,8 @@
    
    Deutsche Ãœbersetzung von Ian Barwick ([email protected]).
    
-   Letzte Aktualisierung der deutschen Ãœbersetzung: Di., den 22.07.2003,
-   16:20 CET
+   Letzte Aktualisierung der deutschen Ãœbersetzung: Di., den 02.09.2003,
+   10:00 CET
    
    Die aktuellste Version dieses Dokuments liegt auf der PostgreSQL
    Website:
@@ -1063,9 +1063,12 @@ BYTEA         bytea           Bytearray mit variabler L
 
    Schließlich besteht noch die Möglichkeit, den von einer
    INSERT-Anweisung zurückgelieferten OID-Wert als einmaligen Wert zu
-   verwenden. In Perl mit dem DBD::Pg-Modul von Edmund Mergl wird der
-   OID-Wert nach einem $sth->excute() Ã¼ber $sth->{pg_oid_status}
-   zurückgeliefert.
+   verwenden. Dieser Ansatz ist allerdings PostgreSQL-spezifisch;
+   außerdem wird nach ca. 4 Milliarden Einträgen der OID-Wert wieder auf
+   eine kleine Zahl gesetzt, ist also nicht garantiert einmalig.
+   
+   In Perl mit dem DBD::Pg-Modul wird der OID-Wert nach einem
+   $sth->excute() Ã¼ber $sth->{pg_oid_status} zurückgeliefert.
    
     4.15.3) Führen currval() und nextval() zu einer Race-Condition mit anderen
     Nutzern?
@@ -1278,15 +1281,21 @@ BYTEA         bytea           Bytearray mit variabler L
     4.28) Welche Möglichkeiten zur Verschlüsselung gibt es?
     
      * contrib/pgcrypto enthält diverse Funktionen für die Benützung mit
-       SQL-Abfragen;
-     * die einzige Möglichkeit, Kommunikationen zwischen Client und
-       Server zu verschlüsseln, ist durch die Anwendung von hostssl in
-       pg_hba.conf;
+       SQL-Abfragen.
+     * Um Verbindungen zwischen dem Server und Client-Anwendungen zu
+       verschlüsseln, muss in der Server-Konfigurationsdatei
+       postgresql.conf die ssl-Option auf true (Voreinstellung: false)
+       gesetzt werden und ein passender host- bzw. hostssl-Eintrag muss
+       in pg_hba.conf vorhanden sein. Zudem muss die sslmode-Einstellung
+       beim Client nicht auf disable gesetzt werden. (Bitte beachten Sie
+       auch, daß neben der eingebauten SSL-Unterstützung verschlüsselte
+       Verbindungen auch Ã¼ber externe Anwendungen wie stunnel oder ssh
+       aufgebaut werden können).
      * Die Passwörter der Datenbanknutzer werden ab Version 7.3
        automatisch verschlüsselt (in früheren Versionen muß der Parameter
        PASSWORD_ENCRYPTION in postgresql.conf explizit eingeschaltet
-       werden);
-     * der Server läuft auf einem verschlüsselten Dateisystem.
+       werden).
+     * Betrieb des Servers auf einem verschlüsselten Dateisystem.
      _________________________________________________________________
    
                             PostgreSQL erweitern
@@ -1326,10 +1335,15 @@ BYTEA         bytea           Bytearray mit variabler L
    Die englische Vorlage dieser FAQ wird ständig Ã¼berarbeitet. Daher
    liegt die Ãœbersetzung nicht immer auf dem aktuellsten Stand.
    
+   Die aktuellste Version der deutschen Ãœbersetzung befindet sich immer
+   unter http://sql-info.de/postgresql/FAQ_german.html. Diese
+   "Arbeitsversion" enthält eventuell Ã„nderungen, die noch nicht auf der
+   PostgreSQL-Website eingebunden worden sind.
+   
    Ãœber Verbesserungshinweise und Korrekturvorschläge sowie
    Verständnisfragen zum Inhalt der FAQ freue ich mich. Ich nehme auch
-   allgemeine Fragen zu PostgreSQL gerne entgegen, kann aber leider keine
-   zeitige Antwort garantieren.
+   allgemeine Fragen zu PostgreSQL gerne entgegen, verweise jedoch auf
+   die Mailing-Listen als schnelle und zuverlässige Anlaufstellen.
    
    Diese Ãœbersetzung basiert teilweise auf einer früheren Ãœbersetzung von
    Karsten Schulz ([email protected]).
index 3db0d918913a903e5ea65a14bb935970b3174ab8..89d5681dfb4bcf3c2d21c31f8574b22db4c2e307 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,6 +1,6 @@
 TODO list for PostgreSQL
 ========================
-Last updated:          Tue Aug 12 18:04:15 EDT 2003
+Last updated:          Fri Sep  5 15:52:01 EDT 2003
 
 Current maintainer:    Bruce Momjian ([email protected])
 
@@ -52,7 +52,7 @@ Administration
 * Allow configuration files to be specified in a different directory
 * -Add start time to pg_stat_activity
 * Allow limits on per-db/user connections
-* Have standalone backend read postgresql.conf
+* -Have standalone backend read postgresql.conf (Tom)
 * Add group object ownership, so groups can rename/drop/grant on objects,
   so we can implement roles
 * Add the concept of dataspaces/tablespaces [tablespaces]
@@ -62,6 +62,8 @@ Administration
 * Allow server log information to be output as INSERT statements
 * Prevent default re-use of sysids for dropped users and groups
 * Prevent dropping user that still owns objects, or auto-drop the objects
+* Allow pooled connections to query prepared queries
+* Allow pooled connections to close all open WITH HOLD cursors
 
 
 
@@ -88,6 +90,10 @@ Data Types
   from making invalid dates valid
 * -Prevent month/day swapping of ISO dates to make invalid dates valid
 * Have initdb set DateStyle based on locale?
+* Add pg_get_acldef(), pg_get_typedefault(), and pg_get_attrdef()
+* Add ALTER DOMAIN, AGGREGATE, CONVERSION, SEQUENCE ... OWNER TO
+* Allow to_char to print localized month names (Karel)
+
 
 * ARRAYS
        o Allow nulls in arrays
@@ -117,6 +123,8 @@ Multi-Language Support
 * Prevent mismatch of frontend/backend encodings from converting bytea
   data from being interpreted as encoded strings
 * -Remove Cyrillic recode support
+* Fix upper()/lower() to work for multibyte encodings
+
 
  
 Views / Rules
@@ -142,7 +150,7 @@ Indexes
   INSERT INTO inherit_table (unique_index_col) VALUES (dup) should fail
   [inheritance]
 * Add UNIQUE capability to non-btree indexes
-* Add btree index support for reltime, tinterval, regproc
+* -Add btree index support for reltime, tinterval, regproc (Tom)
 * Add rtree index support for line, lseg, path, point
 * -Certain indexes will not shrink, e.g. indexes on ever-increasing
   columns and indexes with many duplicate keys
@@ -160,7 +168,7 @@ Indexes
   float4, numeric/decimal too [optimizer]
 * Add FILLFACTOR to btree index creation
 * Add concurrency to GIST
-* Improve concurrency of hash indexes (Neil)
+* -Improve concurrency of hash indexes (Tom)
 * Allow a single index to index multiple tables (for inheritance and subtables)
 
 
@@ -188,6 +196,8 @@ Commands
 * -Have SELECT '13 minutes'::interval display zero seconds in ISO datestyle
 * Prevent COMMENT ON DATABASE from using a database name
 * Add GUC variable to prevent waiting on locks
+* Allow TRUNCATE ... CASCADE/RESTRICT
+* Allow PREPARE of cursors
 
 
 * ALTER
@@ -204,6 +214,7 @@ Commands
        o Allow ALTER TABLE to modify column lengths and change to binary
          compatible types
        o Add ALTER DATABASE ... OWNER TO newowner
+       o Allow ALTER TABLE ... ALTER CONSTRAINT ... RENAME
 
 * CLUSTER
        o Automatically maintain clustering on a table
@@ -267,7 +278,7 @@ Clients
 * -Allow psql to show transaction status if backend protocol changes made
 * -Add schema, cast, and conversion backslash commands to psql (Christopher)
 * -Allow pg_dump to dump a specific schema (Neil Conway)
-* Allow psql to do table completion for SELECT * FROM schema_part and
+* -Allow psql to do table completion for SELECT * FROM schema_part and
   table completion for SELECT * FROM schema_name.
 * Add XML capability to pg_dump and COPY, when backend XML capability
 * -Allow SSL-enabled clients to turn off SSL transfers
@@ -276,6 +287,7 @@ Clients
 * Allow psql \du to show groups, and add \dg for groups
 * Allow clients to query WITH HOLD cursors and prepared statements
 * Prevent unneeded quoting in psql \d output using fmtId()
+* Add a libpq function to support Parse/DescribeStatement capability
 
 
 * JDBC
@@ -326,7 +338,8 @@ Referential Integrity
 * Support triggers on columns (Neil)
 * Have AFTER triggers execute after the appropriate SQL statement in a 
   function, not at the end of the function
-
+* Print table names with constraint names in error messages, or make constraint
+  names unique within a schema
 
 Dependency Checking
 ===================
@@ -381,6 +394,8 @@ Vacuum
 * Provide automatic running of vacuum in the background in backend
   rather than in /contrib [vacuum]
 * Allow free space map to be auto-sized or warn when it is too small
+* Maintain a map of recently-expired of pages so vacuum can reclaim
+  free space without a sequential scan
 
 
 Locking
index 641a3de6ea2c9b82cc74eedb2007c6494433d448..2983f0519d38c9c930da10e63716871ee480b255 100644 (file)
@@ -10,7 +10,7 @@
   alink="#0000ff">
     <H1>Frequently Asked Questions (FAQ) for PostgreSQL</H1>
 
-    <P>Last updated: Fri Jul 25 18:07:30 EDT 2003</P>
+    <P>Last updated: Fri Sep  5 12:42:57 EDT 2003</P>
 
     <P>Current maintainer: Bruce Momjian (<A href=
     "mailto:[email protected]">[email protected]</A>)<BR>
     <p>A native port to MS Win NT/2000/XP is currently being worked
     on. For more details on the current status of PostgreSQL on Windows see
     <a href="http://techdocs.postgresql.org/guides/Windows">
-    http://techdocs.postgresql.org/guides/Windows</a>.</p>
+    http://techdocs.postgresql.org/guides/Windows</a> and
+    <a href="http://candle.pha.pa.us/main/writings/pgsql/win32.html">
+    http://candle.pha.pa.us/main/writings/pgsql/win32.html</a>.</p>
 
     <p>There is also a Novell Netware 6 port at
     <a href="http://forge.novell.com">http://forge.novell.com</a>.</p>
@@ -1152,7 +1154,8 @@ BYTEA           bytea           variable-length byte array (null-byte safe)
 
     Finally, you could use the <A href="#4.16"><SMALL>OID</SMALL></A>
     returned from the <SMALL>INSERT</SMALL> statement to look up the
-    default value, though this is probably the least portable approach.
+    default value, though this is probably the least portable approach,
+    and the oid value will wrap around when it reaches 4 billion.
     In Perl, using DBI with Edmund Mergl's DBD::Pg module, the oid
     value is made available via <I>$sth-&gt;{pg_oid_status}</I> after
     <I>$sth-&gt;execute()</I>.
index 60752bcb5b2ab1fd64a132710b71ba48908f9918..5042cdfdca979c2b1d7eb3c06052ebee429f5926 100644 (file)
@@ -14,7 +14,7 @@ href="mailto:[email protected]">[email protected]</a>).</p>
 
     <p>Deutsche Ãœbersetzung von Ian Barwick (<a href="mailto:[email protected]">[email protected]</a>).</p>
 
-    <p>Letzte Aktualisierung der deutschen Ãœbersetzung: Di., den 22.07.2003, 16:20 CET</p>
+    <p>Letzte Aktualisierung der deutschen Ãœbersetzung: Di., den 02.09.2003, 10:00 CET</p>
 
     <p>Die aktuellste Version dieses Dokuments liegt auf der PostgreSQL Website:</p>
     <ul>
@@ -1060,8 +1060,12 @@ BYTEA         bytea           Bytearray mit variabler L
     new_id = output of execute("SELECT currval('person_id_seq')");
 </pre>
     <p>Schließlich besteht noch die Möglichkeit, den von einer <small>INSERT</small>-Anweisung
-    zurückgelieferten <small>OID</small>-Wert als einmaligen Wert zu verwenden.
-    In Perl mit dem <em>DBD::Pg</em>-Modul von Edmund Mergl wird der OID-Wert nach einem
+    zurückgelieferten <a href="#4.16"><small>OID</small></a>-Wert als einmaligen Wert zu verwenden.
+    Dieser Ansatz ist allerdings PostgreSQL-spezifisch; außerdem wird nach 
+    ca. 4 Milliarden Einträgen der <small>OID</small>-Wert wieder auf eine kleine Zahl
+    gesetzt, ist also nicht garantiert einmalig.</p>
+
+    <p>In Perl mit dem <em>DBD::Pg</em>-Modul wird der OID-Wert nach einem
     <em>$sth->excute()</em> Ã¼ber <em>$sth->{pg_oid_status}</em> zurückgeliefert.</p>
 
     <h4><a name="4.15.3">4.15.3</a>) Führen <em>currval()</em> und <em>nextval()</em> zu einer Race-Condition mit anderen
@@ -1285,13 +1289,21 @@ BYTEA         bytea           Bytearray mit variabler L
 
     <ul>
     <li><em>contrib/pgcrypto</em> enthält diverse Funktionen für die Benützung mit
-      SQL-Abfragen;</li>
-    <li>die einzige Möglichkeit, Kommunikationen zwischen Client und Server
-      zu verschlüsseln, ist durch die Anwendung von <em>hostssl</em> in <em>pg_hba.conf</em>;</li>
+      SQL-Abfragen.</li>
+
+    <li>Um Verbindungen zwischen dem Server und Client-Anwendungen zu
+      verschlüsseln, muss in der Server-Konfigurationsdatei <em>postgresql.conf</em>
+      die <em>ssl</em>-Option auf <em>true</em> (Voreinstellung: <em>false</em>) gesetzt werden
+      und ein passender <em>host</em>- bzw. <em>hostssl</em>-Eintrag muss in 
+      <em>pg_hba.conf</em> vorhanden sein. Zudem muss die <em>sslmode</em>-Einstellung
+      beim Client nicht auf <em>disable</em> gesetzt werden. (Bitte beachten Sie auch,
+      daß neben der eingebauten SSL-Unterstützung verschlüsselte Verbindungen 
+      auch Ã¼ber externe Anwendungen wie <em>stunnel</em> oder <em>ssh</em> aufgebaut werden können).</li>
+
     <li>Die Passwörter der Datenbanknutzer werden ab Version 7.3 automatisch
       verschlüsselt (in früheren Versionen muß der Parameter <em>PASSWORD_ENCRYPTION</em>
-      in <em>postgresql.conf</em> explizit eingeschaltet werden);</li>
-    <li>der Server läuft auf einem verschlüsselten Dateisystem.</li>
+      in <em>postgresql.conf</em> explizit eingeschaltet werden).</li>
+    <li>Betrieb des Servers auf einem verschlüsselten Dateisystem.</li>
     </ul>
 
     <hr />
@@ -1333,9 +1345,15 @@ BYTEA         bytea           Bytearray mit variabler L
     <p>Die englische Vorlage dieser FAQ wird ständig Ã¼berarbeitet. Daher liegt
     die Ãœbersetzung nicht immer auf dem aktuellsten Stand.</p>
 
+    <p>Die aktuellste Version der deutschen Ãœbersetzung befindet sich immer unter
+    <a href="http://sql-info.de/postgresql/FAQ_german.html">http://sql-info.de/postgresql/FAQ_german.html</a>.
+    Diese "Arbeitsversion" enthält eventuell Ã„nderungen, die noch nicht auf der 
+    PostgreSQL-Website eingebunden worden sind.</p>
+
     <p>Über Verbesserungshinweise und Korrekturvorschläge sowie Verständnisfragen
     zum Inhalt der FAQ freue ich mich. Ich nehme auch allgemeine Fragen zu PostgreSQL gerne
-    entgegen, kann aber leider keine zeitige Antwort garantieren.</p>
+    entgegen, verweise jedoch auf die Mailing-Listen als schnelle und zuverlässige
+    Anlaufstellen.</p>
 
     <p>Diese Ãœbersetzung basiert teilweise auf einer früheren Ãœbersetzung von Karsten
     Schulz (<a href="mailto:[email protected]">[email protected]</a>).</p>
index 0d1aa634f9d03e702eb90bd33c08a8fbd6aebaff..42d33f702fb9aa2b9239c68aa68e4deeb65bf887 100644 (file)
@@ -48,7 +48,7 @@ endif
 
 # Enable draft mode during development
 ifneq (,$(findstring devel, $(VERSION)))
-JADEFLAGS += -V draft-mode
+override JADEFLAGS += -V draft-mode
 endif
 
 
@@ -82,7 +82,7 @@ html: postgres.sgml $(ALLSGML) stylesheet.dsl
        $(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -i output-html -t sgml $<
 
 
-COLLATEINDEX := $(PERL) $(COLLATEINDEX) -f -g
+COLLATEINDEX := LC_ALL=C $(PERL) $(COLLATEINDEX) -f -g
 
 ifeq (,$(wildcard HTML.index))
 bookindex.sgml:
index 2cb759b614d9c91d8afc364be38215c1b11aae52..8f674000288a704b41fb5738cfba1416044c7127 100644 (file)
@@ -142,7 +142,7 @@ ERROR:  &lt;unnamed&gt; referential integrity violation - key referenced from we
    <title>Transactions</title>
 
    <indexterm zone="tutorial-transactions">
-    <primary>transactions</primary>
+    <primary>transaction</primary>
    </indexterm>
 
    <para>
index 8f6638a1322117e98eb3417cdde435d32f447e5e..1ebd01544654c0e8973248dab925ca3b9f668ae9 100644 (file)
@@ -4,7 +4,7 @@
  <title>Arrays</title>
 
  <indexterm>
-  <primary>arrays</primary>
+  <primary>array</primary>
  </indexterm>
 
  <para>
@@ -162,7 +162,6 @@ ERROR:  multidimensional arrays must have array expressions with matching dimens
   expression syntax is discussed in more detail in <xref
   linkend="sql-syntax-array-constructors">.
  </para>
-
  </sect2>
 
  <sect2>
@@ -326,9 +325,9 @@ UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
   <literal>||</literal>.
 <programlisting>
 SELECT ARRAY[1,2] || ARRAY[3,4];
  ?column?
----------------
- {{1,2},{3,4}}
+ ?column?
+-----------
+ {1,2,3,4}
 (1 row)
 
 SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]];
@@ -337,27 +336,68 @@ SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]];
  {{5,6},{1,2},{3,4}}
 (1 row)
 </programlisting>
+ </para>
 
+ <para>
   The concatenation operator allows a single element to be pushed on to the
   beginning or end of a one-dimensional array. It also accepts two
   <replaceable>N</>-dimensional arrays, or an <replaceable>N</>-dimensional
-  and an <replaceable>N+1</>-dimensional array. In the former case, the two
-  <replaceable>N</>-dimension arrays become outer elements of an
-  <replaceable>N+1</>-dimensional array. In the latter, the
-  <replaceable>N</>-dimensional array is added as either the first or last
-  outer element of the <replaceable>N+1</>-dimensional array.
-
-  When extending an array by concatenation, the subscripts of its existing
-  elements are preserved. For example, when pushing
-  onto the beginning of an array with one-based subscripts, the resulting
-  array has zero-based subscripts:
+  and an <replaceable>N+1</>-dimensional array.
+ </para>
 
+ <para>
+  When a single element is pushed on to the beginning of a one-dimensional
+  array, the result is an array with a lower bound subscript equal to
+  the righthand operand's lower bound subscript, minus one. When a single
+  element is pushed on to the end of a one-dimensional array, the result is
+  an array retaining the lower bound of the lefthand operand. For example:
 <programlisting>
 SELECT array_dims(1 || ARRAY[2,3]);
  array_dims
 ------------
  [0:2]
 (1 row)
+
+SELECT array_dims(ARRAY[1,2] || 3);
+ array_dims
+------------
+ [1:3]
+(1 row)
+</programlisting>
+ </para>
+
+ <para>
+  When two arrays with an equal number of dimensions are concatenated, the
+  result retains the lower bound subscript of the lefthand operand's outer
+  dimension. The result is an array comprising every element of the lefthand
+  operand followed by every element of the righthand operand. For example:
+<programlisting>
+SELECT array_dims(ARRAY[1,2] || ARRAY[3,4,5]);
+ array_dims
+------------
+ [1:5]
+(1 row)
+
+SELECT array_dims(ARRAY[[1,2],[3,4]] || ARRAY[[5,6],[7,8],[9,0]]);
+ array_dims
+------------
+ [1:5][1:2]
+(1 row)
+</programlisting>
+ </para>
+
+ <para>
+  When an <replaceable>N</>-dimensional array is pushed on to the beginning
+  or end of an <replaceable>N+1</>-dimensional array, the result is
+  analogous to the element-array case above. Each <replaceable>N</>-dimensional
+  sub-array is essentially an element of the <replaceable>N+1</>-dimensional
+  array's outer dimension. For example:
+<programlisting>
+SELECT array_dims(ARRAY[1,2] || ARRAY[[3,4],[5,6]]);
+ array_dims
+------------
+ [0:2][1:2]
+(1 row)
 </programlisting>
  </para>
 
@@ -386,9 +426,9 @@ SELECT array_append(ARRAY[1,2], 3);
 (1 row)
 
 SELECT array_cat(ARRAY[1,2], ARRAY[3,4]);
  array_cat
----------------
- {{1,2},{3,4}}
+ array_cat
+-----------
+ {1,2,3,4}
 (1 row)
 
 SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]);
index 86b36be4e952533da1e8d3738db37b33c7f4939c..31278606bd4520632f1522160e4e14b16ed0e499 100644 (file)
@@ -153,6 +153,12 @@ pg_dump -h <replaceable>host1</> <replaceable>dbname</> | psql -h <replaceable>h
     </para>
    </important>
 
+   <tip>
+    <para>
+    Restore performance can be improved by increasing <literal>SORT_MEM</>
+    (see <xref linkend="runtime-config-resource-memory">).
+    </para>
+   </tip>
   </sect2>
 
   <sect2 id="backup-dump-all">
@@ -279,13 +285,15 @@ pg_dump -Fc <replaceable class="parameter">dbname</replaceable> > <replaceable c
    </para>
 
    <para>
-    For reasons of backward compatibility, <application>pg_dump</> does
-    not dump large objects by default. To dump large objects you must use 
-    either the custom or the TAR output format, and use the <option>-b</> option in 
-    <application>pg_dump</>. See the reference pages for details.
-    The directory <filename>contrib/pg_dumplo</> of the
-    <productname>PostgreSQL</> source tree also contains a program that can
-    dump large objects.
+    For reasons of backward compatibility, <application>pg_dump</>
+    does not dump large objects by default.<indexterm><primary>large
+    object</primary><secondary>backup</secondary></indexterm> To dump
+    large objects you must use either the custom or the TAR output
+    format, and use the <option>-b</> option in
+    <application>pg_dump</>. See the reference pages for details.  The
+    directory <filename>contrib/pg_dumplo</> of the
+    <productname>PostgreSQL</> source tree also contains a program
+    that can dump large objects.
    </para>
 
    <para>
@@ -365,7 +373,15 @@ tar -cf backup.tar /usr/local/pgsql/data
 
  <sect1 id="migration">
   <title>Migration between releases</title>
-  <indexterm zone="migration"><primary>upgrading</></>
+
+  <indexterm zone="migration">
+   <primary>upgrading</primary>
+  </indexterm>
+
+  <indexterm zone="migration">
+   <primary>version</primary>
+   <secondary>compatibility</secondary>
+  </indexterm>
 
   <para>
    As a general rule, the internal data storage format is subject to
index fd4416368a3cca9c4cb6e33e26d2e8d1c4feee2e..5287873db7db529227a3ca81a35e112006571dc4 100644 (file)
@@ -197,7 +197,7 @@ initdb --locale=sv_SE
      <listitem>
       <para>
        Sort order in queries using <command>ORDER BY</>
-       <indexterm><primary>ORDER BY</></>
+       <indexterm><primary>ORDER BY</><secondary>and locales</></indexterm>
       </para>
      </listitem>
 
index c834a4351e372d6b493a2e8e9cb9aa0db1ccf0b5..274fd0d08ab5361a56eba0efbaa1d6ce6ca5376c 100644 (file)
@@ -199,13 +199,17 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
 <programlisting>
 (<replaceable>actual-IP-address</replaceable> xor <replaceable>IP-address-field</replaceable>) and <replaceable>IP-mask-field</replaceable>
 </programlisting>
-       must be zero for the record to match.  (Of course IP addresses
-       can be spoofed but this consideration is beyond the scope of
-       <productname>PostgreSQL</productname>.) If you machine supports
-       IPv6, the default <filename>pg_hba.conf</> file will have an
-       IPv6 entry for <literal>localhost</>. You can add your own IPv6
-       entries to the file. IPv6 entries are used only for IPv6
-       connections.
+       must be zero for the record to match.
+      </para>
+
+      <para>
+       An IP address given in IPv4 format will match IPv6 connections that
+       have the corresponding address, for example <literal>127.0.0.1</>
+       will match the IPv6 address <literal>::ffff:127.0.0.1</>.  An entry
+       given in IPv6 format will match only IPv6 connections, even if the
+       represented address is in the IPv4-in-IPv6 range.  Note that entries
+       in IPv6 format will be rejected if the system's C library does not have
+       support for IPv6 addresses.
       </para>
 
       <para>
@@ -219,9 +223,10 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
      <term><replaceable>CIDR-mask</replaceable></term>
      <listitem>
       <para>
-        This is an integer specifying the number of significant bits 
-        to set in the mask, and is an alternative to using the 
-        <replaceable>IP-mask</replaceable> notation. The number must
+        This field may be used as an alternative to the 
+        <replaceable>IP-mask</replaceable> notation.  It is an
+       integer specifying the number of high-order bits 
+        to set in the mask.  The number must
         be between 0 and 32 (in the case of an IPv4 address) or 128
         (in the case of an IPv6 address) inclusive. 0 will match any
         address, while 32/128 will match only the exact host specified.
@@ -451,6 +456,11 @@ local   all         all                                             trust
 # TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
 host    all         all         127.0.0.1         255.255.255.255   trust     
 
+# The same as the last line but using a CIDR mask
+#
+# TYPE  DATABASE    USER        IP-ADDRESS/CIDR-mask  METHOD
+host    all         all         127.0.0.1/32          trust     
+
 # Allow any user from any host with IP address 192.168.93.x to connect
 # to database "template1" as the same user name that ident reports for
 # the connection (typically the Unix user name).
@@ -458,6 +468,11 @@ host    all         all         127.0.0.1         255.255.255.255   trust
 # TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
 host    template1   all         192.168.93.0      255.255.255.0     ident sameuser
 
+# The same as the last line but using a CIDR mask
+#
+# TYPE  DATABASE    USER        IP-ADDRESS/CIDR-mask  METHOD
+host    template1   all         192.168.93.0/24       ident sameuser
+
 # Allow a user from host 192.168.12.10 to connect to database
 # "template1" if the user's password is correctly supplied.
 # 
@@ -566,6 +581,7 @@ local   db1,db2,@demodbs  all                                       md5
    </indexterm>
    <indexterm>
     <primary>password</primary>
+    <secondary>authentication</secondary>
    </indexterm>
 
    <para>
@@ -610,16 +626,21 @@ local   db1,db2,@demodbs  all                                       md5
 
    <para>
     <productname>Kerberos</productname> is an industry-standard secure
-    authentication system suitable for distributed computing over a
-    public network. A description of the
-    <productname>Kerberos</productname> system is far beyond the scope
-    of this document; in all generality it can be quite complex (yet
-    powerful). The <ulink
+    authentication system suitable for distributed computing over a public
+    network. A description of the <productname>Kerberos</productname> system
+    is far beyond the scope of this document; in all generality it can be
+    quite complex (yet powerful). The <ulink
     url="http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html">Kerberos
-    <acronym>FAQ</></ulink> or <ulink
-    url="ftp://athena-dist.mit.edu">MIT Project Athena</ulink> can be
-    a good starting point for exploration. Several sources for
-    <productname>Kerberos</> distributions exist.
+    <acronym>FAQ</></ulink> or <ulink url="ftp://athena-dist.mit.edu">MIT
+    Project Athena</ulink> can be a good starting point for exploration.
+    Several sources for <productname>Kerberos</> distributions exist.
+   </para>
+
+   <para>
+    While <productname>PostgreSQL</> supports both Kerberos 4 and 
+    Kerberos 5, only Kerberos 5 is recommended.  Kerberos 4 is
+    considered insecure and no longer recommended for general
+    use.
    </para>
 
    <para>
@@ -850,6 +871,10 @@ omicron       bryanh            guest1
   <sect2 id="auth-pam">
    <title>PAM Authentication</title>
 
+   <indexterm zone="auth-pam">
+    <primary>PAM</primary>
+   </indexterm>
+
    <para>
     This authentication method operates similarly to
     <literal>password</literal> except that it uses PAM (Pluggable
index 367e1b5ce7ccb5141b61df75f46b05a4d5d108af..273eb556bb601065a0e1f17e9d99e5f4cdb4873d 100644 (file)
@@ -6,12 +6,12 @@ $Header$
   <title id="datatype-title">Data Types</title>
 
   <indexterm zone="datatype">
-   <primary>data types</primary>
+   <primary>data type</primary>
   </indexterm>
 
   <indexterm>
-   <primary>types</primary>
-   <see>data types</see>
+   <primary>type</primary>
+   <see>data type</see>
   </indexterm>
 
   <para>
@@ -279,68 +279,10 @@ $Header$
    <title>Numeric Types</title>
 
    <indexterm zone="datatype-numeric">
-    <primary>data types</primary>
+    <primary>data type</primary>
     <secondary>numeric</secondary>
    </indexterm>
 
-   <indexterm zone="datatype-numeric">
-    <primary>integer</primary>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>smallint</primary>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>bigint</primary>
-   </indexterm>
-
-   <indexterm>
-    <primary>int4</primary>
-    <see>integer</see>
-   </indexterm>
-
-   <indexterm>
-    <primary>int2</primary>
-    <see>smallint</see>
-   </indexterm>
-
-   <indexterm>
-    <primary>int8</primary>
-    <see>bigint</see>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>numeric (data type)</primary>
-   </indexterm>
-
-   <indexterm>
-    <primary>decimal</primary>
-    <see>numeric</see>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>real</primary>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>double precision</primary>
-   </indexterm>
-
-   <indexterm>
-    <primary>float4</primary>
-    <see>real</see>
-   </indexterm>
-
-   <indexterm>
-    <primary>float8</primary>
-    <see>double precision</see>
-   </indexterm>
-
-   <indexterm zone="datatype-numeric">
-    <primary>floating point</primary>
-   </indexterm>
-
    <para>
     Numeric types consist of two-, four-, and eight-byte integers,
     four- and eight-byte floating-point numbers, and fixed-precision
@@ -434,6 +376,33 @@ $Header$
    <sect2 id="datatype-int">
     <title>Integer Types</title>
 
+    <indexterm zone="datatype-int">
+     <primary>integer</primary>
+    </indexterm>
+
+    <indexterm zone="datatype-int">
+     <primary>smallint</primary>
+    </indexterm>
+
+    <indexterm zone="datatype-int">
+     <primary>bigint</primary>
+    </indexterm>
+
+    <indexterm>
+     <primary>int4</primary>
+     <see>integer</see>
+    </indexterm>
+
+    <indexterm>
+     <primary>int2</primary>
+     <see>smallint</see>
+    </indexterm>
+
+    <indexterm>
+     <primary>int8</primary>
+     <see>bigint</see>
+    </indexterm>
+
     <para>
      The types <type>smallint</type>, <type>integer</type>, and
      <type>bigint</type> store whole numbers, that is, numbers without
@@ -495,6 +464,15 @@ $Header$
    <sect2 id="datatype-numeric-decimal">
     <title>Arbitrary Precision Numbers</title>
 
+    <indexterm zone="datatype-numeric-decimal">
+     <primary>numeric (data type)</primary>
+    </indexterm>
+
+    <indexterm>
+     <primary>decimal</primary>
+     <see>numeric</see>
+    </indexterm>
+
     <para>
      The type <type>numeric</type> can store numbers with up to 1000
      digits of precision and perform calculations exactly. It is
@@ -562,6 +540,28 @@ NUMERIC
    <sect2 id="datatype-float">
     <title>Floating-Point Types</title>
 
+    <indexterm zone="datatype-float">
+     <primary>real</primary>
+    </indexterm>
+
+    <indexterm zone="datatype-float">
+     <primary>double precision</primary>
+    </indexterm>
+
+    <indexterm>
+     <primary>float4</primary>
+     <see>real</see>
+    </indexterm>
+
+    <indexterm>
+     <primary>float8</primary>
+     <see>double precision</see>
+    </indexterm>
+
+    <indexterm zone="datatype-float">
+     <primary>floating point</primary>
+    </indexterm>
+
     <para>
      The data types <type>real</type> and <type>double
      precision</type> are inexact, variable-precision numeric types.
@@ -675,7 +675,7 @@ NUMERIC
     </indexterm>
 
     <indexterm>
-     <primary>sequences</primary>
+     <primary>sequence</primary>
      <secondary>and serial type</secondary>
     </indexterm>
 
@@ -807,18 +807,33 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
    <title>Character Types</title>
 
    <indexterm zone="datatype-character">
-    <primary>character strings</primary>
+    <primary>character string</primary>
     <secondary>data types</secondary>
    </indexterm>
 
    <indexterm>
-    <primary>strings</primary>
-    <see>character strings</see>
+    <primary>string</primary>
+    <see>character string</see>
    </indexterm>
 
-   <indexterm>
+   <indexterm zone="datatype-character">
+    <primary>character</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-character">
+    <primary>character varying</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-character">
     <primary>text</primary>
-    <see>character strings</see>
+   </indexterm>
+
+   <indexterm zone="datatype-character">
+    <primary>char</primary>
+   </indexterm>
+
+   <indexterm zone="datatype-character">
+    <primary>varchar</primary>
    </indexterm>
 
     <table id="datatype-character-table">
@@ -1020,6 +1035,15 @@ SELECT b, char_length(b) FROM test2;
 
  <sect1 id="datatype-binary">
   <title>Binary Data Types</title>
+
+  <indexterm zone="datatype-binary">
+   <primary>binary data</primary>
+  </indexterm>
+
+  <indexterm zone="datatype-binary">
+   <primary>bytea</primary>
+  </indexterm>
+
    <para>
     The <type>bytea</type> data type allows storage of binary strings;
     see <xref linkend="datatype-binary-table">.
@@ -1210,6 +1234,34 @@ SELECT b, char_length(b) FROM test2;
   <sect1 id="datatype-datetime">
    <title>Date/Time Types</title>
 
+   <indexterm zone="datatype-datetime">
+    <primary>date</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>time</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>time without time zone</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>time with time zone</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>timestamp</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>timestamp with time zone</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>timestamp without time zone</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>interval</primary>
+   </indexterm>
+   <indexterm zone="datatype-datetime">
+    <primary>time span</primary>
+   </indexterm>
+
    <para>
     <productname>PostgreSQL</productname> supports the full set of
     <acronym>SQL</acronym> date and time types, shown in <xref
@@ -1387,7 +1439,6 @@ SELECT b, char_length(b) FROM test2;
 
     <indexterm>
      <primary>date</primary>
-     <secondary>data type</secondary>
     </indexterm>
  
     <para>
@@ -1461,15 +1512,12 @@ SELECT b, char_length(b) FROM test2;
 
      <indexterm>
       <primary>time</primary>
-      <secondary>data type</secondary>
      </indexterm>
      <indexterm>
       <primary>time without time zone</primary>
-      <secondary>time</secondary>
      </indexterm>
      <indexterm>
       <primary>time with time zone</primary>
-      <secondary>data type</secondary>
      </indexterm>
 
      <para>
@@ -1587,17 +1635,14 @@ SELECT b, char_length(b) FROM test2;
 
     <indexterm>
      <primary>timestamp</primary>
-     <secondary>data type</secondary>
     </indexterm>
 
     <indexterm>
      <primary>timestamp with time zone</primary>
-     <secondary>data type</secondary>
     </indexterm>
 
     <indexterm>
      <primary>timestamp without time zone</primary>
-     <secondary>data type</secondary>
     </indexterm>
 
      <para>
@@ -1797,13 +1842,13 @@ January 8 04:05:06 1999 PST
     <indexterm>
      <primary>date</primary>
      <secondary>output format</secondary>
-     <seealso>Formatting</seealso>
+     <seealso>formatting</seealso>
     </indexterm>
 
     <indexterm>
      <primary>time</primary>
      <secondary>output format</secondary>
-     <seealso>Formatting</seealso>
+     <seealso>formatting</seealso>
     </indexterm>
 
     <para>
@@ -1924,7 +1969,7 @@ January 8 04:05:06 1999 PST
     <title>Time Zones</title>
 
     <indexterm zone="datatype-timezones">
-     <primary>time zones</primary>
+     <primary>time zone</primary>
     </indexterm>
 
    <para>
@@ -2265,7 +2310,11 @@ SELECT * FROM test1 WHERE a;
     <title>Line Segments</title>
 
     <indexterm>
-     <primary>line</primary>
+     <primary>lseg</primary>
+    </indexterm>
+
+    <indexterm>
+     <primary>line segment</primary>
     </indexterm>
 
     <para>
@@ -2293,6 +2342,10 @@ SELECT * FROM test1 WHERE a;
      <primary>box (data type)</primary>
     </indexterm>
 
+    <indexterm>
+     <primary>rectangle</primary>
+    </indexterm>
+
     <para>
      Boxes are represented by pairs of points that are opposite
      corners of the box.
@@ -2431,7 +2484,7 @@ SELECT * FROM test1 WHERE a;
 
    <indexterm zone="datatype-net-types">
     <primary>network</primary>
-    <secondary>addresses</secondary>
+    <secondary>data types</secondary>
    </indexterm>
 
    <para>
@@ -2708,7 +2761,7 @@ SELECT * FROM test1 WHERE a;
    <title>Bit String Types</title>
 
    <indexterm zone="datatype-bit">
-    <primary>bit strings</primary>
+    <primary>bit string</primary>
     <secondary>data type</secondary>
    </indexterm>
 
@@ -3045,11 +3098,6 @@ SELECT * FROM test;
       </thead>
 
       <tbody>
-       <row>
-       <entry><type>record</></entry>
-       <entry>Identifies a function returning an unspecified row type.</entry>
-       </row>
-
        <row>
        <entry><type>any</></entry>
        <entry>Indicates that a function accepts any input data type whatever.</entry>
@@ -3058,23 +3106,24 @@ SELECT * FROM test;
        <row>
        <entry><type>anyarray</></entry>
        <entry>Indicates that a function accepts any array data type
-       (see <xref linkend="types-polymorphic">).</entry>
+       (see <xref linkend="extend-types-polymorphic">).</entry>
        </row>
 
        <row>
        <entry><type>anyelement</></entry>
        <entry>Indicates that a function accepts any data type
-       (see <xref linkend="types-polymorphic">).</entry>
+       (see <xref linkend="extend-types-polymorphic">).</entry>
        </row>
 
        <row>
-       <entry><type>void</></entry>
-       <entry>Indicates that a function returns no value.</entry>
+       <entry><type>cstring</></entry>
+       <entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
        </row>
 
        <row>
-       <entry><type>trigger</></entry>
-       <entry>A trigger function is declared to return <type>trigger.</></entry>
+       <entry><type>internal</></entry>
+       <entry>Indicates that a function accepts or returns a server-internal
+       data type.</entry>
        </row>
 
        <row>
@@ -3083,14 +3132,18 @@ SELECT * FROM test;
        </row>
 
        <row>
-       <entry><type>cstring</></entry>
-       <entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
+       <entry><type>record</></entry>
+       <entry>Identifies a function returning an unspecified row type.</entry>
        </row>
 
        <row>
-       <entry><type>internal</></entry>
-       <entry>Indicates that a function accepts or returns a server-internal
-       data type.</entry>
+       <entry><type>trigger</></entry>
+       <entry>A trigger function is declared to return <type>trigger.</></entry>
+       </row>
+
+       <row>
+       <entry><type>void</></entry>
+       <entry>Indicates that a function returns no value.</entry>
        </row>
 
        <row>
index a72d1e77e0ce40040e6530c2e528c6cd1a4a4548..e809913c34a338bce53560c81f232882c0fd2edb 100644 (file)
@@ -364,7 +364,8 @@ $Header$
    </para>
 
    <indexterm>
-    <primary>time zones</primary>
+    <primary>time zone</primary>
+    <secondary>abbreviations</secondary>
    </indexterm>
 
    <para>
@@ -536,18 +537,10 @@ $Header$
        <entry>+07:00</entry>
        <entry>Christmas (Island) Time</entry>
        </row>
-<!--
-       Conflicts with China Coastal Time
-       <row>
-       <entry>CCT</entry>
-       <entry>+06:30</entry>
-       <entry>Cocos Island Time</entry>
-       </row>
--->
        <row>
        <entry>MMT</entry>
        <entry>+06:30</entry>
-       <entry>Myannar Time</entry>
+       <entry>Myanmar Time</entry>
        </row>
        <row>
        <entry>ALMT</entry>
@@ -759,6 +752,21 @@ $Header$
        <entry>-01:00</entry>
        <entry>West Africa Time</entry>
        </row>
+       <row>
+       <entry>FNST</entry>
+       <entry>-01:00</entry>
+       <entry>Fernando de Noronha Summer Time</entry>
+       </row>
+       <row>
+       <entry>FNT</entry>
+       <entry>-02:00</entry>
+       <entry>Fernando de Noronha Time</entry>
+       </row>
+       <row>
+       <entry>BRST</entry>
+       <entry>-02:00</entry>
+       <entry>Brasilia Summer Time</entry>
+       </row>
        <row>
        <entry>NDT</entry>
        <entry>-02:30</entry>
@@ -774,6 +782,11 @@ $Header$
        <entry>-03:00</entry>
        <entry>(unknown)</entry>
        </row>
+       <row>
+       <entry>BRT</entry>
+       <entry>-03:00</entry>
+       <entry>Brasilia Time</entry>
+       </row>
        <row>
        <entry>NFT</entry>
        <entry>-03:30</entry>
@@ -794,11 +807,6 @@ $Header$
        <entry>-04:00</entry>
        <entry>Atlantic/Porto Acre Summer Time</entry>
        </row>
-       <row>
-       <entry>ACT</entry>
-       <entry>-05:00</entry>
-       <entry>Atlantic/Porto Acre Standard Time</entry>
-       </row>
        <row>
        <entry>EDT</entry>
        <entry>-04:00</entry>
@@ -811,6 +819,11 @@ $Header$
       <entry>GMT +4 hours</entry>
       </row>
        -->
+       <row>
+       <entry>ACT</entry>
+       <entry>-05:00</entry>
+       <entry>Atlantic/Porto Acre Standard Time</entry>
+       </row>
        <row>
        <entry>CDT</entry>
        <entry>-05:00</entry>
index 045fd388fe4a402d26f06452f0692cdceb054d11..88752b909b23871549403293fc26db7fa1b97a94 100644 (file)
  <sect1 id="ddl-basics">
   <title>Table Basics</title>
 
+  <indexterm zone="ddl-basics">
+   <primary>table</primary>
+  </indexterm>
+
+  <indexterm>
+   <primary>row</primary>
+  </indexterm>
+
+  <indexterm>
+   <primary>column</primary>
+  </indexterm>
+
   <para>
    A table in a relational database is much like a table on paper: It
    consists of rows and columns.  The number and order of the columns
    containing both date and time.
   </para>
 
+  <indexterm>
+   <primary>table</primary>
+   <secondary>creating</secondary>
+  </indexterm>
+
   <para>
    To create a table, you use the aptly named <literal>CREATE
    TABLE</literal> command.  In this command you specify at least a
@@ -114,6 +131,11 @@ CREATE TABLE products (
    highly unusual and often a questionable design.
   </para>
 
+  <indexterm>
+   <primary>table</primary>
+   <secondary>removing</secondary>
+  </indexterm>
+
   <para>
    If you no longer need a table, you can remove it using the
    <command>DROP TABLE</command> command.  For example:
@@ -156,8 +178,8 @@ DROP TABLE products;
   </para>
 
   <indexterm>
-   <primary>columns</primary>
-   <secondary>system columns</secondary>
+   <primary>column</primary>
+   <secondary>system column</secondary>
   </indexterm>
 
   <variablelist>
@@ -167,6 +189,7 @@ DROP TABLE products;
      <para>
       <indexterm>
        <primary>OID</primary>
+       <secondary>column</secondary>
       </indexterm>
       The object identifier (object ID) of a row.  This is a serial
       number that is automatically added by
@@ -182,6 +205,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>tableoid</></term>
     <listitem>
+     <indexterm>
+      <primary>tableoid</primary>
+     </indexterm>
+
      <para>
       The OID of the table containing this row.  This column is
       particularly handy for queries that select from inheritance
@@ -197,6 +224,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>xmin</></term>
     <listitem>
+     <indexterm>
+      <primary>xmin</primary>
+     </indexterm>
+
      <para>
       The identity (transaction ID) of the inserting transaction for
       this tuple.  (Note: In this context, a tuple is an individual
@@ -209,6 +240,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>cmin</></term>
     <listitem>
+     <indexterm>
+      <primary>cmin</primary>
+     </indexterm>
+
      <para>
       The command identifier (starting at zero) within the inserting
       transaction.
@@ -219,6 +254,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>xmax</></term>
     <listitem>
+     <indexterm>
+      <primary>xmax</primary>
+     </indexterm>
+
      <para>
       The identity (transaction ID) of the deleting transaction, or
       zero for an undeleted tuple.  It is possible for this column to
@@ -232,6 +271,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>cmax</></term>
     <listitem>
+     <indexterm>
+      <primary>cmax</primary>
+     </indexterm>
+
      <para>
       The command identifier within the deleting transaction, or zero.
      </para>
@@ -241,6 +284,10 @@ DROP TABLE products;
    <varlistentry>
     <term><structfield>ctid</></term>
     <listitem>
+     <indexterm>
+      <primary>ctid</primary>
+     </indexterm>
+
      <para>
       The physical location of the tuple within its table.  Note that
       although the <structfield>ctid</structfield> can be used to
@@ -292,6 +339,10 @@ DROP TABLE products;
  <sect1 id="ddl-default">
   <title>Default Values</title>
 
+  <indexterm zone="ddl-default">
+   <primary>default value</primary>
+  </indexterm>
+
   <para>
    A column can be assigned a default value.  When a new row is
    created and no values are specified for some of the columns, the
@@ -302,6 +353,7 @@ DROP TABLE products;
   </para>
 
   <para>
+   <indexterm><primary>null value</primary><secondary>default value</secondary></indexterm>
    If no default value is declared explicitly, the null value is the
    default value.  This usually makes sense because a null value can
    be thought to represent unknown data.
@@ -329,6 +381,10 @@ CREATE TABLE products (
  <sect1 id="ddl-constraints">
   <title>Constraints</title>
 
+  <indexterm zone="ddl-constraints">
+   <primary>constraint</primary>
+  </indexterm>
+
   <para>
    Data types are a way to limit the kind of data that can be stored
    in a table.  For many applications, however, the constraint they
@@ -351,6 +407,15 @@ CREATE TABLE products (
   <sect2>
    <title>Check Constraints</title>
 
+   <indexterm>
+    <primary>check constraint</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>check</secondary>
+   </indexterm>
+
    <para>
     A check constraint is the most generic constraint type.  It allows
     you to specify that the value in a certain column must satisfy an
@@ -375,6 +440,11 @@ CREATE TABLE products (
     would not make too much sense.
    </para>
 
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>name</secondary>
+   </indexterm>
+
    <para>
     You can also give the constraint a separate name.  This clarifies
     error messages and allows you to refer to the constraint when you
@@ -444,6 +514,11 @@ CREATE TABLE products (
     It's a matter of taste.
    </para>
 
+   <indexterm>
+    <primary>null value</primary>
+    <secondary sortas="check constraints">with check constraints</secondary>
+   </indexterm>
+
    <para>
     It should be noted that a check constraint is satisfied if the
     check expression evaluates to true or the null value.  Since most
@@ -457,6 +532,15 @@ CREATE TABLE products (
   <sect2>
    <title>Not-Null Constraints</title>
 
+   <indexterm>
+    <primary>not-null constraint</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>NOT NULL</secondary>
+   </indexterm>
+
    <para>
     A not-null constraint simply specifies that a column must not
     assume the null value.  A syntax example:
@@ -526,6 +610,15 @@ CREATE TABLE products (
   <sect2>
    <title>Unique Constraints</title>
 
+   <indexterm>
+    <primary>unique constraint</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>unique</secondary>
+   </indexterm>
+
    <para>
     Unique constraints ensure that the data contained in a column or a
     group of columns is unique with respect to all the rows in the
@@ -573,6 +666,11 @@ CREATE TABLE products (
 </programlisting>
    </para>
 
+   <indexterm>
+    <primary>null value</primary>
+    <secondary sortas="unique constraints">with unique constraints</secondary>
+   </indexterm>
+
    <para>
     In general, a unique constraint is violated when there are (at
     least) two rows in the table where the values of each of the
@@ -591,6 +689,15 @@ CREATE TABLE products (
   <sect2>
    <title>Primary Keys</title>
 
+   <indexterm>
+    <primary>primary key</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>primary key</secondary>
+   </indexterm>
+
    <para>
     Technically, a primary key constraint is simply a combination of a
     unique constraint and a not-null constraint.  So, the following
@@ -649,6 +756,19 @@ CREATE TABLE example (
   <sect2 id="ddl-constraints-fk">
    <title>Foreign Keys</title>
 
+   <indexterm>
+    <primary>foreign key</primary>
+   </indexterm>
+
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>foreign key</secondary>
+   </indexterm>
+
+   <indexterm>
+    <primary>referential integrity</primary>
+   </indexterm>
+
    <para>
     A foreign key constraint specifies that the values in a column (or
     a group of columns) must match the values appearing in some row
@@ -749,6 +869,16 @@ CREATE TABLE order_items (
     the last table.
    </para>
 
+   <indexterm>
+    <primary>CASCADE</primary>
+    <secondary>foreign key action</secondary>
+   </indexterm>
+
+   <indexterm>
+    <primary>RESTRICT</primary>
+    <secondary>foreign key action</secondary>
+   </indexterm>
+
    <para>
     We know that the foreign keys disallow creation of orders that
     do not relate to any products.  But what if a product is removed
@@ -998,6 +1128,11 @@ SET SQL_Inheritance TO OFF;
  <sect1 id="ddl-alter">
   <title>Modifying Tables</title>
 
+  <indexterm zone="ddl-alter">
+   <primary>table</primary>
+   <secondary>modifying</secondary>
+  </indexterm>
+
   <para>
    When you create a table and you realize that you made a mistake, or
    the requirements of the application changed, then you can drop the
@@ -1042,6 +1177,11 @@ SET SQL_Inheritance TO OFF;
   <sect2>
    <title>Adding a Column</title>
 
+   <indexterm>
+    <primary>column</primary>
+    <secondary>adding</secondary>
+   </indexterm>
+
    <para>
     To add a column, use this command:
 <programlisting>
@@ -1070,6 +1210,11 @@ ALTER TABLE products ADD COLUMN description text CHECK (description &lt;&gt; '')
   <sect2>
    <title>Removing a Column</title>
 
+   <indexterm>
+    <primary>column</primary>
+    <secondary>removing</secondary>
+   </indexterm>
+
    <para>
     To remove a column, use this command:
 <programlisting>
@@ -1081,6 +1226,11 @@ ALTER TABLE products DROP COLUMN description;
   <sect2>
    <title>Adding a Constraint</title>
 
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>adding</secondary>
+   </indexterm>
+
    <para>
     To add a constraint, the table constraint syntax is used.  For example:
 <programlisting>
@@ -1104,6 +1254,11 @@ ALTER TABLE products ALTER COLUMN product_no SET NOT NULL;
   <sect2>
    <title>Removing a Constraint</title>
 
+   <indexterm>
+    <primary>constraint</primary>
+    <secondary>removing</secondary>
+   </indexterm>
+
    <para>
     To remove a constraint you need to know its name.  If you gave it
     a name then that's easy.  Otherwise the system assigned a
@@ -1127,6 +1282,11 @@ ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;
   <sect2>
    <title>Changing the Default</title>
 
+   <indexterm>
+    <primary>default value</primary>
+    <secondary>changing</secondary>
+   </indexterm>
+
    <para>
     To set a new default for a column, use a command like this:
 <programlisting>
@@ -1146,6 +1306,11 @@ ALTER TABLE products ALTER COLUMN price DROP DEFAULT;
   <sect2>
    <title>Renaming a Column</title>
 
+   <indexterm>
+    <primary>column</primary>
+    <secondary>renaming</secondary>
+   </indexterm>
+
    <para>
     To rename a column:
 <programlisting>
@@ -1157,6 +1322,11 @@ ALTER TABLE products RENAME COLUMN product_no TO product_number;
   <sect2>
    <title>Renaming a Table</title>
 
+   <indexterm>
+    <primary>table</primary>
+    <secondary>renaming</secondary>
+   </indexterm>
+
    <para>
     To rename a table:
 <programlisting>
@@ -1169,6 +1339,15 @@ ALTER TABLE products RENAME TO items;
  <sect1 id="ddl-priv">
   <title>Privileges</title>
 
+  <indexterm zone="ddl-priv">
+   <primary>privilege</primary>
+  </indexterm>
+
+  <indexterm>
+   <primary>permission</primary>
+   <see>privilege</see>
+  </indexterm>
+
   <para>
    When you create a database object, you become its owner.  By
    default, only the owner of an object can do anything with the
@@ -1241,12 +1420,8 @@ REVOKE ALL ON accounts FROM PUBLIC;
  <sect1 id="ddl-schemas">
   <title>Schemas</title>
 
-  <indexterm>
-   <primary>schemas</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>namespaces</primary>
+  <indexterm zone="ddl-schemas">
+   <primary>schema</primary>
   </indexterm>
 
   <para>
@@ -1313,6 +1488,11 @@ REVOKE ALL ON accounts FROM PUBLIC;
   <sect2 id="ddl-schemas-create">
    <title>Creating a Schema</title>
 
+   <indexterm zone="ddl-schemas-create">
+    <primary>schema</primary>
+    <secondary>creating</secondary>
+   </indexterm>
+
    <para>
     To create a separate schema, use the command <literal>CREATE
     SCHEMA</literal>.  Give the schema a name of your choice.  For
@@ -1323,11 +1503,11 @@ CREATE SCHEMA myschema;
    </para>
 
    <indexterm>
-    <primary>qualified names</primary>
+    <primary>qualified name</primary>
    </indexterm>
 
    <indexterm>
-    <primary>names</primary>
+    <primary>name</primary>
     <secondary>qualified</secondary>
    </indexterm>
 
@@ -1359,6 +1539,11 @@ CREATE TABLE myschema.mytable (
     the following chapters.
    </para>
 
+   <indexterm>
+    <primary>schema</primary>
+    <secondary>removing</secondary>
+   </indexterm>
+
    <para>
     To drop a schema if it's empty (all objects in it have been
     dropped), use
@@ -1394,6 +1579,11 @@ CREATE SCHEMA <replaceable>schemaname</replaceable> AUTHORIZATION <replaceable>u
   <sect2 id="ddl-schemas-public">
    <title>The Public Schema</title>
 
+   <indexterm zone="ddl-schemas-public">
+    <primary>schema</primary>
+    <secondary>public</secondary>
+   </indexterm>
+
    <para>
     In the previous sections we created tables without specifying any
     schema names.  By default, such tables (and other objects) are
@@ -1417,11 +1607,11 @@ CREATE TABLE public.products ( ... );
    </indexterm>
 
    <indexterm>
-    <primary>unqualified names</primary>
+    <primary>unqualified name</primary>
    </indexterm>
 
    <indexterm>
-    <primary>names</primary>
+    <primary>name</primary>
     <secondary>unqualified</secondary>
    </indexterm>
 
@@ -1437,6 +1627,11 @@ CREATE TABLE public.products ( ... );
     in other schemas in the database.
    </para>
 
+   <indexterm>
+    <primary>schema</primary>
+    <secondary>current</secondary>
+   </indexterm>
+
    <para>
     The first schema named in the search path is called the current schema.
     Aside from being the first schema searched, it is also the schema in
@@ -1444,6 +1639,10 @@ CREATE TABLE public.products ( ... );
     command does not specify a schema name.
    </para>
 
+   <indexterm>
+    <primary>search_path</primary>
+   </indexterm>
+
    <para>
     To show the current search path, use the following command:
 <programlisting>
@@ -1523,6 +1722,11 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
   <sect2 id="ddl-schemas-priv">
    <title>Schemas and Privileges</title>
 
+   <indexterm zone="ddl-schemas-priv">
+    <primary>privilege</primary>
+    <secondary sortas="schemas">for schemas</secondary>
+   </indexterm>
+
    <para>
     By default, users cannot see the objects in schemas they do not
     own.  To allow that, the owner of the schema needs to grant the
@@ -1550,9 +1754,14 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
    </para>
   </sect2>
 
-  <sect2>
+  <sect2 id="ddl-schemas-catalog">
    <title>The System Catalog Schema</title>
 
+   <indexterm zone="ddl-schemas-catalog">
+    <primary>system catalog</primary>
+    <secondary>schema</secondary>
+   </indexterm>
+
    <para>
     In addition to <literal>public</> and user-created schemas, each
     database contains a <literal>pg_catalog</> schema, which contains
@@ -1701,6 +1910,16 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
  <sect1 id="ddl-depend">
   <title>Dependency Tracking</title>
 
+  <indexterm zone="ddl-depend">
+   <primary>CASCADE</primary>
+   <secondary sortas="DROP">with DROP</secondary>
+  </indexterm>
+
+  <indexterm zone="ddl-depend">
+   <primary>RESTRICT</primary>
+   <secondary sortas="DROP">with DROP</secondary>
+  </indexterm>
+
   <para>
    When you create complex database structures involving many tables
    with foreign key constraints, views, triggers, functions, etc. you
index 16a220f64bcbbe59ba66e74a902951250a7a26a9..e0e234215a7b8805c2bdc1a4fe2d1a8b011569b0 100644 (file)
@@ -8,9 +8,11 @@ $Header$
  <para>
   Before you are able to use your
   <productname>PostgreSQL</productname> extension functions written in
-  C, they must be compiled and linked in a special way to produce a file
-  that can be dynamically loaded by the server.  To be
-  precise, a <firstterm>shared library</firstterm> needs to be created.
+  C, they must be compiled and linked in a special way to produce a
+  file that can be dynamically loaded by the server.  To be precise, a
+  <firstterm>shared library</firstterm> needs to be
+  created.<indexterm><primary>shared library</></indexterm>
+
  </para>
 
  <para>
@@ -26,17 +28,18 @@ $Header$
  </para>
 
  <para>
-  <indexterm><primary>PIC</></>
-  Creating shared libraries is generally analogous to linking
-  executables:  first the source files are compiled into object files,
-  then the object files are linked together.  The object files need to
-  be created as <firstterm>position-independent code</firstterm>
-  (<acronym>PIC</acronym>), which conceptually means that they can be
-  placed at an arbitrary location in memory when they are loaded by the
-  executable.  (Object files intended for executables are usually not compiled
-  that way.)  The command to link a shared library contains special
-  flags to distinguish it from linking an executable. --- At least
-  this is the theory.  On some systems the practice is much uglier.
+  <indexterm><primary>PIC</></> Creating shared libraries is generally
+  analogous to linking executables: first the source files are
+  compiled into object files, then the object files are linked
+  together.  The object files need to be created as
+  <firstterm>position-independent code</firstterm>
+  (<acronym>PIC</acronym>),<indexterm><primary>PIC</></> which
+  conceptually means that they can be placed at an arbitrary location
+  in memory when they are loaded by the executable.  (Object files
+  intended for executables are usually not compiled that way.)  The
+  command to link a shared library contains special flags to
+  distinguish it from linking an executable. --- At least this is the
+  theory.  On some systems the practice is much uglier.
  </para>
 
  <para>
@@ -57,7 +60,7 @@ $Header$
   <variablelist>
    <varlistentry>
     <term><systemitem class="osname">BSD/OS</></term>
-    <indexterm><primary>BSD/OS</></>
+    <indexterm><primary>BSD/OS</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -75,7 +78,7 @@ ld -shared -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">FreeBSD</></term>
-    <indexterm><primary>FreeBSD</></>
+    <indexterm><primary>FreeBSD</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -93,7 +96,7 @@ gcc -shared -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">HP-UX</></term>
-    <indexterm><primary>HP-UX</></>
+    <indexterm><primary>HP-UX</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag of the system compiler to create
@@ -120,7 +123,7 @@ ld -b -o foo.sl foo.o
 
    <varlistentry>
     <term><systemitem class="osname">IRIX</></term>
-    <indexterm><primary>IRIX</></>
+    <indexterm><primary>IRIX</><secondary>shared library</></>
     <listitem>
      <para>
       <acronym>PIC</acronym> is the default, no special compiler
@@ -136,7 +139,7 @@ ld -shared -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">Linux</></term>
-    <indexterm><primary>Linux</></>
+    <indexterm><primary>Linux</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -155,7 +158,7 @@ cc -shared -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">MacOS X</></term>
-    <indexterm><primary>MacOS X</></>
+    <indexterm><primary>MacOS X</><secondary>shared library</></>
     <listitem>
      <para>
       Here is an example.  It assumes the developer tools are installed.
@@ -169,7 +172,7 @@ cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">NetBSD</></term>
-    <indexterm><primary>NetBSD</></>
+    <indexterm><primary>NetBSD</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -187,7 +190,7 @@ gcc -shared -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">OpenBSD</></term>
-    <indexterm><primary>OpenBSD</></>
+    <indexterm><primary>OpenBSD</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -203,7 +206,7 @@ ld -Bshareable -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">Solaris</></term>
-    <indexterm><primary>Solaris</></>
+    <indexterm><primary>Solaris</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is
@@ -227,7 +230,7 @@ gcc -G -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">Tru64 UNIX</></term>   
-    <indexterm><primary>Tru64 UNIX</></>
+    <indexterm><primary>Tru64 UNIX</><secondary>shared library</></>
     <indexterm><primary>Digital UNIX</><see>Tru64 UNIX</></>
     <listitem>
      <para>
@@ -246,7 +249,7 @@ ld -shared -expect_unresolved '*' -o foo.so foo.o
 
    <varlistentry>
     <term><systemitem class="osname">UnixWare</></term>
-    <indexterm><primary>UnixWare</></>
+    <indexterm><primary>UnixWare</><secondary>shared library</></>
     <listitem>
      <para>
       The compiler flag to create <acronym>PIC</acronym> is <option>-K
index ec6ab8f8eb54d3f015036a1fc766daa32447b5e8..8e5b490e77a2597c2bf25a4d7598835ab287464e 100644 (file)
  <sect1 id="dml-insert">
   <title>Inserting Data</title>
 
+  <indexterm zone="dml-insert">
+   <primary>inserting</primary>
+  </indexterm>
+
+  <indexterm zone="dml-insert">
+   <primary>INSERT</primary>
+  </indexterm>
+
   <para>
    When a table is created, it contains no data.  The first thing to
    do before a database can be of much use is to insert data.  Data is
@@ -98,6 +106,14 @@ INSERT INTO products DEFAULT VALUES;
  <sect1 id="dml-update">
   <title>Updating Data</title>
 
+  <indexterm zone="dml-update">
+   <primary>updating</primary>
+  </indexterm>
+
+  <indexterm zone="dml-update">
+   <primary>UPDATE</primary>
+  </indexterm>
+
   <para>
    The modification of data that is already in the database is
    referred to as updating.  You can update individual rows, all the
@@ -182,6 +198,14 @@ UPDATE mytable SET a = 5, b = 3, c = 1 WHERE a > 0;
  <sect1 id="dml-delete">
   <title>Deleting Data</title>
 
+  <indexterm zone="dml-delete">
+   <primary>deleting</primary>
+  </indexterm>
+
+  <indexterm zone="dml-delete">
+   <primary>DELETE</primary>
+  </indexterm>
+
   <para>
    So far we have explained how to add data to tables and how to
    change data.  What remains is to discuss how to remove data that is
index 0fc8623a9085be9e0cc28b7b6106f29d53b3d154..b469557d494bed350030ae81613e33dadec8856e 100644 (file)
@@ -6,6 +6,8 @@ $Header$
  <title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title>
 
  <indexterm zone="ecpg"><primary>embedded SQL</primary><secondary>in C</secondary></indexterm>
+ <indexterm zone="ecpg"><primary>C</primary></indexterm>
+ <indexterm zone="ecpg"><primary>ECPG</primary></indexterm>
 
  <para>
   This chapter describes the embedded <acronym>SQL</acronym> package
index 005147923e5b0f38f69337