diff --git a/doc/src/Makefile b/doc/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..88755599ee40bbc58e3057112fc09b1244bc3255
--- /dev/null
+++ b/doc/src/Makefile
@@ -0,0 +1,120 @@
+# Postgres documentation makefile
+# Thomas Lockhart
+
+PGDOCS= ..
+SRCDIR= ../../src
+
+HPATH=$(PGDOCS)/doc
+PPATH=$(PGDOCS)/doc
+
+#HSTYLE=/usr/lib/sgml/stylesheets/jade/docbook/html
+#PSTYLE=/usr/lib/sgml/stylesheets/jade/docbook/print
+
+HSTYLE=/home/tgl/SGML/db107.d/docbook/html
+PSTYLE=/home/tgl/SGML/db107.d/docbook/print
+
+HDSL=$(HSTYLE)/docbook.dsl
+PDSL=$(PSTYLE)/docbook.dsl
+
+#DBOPTS=-V %no-split-output% -V %no-make-index%
+
+TAR= tar
+TAREXCLUDE= --exclude=Makefile --exclude='*.sgml'
+
+# Pick up Makefile.custom from the source area
+# This is the only resource from the code source area and is optional
+
+ifneq ($(wildcard $(SRCDIR)/Makefile.custom), )
+include $(SRCDIR)/Makefile.custom
+endif
+
+TARGETS= postgres tutorial user admin programmer
+
+HTARGETS=#make this a mapping from targets
+PTARGETS=#make this a mapping from targets
+
+.PRECIOUS: postgres.html postgres.tex postgres.dvi
+.PHONY: sources clean
+
+install::
+	$(MAKE) all
+	(mv -rf *.gz ..)
+
+all:: $(SGO) $(SGP)
+
+sources::
+	($(TAR) zcf sources.tar.gz --exclude='*.htm*' --exclude='*.gz' .)
+
+user.tar.gz:
+	$(MAKE) -C sgml clean
+	$(MAKE) -C sgml user.html
+	($(TAR) zcf $@ $(TAREXCLUDE) -C sgml .)
+
+tutorial.tar.gz:
+	$(MAKE) -C sgml clean
+	$(MAKE) -C sgml tutorial.html
+	($(TAR) zcf $@ $(TAREXCLUDE) -C sgml . -C .. -C graphics clientserver.gif)
+
+clean::
+	(rm -rf *.html *.htm)
+
+distclean::
+	$(MAKE) -C sgml clean
+
+# Generic production rules
+
+# Compressed file
+
+%.gz:	%
+	(gzip -f $<)
+
+# TAR file for HTML package
+
+%.tar:	%.html # %.ps
+	(tar cf $@ $*.html index.html *.htm *.gif) # $*.ps
+	(rm -rf index.html *.htm)
+
+#	(mkdir $*)
+#	(rm -rf $*/*)
+#	(mv *.htm $*/)
+#	(cd $*/; ln -sf book01.htm index.html)
+#	(tar cf $@ $*)
+
+# HTML
+# Include some softlinks to the generic default file names
+
+%.html:	%.sgml $(HDSL)
+	(rm -rf *.htm)
+	jade $(DBOPTS) -D sgml -d $(HDSL) -t sgml $<
+	(ln -sf book01.htm index.html)
+	(ln -sf book01.htm $*.html)
+
+#	(mkdir $(HPATH)/$*)	# be sure there is somewhere to put them
+#	(rm -rf $(HPATH)/$*/*)	# remove existing files since some names may be obsolete
+#	(mv *.htm $(HPATH)/$*/)	# and copy 'em over
+#	(cd $(HPATH)/$*/; ln -sf book01.htm index.html)
+
+# RTF to allow minor editing for hardcopy
+# This is used for v6.3 docs
+
+%.rtf: %.sgml $(PDSL)
+	jade $(DBOPTS) -d $(PDSL) -t rtf $<
+
+# TeX and DVI
+
+%.tex: %.sgml $(PDSL)
+	jade $(DBOPTS) -d $(PDSL) -t tex $<
+
+%.dvi: %.tex
+	jadetex $<
+	jadetex $<
+
+# Postscript from TeX
+
+%.ps: %.dvi
+	dvips -o $@ $<
+
+# Graphics
+
+%.gif:
+	cp -p graphics/%.gif .
diff --git a/doc/src/sgml/admin.sgml b/doc/src/sgml/admin.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..de0f6a3f7a0005cb9add73ca3dd473f45ab92ecb
--- /dev/null
+++ b/doc/src/sgml/admin.sgml
@@ -0,0 +1,103 @@
+<!-- admin.sgml
+-
+- Postgres administrator's guide.
+- Derived from postgres.sgml.
+- thomas 1998-02-27
+-
+- -->
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!entity intro    SYSTEM "intro.sgml">
+
+<!entity install  SYSTEM "install.sgml">
+<!entity ports    SYSTEM "ports.sgml">
+<!entity recovery SYSTEM "recovery.sgml">
+<!entity regress  SYSTEM "regress.sgml">
+<!entity release  SYSTEM "release.sgml">
+<!entity start-ag SYSTEM "start-ag.sgml">
+
+<!entity biblio   SYSTEM "biblio.sgml">
+]>
+<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc -->
+<Book>
+
+<!-- Title information -->
+
+<Title>PostgreSQL Administrator's Guide</Title>
+<BookInfo>
+    <ReleaseInfo>Covering v6.3 for general release</ReleaseInfo>
+    <BookBiblio>
+    <AuthorGroup>
+      <CorpAuthor>The PostgreSQL Development Team</CorpAuthor>
+    </AuthorGroup>
+<!-- editor in authorgroup is not supported
+    <AuthorGroup>
+-->
+      <Editor>
+        <FirstName>Thomas</FirstName>
+        <SurName>Lockhart</SurName>
+        <Affiliation>
+          <OrgName>Caltech/JPL</OrgName>
+        </Affiliation>
+      </Editor>
+<!--
+    </AuthorGroup>
+-->
+ 
+<!--
+    <AuthorInitials>TGL</AuthorInitials>
+-->
+
+    <Date>(last updated 1998-02-23)</Date>
+    </BookBiblio>
+
+<LegalNotice>
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group.
+</Para>
+</LegalNotice>
+
+</BookInfo>
+
+<!--
+<TOC> </TOC>
+<LOT> </LOT>
+-->
+
+<!--
+<Dedication>
+<Para>
+Your name here...
+</Para>
+</Dedication>
+-->
+
+<Preface>
+<Title>Summary</Title>
+
+<Para>
+<ProductName>Postgres</ProductName>, 
+ developed originally in the UC Berkeley Computer Science Department,
+ pioneered many of the object-relational concepts
+ now becoming available in some commercial databases.
+It provides SQL92/SQL3 language support,
+ transaction integrity, and type extensibility.
+ <ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant
+ of this original Berkeley code.
+</Para>
+</Preface>
+
+&intro;
+
+&ports;
+&install;
+&start-ag;
+&recovery;
+&regress;
+&release;
+
+&biblio;
+
+<INDEX> </INDEX>
+
+</Book>
+
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..ccbb054483d850931b452a5be8ecaa26b3081c26
--- /dev/null
+++ b/doc/src/sgml/advanced.sgml
@@ -0,0 +1,304 @@
+<Chapter>
+<Title>Advanced <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> Features</Title>
+
+<Para>
+     Having covered the basics  of  using  <ProductName>Postgres</ProductName>  <Acronym>SQL</Acronym>  to
+     access your data, we will now discuss those features of
+     <ProductName>Postgres</ProductName> that distinguish  it  from  conventional  data
+     managers.   These  features  include  inheritance, time
+     travel and non-atomic  data  values  (array-  and  
+     set-valued attributes).
+     Examples   in   this  section  can  also  be  found  in
+     <FileName>advance.sql</FileName> in the tutorial directory.
+(Refer to <XRef LinkEnd="QUERY"> for how to use it.)
+</Para>
+
+<Sect1>
+<Title>Inheritance</Title>
+
+<Para>
+     Let's create two classes. The capitals  class  contains
+     state  capitals  which  are also cities. Naturally, the
+     capitals class should inherit from cities.
+     
+<ProgramListing>
+CREATE TABLE cities (
+    name            text,
+    population      float,
+    altitude        int            -- (in ft)
+);
+
+CREATE TABLE capitals (
+    state           char2
+) INHERITS (cities);
+</ProgramListing>
+
+     In this case, an  instance  of  capitals  <FirstTerm>inherits</FirstTerm>  all
+     attributes  (name,  population,  and altitude) from its
+     parent, cities.  The type  of  the  attribute  name  is
+     <Type>text</Type>,  a  native  <ProductName>Postgres</ProductName>  type  for variable length
+     ASCII strings.  The type of the attribute population is
+     <Type>float</Type>,  a  native <ProductName>Postgres</ProductName> type for double precision
+     floating point numbers.  State capitals have  an  extra
+     attribute, state, that shows their state.  In <ProductName>Postgres</ProductName>,
+     a  class  can inherit from zero or more other classes,
+     and a query can reference either  all  instances  of  a
+     class  or  all  instances  of  a  class plus all of its
+     descendants.
+<Note>
+<Para>
+The inheritance hierarchy is a  directed  acyclic graph.
+</Para>
+</Note>
+For example, the  following  query  finds
+     all  the cities that are situated at an attitude of 500ft or higher:
+     
+<ProgramListing>
+SELECT name, altitude
+    FROM cities
+    WHERE altitude &gt; 500;
+
++----------+----------+
+|name      | altitude |
++----------+----------+
+|Las Vegas | 2174     |
++----------+----------+
+|Mariposa  | 1953     |
++----------+----------+
+</ProgramListing>         
+
+<Para>
+     On the other hand, to find the  names  of  all  cities,
+     including  state capitals, that are located at an altitude 
+     over 500ft, the query is:
+
+<ProgramListing>
+SELECT c.name, c.altitude
+    FROM cities* c
+    WHERE c.altitude > 500;
+</ProgramListing>
+
+     which returns:
+     
+<ProgramListing>
++----------+----------+
+|name      | altitude |
++----------+----------+
+|Las Vegas | 2174     |
++----------+----------+
+|Mariposa  | 1953     |
++----------+----------+
+|Madison   | 845      |
++----------+----------+
+</ProgramListing>
+
+     Here the <Quote>*</Quote> after cities indicates that the query should
+     be  run over cities and all classes below cities in the
+     inheritance hierarchy.  Many of the  commands  that  we
+     have  already discussed (<Command>select</Command>, <Command>update</Command> and <Command>delete</Command>)
+     support this <Quote>*</Quote> notation, as do others, like <Command>alter</Command>.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Non-Atomic Values</Title>
+
+<Para>
+     One  of  the tenets of the relational model is that the
+     attributes of a relation are atomic.  <ProductName>Postgres</ProductName> does not
+     have  this  restriction; attributes can themselves contain 
+     sub-values that can be  accessed  from  the  query
+     language.   For example, you can create attributes that
+     are arrays of base types.
+
+<Sect2>
+<Title>Arrays</Title>
+
+<Para>
+     <ProductName>Postgres</ProductName> allows attributes of an instance to be defined
+     as  fixed-length  or  variable-length multi-dimensional
+     arrays. Arrays of any base type  or  user-defined  type
+     can  be created. To illustrate their use, we first create a 
+     class with arrays of base types.
+     
+<ProgramListing>
+CREATE TABLE SAL_EMP (
+    name            text,
+    pay_by_quarter  int4[],
+    schedule        char16[][]
+);
+</ProgramListing>
+</Para>
+
+<Para>
+     The above query will create a class named SAL_EMP  with
+     a  <FirstTerm>text</FirstTerm>  string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm>
+     (pay_by_quarter),  which  represents   the   employee's
+     salary by quarter and a two-dimensional array of <FirstTerm>char16</FirstTerm>
+     (schedule),  which  represents  the  employee's  weekly
+     schedule.   Now  we  do  some  <FirstTerm>INSERTS</FirstTerm>s; note that when
+     appending to an array, we  enclose  the  values  within
+     braces  and  separate  them  by commas.  If you know <FirstTerm>C</FirstTerm>,
+     this is not unlike the syntax for  initializing  structures.
+     
+<ProgramListing>
+INSERT INTO SAL_EMP
+    VALUES ('Bill',
+    '{10000, 10000, 10000, 10000}',
+    '{{"meeting", "lunch"}, {}}');
+
+INSERT INTO SAL_EMP
+    VALUES ('Carol',
+    '{20000, 25000, 25000, 25000}',
+    '{{"talk", "consult"}, {"meeting"}}');
+</ProgramListing>
+
+     By  default,  <ProductName>Postgres</ProductName>  uses  the "one-based" numbering
+     convention for arrays -- that is, an array  of  n  elements starts with array[1] and ends with array[n].
+     Now,  we  can  run  some queries on SAL_EMP.  First, we
+     show how to access a single element of an  array  at  a
+     time.   This query retrieves the names of the employees
+     whose pay changed in the second quarter:
+     
+<ProgramListing>
+SELECT name
+    FROM SAL_EMP
+    WHERE SAL_EMP.pay_by_quarter[1] &lt;&gt;
+    SAL_EMP.pay_by_quarter[2];
+
++------+
+|name  |
++------+
+|Carol |
++------+
+</ProgramListing>
+</Para>
+
+<Para>
+     This query retrieves  the  third  quarter  pay  of  all
+     employees:
+     
+<ProgramListing>
+SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;
+
+
++---------------+
+|pay_by_quarter |
++---------------+
+|10000          |
++---------------+
+|25000          |
++---------------+
+</ProgramListing>
+</Para>
+
+<Para>
+     We  can  also  access  arbitrary slices of an array, or
+     subarrays.  This query  retrieves  the  first  item  on
+     Bill's schedule for the first two days of the week.
+     
+<ProgramListing>
+SELECT SAL_EMP.schedule[1:2][1:1]
+    FROM SAL_EMP
+    WHERE SAL_EMP.name = 'Bill';
+
++-------------------+
+|schedule           |
++-------------------+
+|{{"meeting"},{""}} |
++-------------------+
+</ProgramListing>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Time Travel</Title>
+
+<Para>
+As of <ProductName>Postgres</ProductName> v6.2, <Emphasis>time travel is no longer supported</Emphasis>. There are
+several reasons for this: performance impact, storage size, and a pg_time file which grows
+toward infinite size in a short period of time.
+</Para>
+
+<Para>
+New features such as triggers allow one to mimic the behavior of time travel when desired, without
+incurring the overhead when it is not needed (for most users, this is most of the time).
+See examples in the <FileName>contrib</FileName> directory for more information.
+</Para>
+
+<Note>
+<Title>Time travel is deprecated</Title>
+<Para>
+The remaining text in this section is retained only until it can be rewritten in the context
+of new techniques to accomplish the same purpose. Volunteers? - thomas 1998-01-12
+</Para>
+</Note>
+
+<Para>
+     <ProductName>Postgres</ProductName> supports the notion of time travel.  This feature 
+     allows a user  to  run  historical  queries.   For
+     example,  to  find  the  current population of Mariposa
+     city, one would query:
+     
+<ProgramListing>
+SELECT * FROM cities WHERE name = 'Mariposa';
+
++---------+------------+----------+
+|name     | population | altitude |
++---------+------------+----------+
+|Mariposa | 1320       | 1953     |
++---------+------------+----------+
+</ProgramListing>
+
+     <ProductName>Postgres</ProductName> will automatically find the version  of  Mariposa's 
+     record valid at the current time.
+     One can also give a time range.  For example to see the
+     past and present populations  of  Mariposa,  one  would
+     query:
+     
+<ProgramListing>
+SELECT name, population
+    FROM cities['epoch', 'now']
+    WHERE name = 'Mariposa';
+</ProgramListing>
+
+     where  "epoch"  indicates  the  beginning of the system
+     clock.
+<Note>
+<Para>
+On UNIX systems, this is always  midnight,  January  1, 1970 GMT.
+</Para>
+</Note>
+</Para>
+
+     If  you  have  executed all of the examples so
+     far, then the above query returns:
+     
+<ProgramListing>
++---------+------------+
+|name     | population |
++---------+------------+
+|Mariposa | 1200       |
++---------+------------+
+|Mariposa | 1320       |
++---------+------------+
+</ProgramListing>
+
+<Para>
+     The default beginning of a time range is  the  earliest
+     time representable by the system and the default end is
+     the current time; thus, the above  time  range  can  be
+     abbreviated as ``[,].''
+</Para>
+
+<Sect1>
+<Title>More Advanced Features</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> has many features not touched upon in this
+tutorial introduction, which has been oriented toward newer users of <Acronym>SQL</Acronym>.
+These are discussed in more detail in both the User's and Programmer's Guides.
+
+</Chapter>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..aa83257a0b2bb348dc9651f6f86952d9c0e13630
--- /dev/null
+++ b/doc/src/sgml/arch-dev.sgml
@@ -0,0 +1,80 @@
+<Chapter>
+	<TITLE>Architecture</TITLE>
+
+<Sect1>
+<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title>
+
+<Para>
+     Before we continue, you  should  understand  the  basic
+     <ProductName>Postgres</ProductName>  system  architecture.   Understanding how the
+     parts of <ProductName>Postgres</ProductName> interact will make the  next  chapter
+     somewhat clearer.
+     In  database  jargon,  <ProductName>Postgres</ProductName> uses a simple "process  
+     per-user" client/server model.  A <ProductName>Postgres</ProductName> session 
+     consists of the following cooperating UNIX processes (programs):
+
+<ItemizedList>
+<ListItem>
+<Para>
+      	A supervisory daemon process (<Application>postmaster</Application>),
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the user's frontend application (e.g., the <Application>psql</Application> program), and
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the  one or more backend database servers (the <Application>postgres</Application> process itself).
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+     A single  <Application>postmaster</Application>  manages  a  given  collection  of
+     databases  on  a  single  host.   Such  a collection of
+     databases is called an installation or site.   Frontend
+     applications  that  wish  to  access  a  given database
+     within an installation make calls to the   library.
+     The library sends user requests over the network to the
+     <Application>postmaster</Application> (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(a)), which in turn  starts  a  new
+     backend  server  process (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(b)) 
+     
+<Figure id="ARCHDEV-CONNECTIONS">
+<Title>How a connection is established</Title>
+<Graphic Align="center" FileRef="connections.gif" Format="GIF"></Graphic>
+</Figure>
+
+     and connects the
+     frontend process to the new server (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(c)).  From
+     that  point  on,  the  frontend process and the backend
+     server communicate without intervention by the 
+     <Application>postmaster</Application>.   Hence, the <Application>postmaster</Application> is always running, waiting
+     for requests, whereas frontend  and  backend  processes
+     come  and  go.  The <FileName>libpq</FileName> library allows a single 
+     frontend to make multiple connections to backend processes.
+     However,  the  frontend  application is still a 
+     single-threaded process.  Multithreaded frontend/backend  
+     connections are not currently supported in <FileName>libpq</FileName>.
+     One  implication of this architecture is that the 
+     <Application>postmaster</Application> and the backend always run on the  same  
+     machine (the  database  server), while the frontend 
+     application may run  anywhere.   You  should  keep  this  
+     in  mind,
+     because  the  files  that  can  be accessed on a client
+     machine may not be accessible (or may only be  accessed
+     using  a  different  filename)  on  the database server
+     machine.
+     You should also be aware that the <Application>postmaster</Application> and  
+     postgres  servers  run  with  the  user-id  of the <ProductName>Postgres</ProductName>
+     "superuser."  Note that the <ProductName>Postgres</ProductName> superuser does not
+     have  to  be  a special user (e.g., a user named 
+     "postgres").  Furthermore,  the  <ProductName>Postgres</ProductName>  superuser  
+     should
+     definitely  not  be the UNIX superuser, "root"!  In any
+     case, all files relating to a database should belong to
+     this <ProductName>Postgres</ProductName> superuser.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/arch-pg.sgml b/doc/src/sgml/arch-pg.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..5a22fd36e7161797ccde9e9646eb69ea507bd79f
--- /dev/null
+++ b/doc/src/sgml/arch-pg.sgml
@@ -0,0 +1,83 @@
+<Chapter>
+	<TITLE>Architecture</TITLE>
+
+<Sect1>
+<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title>
+
+<Para>
+     Before we continue, you  should  understand  the  basic
+     <ProductName>Postgres</ProductName>  system  architecture.   Understanding how the
+     parts of <ProductName>Postgres</ProductName> interact will make the  next  chapter
+     somewhat clearer.
+     In  database  jargon,  <ProductName>Postgres</ProductName> uses a simple "process  
+     per-user" client/server model.  A <ProductName>Postgres</ProductName> session 
+     consists of the following cooperating UNIX processes (programs):
+
+<ItemizedList>
+<ListItem>
+<Para>
+      	A supervisory daemon process (<Application>postmaster</Application>),
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the user's frontend application (e.g., the <Application>psql</Application> program), and
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the  one or more backend database servers (the <Application>postgres</Application> process itself).
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+     A single  <Application>postmaster</Application>  manages  a  given  collection  of
+     databases  on  a  single  host.   Such  a collection of
+     databases is called an installation or site.   Frontend
+     applications  that  wish  to  access  a  given database
+     within an installation make calls to the   library.
+     The library sends user requests over the network to the
+     <Application>postmaster</Application>
+(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(a)), 
+which in turn  starts  a  new backend  server  process 
+(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(b)) 
+     
+<Figure Id="PGARCH-CONNECTIONS">
+<Title>How a connection is established</Title>
+<Graphic Align="center" FileRef="connections.gif" Format="GIF"></Graphic>
+</Figure>
+
+     and connects the frontend process to the new server 
+(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(c)).
+From that  point  on,  the  frontend process and the backend
+     server communicate without intervention by the 
+     <Application>postmaster</Application>.   Hence, the <Application>postmaster</Application> is always running, waiting
+     for requests, whereas frontend  and  backend  processes
+     come  and  go.  The <FileName>libpq</FileName> library allows a single 
+     frontend to make multiple connections to backend processes.
+     However,  the  frontend  application is still a 
+     single-threaded process.  Multithreaded frontend/backend  
+     connections are not currently supported in <FileName>libpq</FileName>.
+     One  implication of this architecture is that the 
+     <Application>postmaster</Application> and the backend always run on the  same  
+     machine (the  database  server), while the frontend 
+     application may run  anywhere.   You  should  keep  this  
+     in  mind,
+     because  the  files  that  can  be accessed on a client
+     machine may not be accessible (or may only be  accessed
+     using  a  different  filename)  on  the database server
+     machine.
+     You should also be aware that the <Application>postmaster</Application> and  
+     postgres  servers  run  with  the  user-id  of the <ProductName>Postgres</ProductName>
+     "superuser."  
+Note that the <ProductName>Postgres</ProductName> superuser does not
+have  to  be  a special user (e.g., a user named 
+"postgres"), although many systems are installed that way.
+Furthermore,  the  <ProductName>Postgres</ProductName>  superuser should
+     definitely  not  be the UNIX superuser, "root"!  In any
+     case, all files relating to a database should belong to
+     this <ProductName>Postgres</ProductName> superuser.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/arch.sgml b/doc/src/sgml/arch.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..b1404b353ccb117019e73cee1e8a086e2321d757
--- /dev/null
+++ b/doc/src/sgml/arch.sgml
@@ -0,0 +1,85 @@
+<Chapter>
+	<TITLE>Architecture</TITLE>
+
+<Sect1>
+<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title>
+
+<Para>
+     Before we begin, you  should  understand  the  basic
+     <ProductName>Postgres</ProductName>  system  architecture.   Understanding how the
+     parts of <ProductName>Postgres</ProductName> interact will make the  next  chapter
+     somewhat clearer.
+     In  database  jargon,  <ProductName>Postgres</ProductName> uses a simple "process  
+     per-user" client/server model.  A <ProductName>Postgres</ProductName> session 
+     consists of the following cooperating UNIX processes (programs):
+
+<ItemizedList>
+<ListItem>
+<Para>
+      	A supervisory daemon process (<Application>postmaster</Application>),
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the user's frontend application (e.g., the <Application>psql</Application> program), and
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	the  one or more backend database servers (the <Application>postgres</Application> process itself).
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+     A single  <Application>postmaster</Application>  manages  a  given  collection  of
+     databases  on  a  single  host.   Such  a collection of
+     databases is called an installation or site.   Frontend
+     applications  that  wish  to  access  a  given database
+     within an installation make calls to the   library.
+     The library sends user requests over the network to the
+     <Application>postmaster</Application> (<XRef LinkEnd="ARCH-CLIENTSERVER" EndTerm="ARCH-CLIENTSERVER">),
+     which in turn  starts  a  new backend  server  process
+     
+<Figure Id="ARCH-CLIENTSERVER">
+<Title>How a connection is established</Title>
+<Graphic Align="center" FileRef="clientserver.gif" Format="GIF"></Graphic>
+</Figure>
+
+     and connects the
+     frontend process to the new server.  From
+     that  point  on,  the  frontend process and the backend
+     server communicate without intervention by the 
+     <Application>postmaster</Application>.   Hence, the <Application>postmaster</Application> is always running, waiting
+     for requests, whereas frontend  and  backend  processes
+     come  and  go.
+
+<Para>
+  The <FileName>libpq</FileName> library allows a single 
+     frontend to make multiple connections to backend processes.
+     However,  the  frontend  application is still a 
+     single-threaded process.  Multithreaded frontend/backend  
+     connections are not currently supported in <FileName>libpq</FileName>.
+     One  implication of this architecture is that the 
+     <Application>postmaster</Application> and the backend always run on the  same  
+     machine (the  database  server), while the frontend 
+     application may run  anywhere.   You  should  keep  this  
+     in  mind,
+     because  the  files  that  can  be accessed on a client
+     machine may not be accessible (or may only be  accessed
+     using  a  different  filename)  on  the database server
+     machine.
+
+<Para>
+     You should also be aware that the <Application>postmaster</Application> and  
+     postgres  servers  run  with  the  user-id  of the <ProductName>Postgres</ProductName>
+     "superuser."  Note that the <ProductName>Postgres</ProductName> superuser does not
+     have  to  be  a special user (e.g., a user named 
+     "postgres").  Furthermore,  the  <ProductName>Postgres</ProductName>  superuser  
+     should
+     definitely  not  be the UNIX superuser ("root")!  In any
+     case, all files relating to a database should belong to
+     this <ProductName>Postgres</ProductName> superuser.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..4b73608600150f895153f8221f0372895cf7bece
--- /dev/null
+++ b/doc/src/sgml/array.sgml
@@ -0,0 +1,108 @@
+<Chapter>
+<Title>Arrays</Title>
+
+<Para>
+<Note>
+<Para>
+This must become a chapter on array behavior. Volunteers? - thomas 1998-01-12
+</Para>
+</Note>
+</Para>
+
+<Para>
+     <ProductName>Postgres</ProductName> allows attributes of an instance to be defined
+     as  fixed-length  or  variable-length multi-dimensional
+     arrays. Arrays of any base type  or  user-defined  type
+     can  be created. To illustrate their use, we first create a 
+     class with arrays of base types.
+     
+<ProgramListing>
+CREATE TABLE SAL_EMP (
+    name            text,
+    pay_by_quarter  int4[],
+    schedule        char16[][]
+);
+</ProgramListing>
+</Para>
+
+<Para>
+     The above query will create a class named SAL_EMP  with
+     a  <FirstTerm>text</FirstTerm>  string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm>
+     (pay_by_quarter),  which  represents   the   employee's
+     salary by quarter and a two-dimensional array of <FirstTerm>char16</FirstTerm>
+     (schedule),  which  represents  the  employee's  weekly
+     schedule.   Now  we  do  some  <FirstTerm>INSERTS</FirstTerm>s; note that when
+     appending to an array, we  enclose  the  values  within
+     braces  and  separate  them  by commas.  If you know <FirstTerm>C</FirstTerm>,
+     this is not unlike the syntax for  initializing  structures.
+     
+<ProgramListing>
+INSERT INTO SAL_EMP
+    VALUES ('Bill',
+    '{10000, 10000, 10000, 10000}',
+    '{{"meeting", "lunch"}, {}}');
+
+INSERT INTO SAL_EMP
+    VALUES ('Carol',
+    '{20000, 25000, 25000, 25000}',
+    '{{"talk", "consult"}, {"meeting"}}');
+</ProgramListing>
+
+     By  default,  <ProductName>Postgres</ProductName>  uses  the "one-based" numbering
+     convention for arrays -- that is, an array  of  n  elements starts with array[1] and ends with array[n].
+     Now,  we  can  run  some queries on SAL_EMP.  First, we
+     show how to access a single element of an  array  at  a
+     time.   This query retrieves the names of the employees
+     whose pay changed in the second quarter:
+     
+<ProgramListing>
+SELECT name
+    FROM SAL_EMP
+    WHERE SAL_EMP.pay_by_quarter[1] &lt;&gt;
+    SAL_EMP.pay_by_quarter[2];
+
++------+
+|name  |
++------+
+|Carol |
++------+
+</ProgramListing>
+</Para>
+
+<Para>
+     This query retrieves  the  third  quarter  pay  of  all
+     employees:
+     
+<ProgramListing>
+SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;
+
+
++---------------+
+|pay_by_quarter |
++---------------+
+|10000          |
++---------------+
+|25000          |
++---------------+
+</ProgramListing>
+</Para>
+
+<Para>
+     We  can  also  access  arbitrary slices of an array, or
+     subarrays.  This query  retrieves  the  first  item  on
+     Bill's schedule for the first two days of the week.
+     
+<ProgramListing>
+SELECT SAL_EMP.schedule[1:2][1:1]
+    FROM SAL_EMP
+    WHERE SAL_EMP.name = 'Bill';
+
++-------------------+
+|schedule           |
++-------------------+
+|{{"meeting"},{""}} |
++-------------------+
+</ProgramListing>
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/biblio.sgml b/doc/src/sgml/biblio.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..1cae84a3edd60af34d6a0f5c637cd05bf448a3c6
--- /dev/null
+++ b/doc/src/sgml/biblio.sgml
@@ -0,0 +1,504 @@
+<BIBLIOGRAPHY>
+<Title><Acronym>SQL</Acronym> References</Title>
+
+<Para>
+Selected references and readings for <Acronym>SQL</Acronym> and <ProductName>Postgres</ProductName>.
+</Para>
+
+<BIBLIODIV>
+<TITLE><Acronym>SQL</Acronym> Reference Books</TITLE>
+<PARA>Reference texts for <Acronym>SQL</Acronym> features.</PARA>
+
+<BIBLIOENTRY ID="BOWMAN93">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="BOWMAN93">
+-->
+<TITLE>The Practical <Acronym>SQL</Acronym> Handbook</TITLE>
+<SUBTITLE>Using Structured Query Language</SUBTITLE>
+<EDITION>3</EDITION>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>Judity</FIRSTNAME>
+<SURNAME>Bowman</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>Sandra</FIRSTNAME>
+<SURNAME>Emerson</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>Marcy</FIRSTNAME>
+<SURNAME>Damovsky</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<ISBN>0-201-44787-8</ISBN>
+<PUBDATE>1996</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>Addison-Wesley</PUBLISHERNAME>
+</PUBLISHER>
+<COPYRIGHT>
+<YEAR>1997</YEAR>
+<HOLDER>Addison-Wesley Longman, Inc.</HOLDER>
+</COPYRIGHT>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="DATE97">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="DATE97">
+-->
+<TITLE>A Guide to The <Acronym>SQL</Acronym> Standard</TITLE>
+<TITLEABBREV>The <Acronym>SQL</Acronym> Standard</TITLEABBREV>
+<SUBTITLE>A user's guide to the standard database language <Acronym>SQL</Acronym></SUBTITLE>
+<EDITION>4</EDITION>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>C. J.</FIRSTNAME>
+<SURNAME>Date</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>Hugh</FIRSTNAME>
+<SURNAME>Darwen</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<ISBN>0-201-96426-0</ISBN>
+<PUBDATE>1997</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>Addison-Wesley</PUBLISHERNAME>
+</PUBLISHER>
+<COPYRIGHT>
+<YEAR>1997</YEAR>
+<HOLDER>Addison-Wesley Longman, Inc.</HOLDER>
+</COPYRIGHT>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="MELT93">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="MELT93">
+-->
+<TITLE>Understanding the New <Acronym>SQL</Acronym></TITLE>
+<SUBTITLE>A complete guide</SUBTITLE>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>Jim</FIRSTNAME>
+<SURNAME>Melton</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>Alan R.</FIRSTNAME>
+<SURNAME>Simon</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<ISBN>1-55860-245-3</ISBN>
+<PUBDATE>1993</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>Morgan Kaufmann</PUBLISHERNAME>
+</PUBLISHER>
+<COPYRIGHT>
+<YEAR>1993</YEAR>
+<HOLDER>Morgan Kaufmann Publishers, Inc.</HOLDER>
+</COPYRIGHT>
+<ABSTRACT>
+<TITLE>Abstract</TITLE>
+<PARA>Accessible reference for <Acronym>SQL</Acronym> features.</PARA>
+</ABSTRACT>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+</BIBLIODIV>
+<BIBLIODIV>
+<TITLE>PostgreSQL-Specific Documentation</TITLE>
+<PARA>This section is for related documentation.</PARA>
+
+<BIBLIOENTRY ID="ADMIN-GUIDE">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="ADMIN-GUIDE">
+-->
+<TITLE>The <ProductName>PostgreSQL</ProductName> Administrator's Guide</TITLE>
+<Editor>
+<FIRSTNAME>Thomas</FIRSTNAME>
+<SURNAME>Lockhart</SURNAME>
+</Editor>
+
+<PUBDATE>1998-03-01</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="PROGRAMMERS-GUIDE">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="PROGRAMMERS-GUIDE">
+-->
+<TITLE>The <ProductName>PostgreSQL</ProductName> Programmer's Guide</TITLE>
+<Editor>
+<FIRSTNAME>Thomas</FIRSTNAME>
+<SURNAME>Lockhart</SURNAME>
+</Editor>
+
+<PUBDATE>1998-03-01</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="TUTORIAL">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="REFERENCE">
+-->
+<TITLE>The <ProductName>PostgreSQL</ProductName> Reference Manual</TITLE>
+<Editor>
+<FIRSTNAME>Thomas</FIRSTNAME>
+<SURNAME>Lockhart</SURNAME>
+</Editor>
+
+<PUBDATE>1998-03-01</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="USERS-GUIDE">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="TUTORIAL">
+-->
+<TITLE>The <ProductName>PostgreSQL</ProductName> Tutorial Introduction</TITLE>
+<Editor>
+<FIRSTNAME>Thomas</FIRSTNAME>
+<SURNAME>Lockhart</SURNAME>
+</Editor>
+
+<PUBDATE>1998-03-01</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="REFERENCE">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="USERS-GUIDE">
+-->
+<TITLE>The <ProductName>PostgreSQL</ProductName> User's Guide</TITLE>
+<Editor>
+<FIRSTNAME>Thomas</FIRSTNAME>
+<SURNAME>Lockhart</SURNAME>
+</Editor>
+
+<PUBDATE>1998-03-01</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="YU95">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="YU95">
+-->
+<TITLE>The <ProductName>Postgres95</ProductName> User Manual</TITLE>
+<TITLEABBREV>YU95</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>A.</FIRSTNAME>
+<SURNAME>Yu</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>J.</FIRSTNAME>
+<SURNAME>Chen</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<AUTHORGROUP>
+<COLLAB>
+<COLLABNAME>
+The POSTGRES Group
+</COLLABNAME>
+</COLLAB>
+</AUTHORGROUP>
+
+<PUBDATE>Sept. 5, 1995</PUBDATE>
+<PUBLISHER>
+<PUBLISHERNAME>University  of  California, Berkeley CA</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+</BIBLIODIV>
+<BIBLIODIV>
+<TITLE>Proceedings and Articles</TITLE>
+<PARA>This section is for articles and newsletters.</PARA>
+
+<BIBLIOENTRY ID="ONG90">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="ONG90">
+-->
+<TITLE>A Unified Framework for Version Modeling Using Production Rules in a Database System</TITLE>
+<TITLEABBREV>ONG90</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>L.</FIRSTNAME>
+<SURNAME>Ong</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>J.</FIRSTNAME>
+<SURNAME>Goh</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<PUBDATE>April, 1990</PUBDATE>
+<ISSN>ERL Technical Memorandum M90/33</ISSN>
+<PUBLISHER>
+<PUBLISHERNAME>University  of  California, Berkeley CA</PUBLISHERNAME>
+</PUBLISHER>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="ROWE87">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="ROWE87">
+-->
+<TITLE>The <ProductName>Postgres</ProductName> Data Model</TITLE>
+<TITLEABBREV>ROWE87</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>L.</FIRSTNAME>
+<SURNAME>Rowe</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>Sept. 1987</CONFDATES>
+<CONFTITLE>VLDB  Conference, Brighton, England</CONFTITLE>
+<CONFNUM>1987</CONFNUM>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON86">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON86">
+-->
+<TITLE>The Design of <ProductName>Postgres</ProductName></TITLE>
+<TITLEABBREV>STON86</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>L.</FIRSTNAME>
+<SURNAME>Rowe</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>May 1986</CONFDATES>
+<CONFTITLE>Conference on Management of Data, Washington DC</CONFTITLE>
+<CONFSPONSOR>ACM-SIGMOD</CONFSPONSOR>
+<CONFNUM>1986</CONFNUM>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON87a">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON87a">
+-->
+<TITLE>The Design of the <ProductName>Postgres</ProductName> Rules System</TITLE>
+<TITLEABBREV>STON87a</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>E.</FIRSTNAME>
+<SURNAME>Hanson</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>C. H.</FIRSTNAME>
+<SURNAME>Hong</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>Feb. 1987</CONFDATES>
+<CONFTITLE>Conference on Data Engineering, Los Angeles, CA</CONFTITLE>
+<CONFSPONSOR>IEEE</CONFSPONSOR>
+<CONFNUM>1987</CONFNUM>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON87b">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON87b">
+-->
+<TITLE>The <ProductName>Postgres</ProductName> Storage System</TITLE>
+<TITLEABBREV>STON87b</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>Sept. 1987</CONFDATES>
+<CONFTITLE>VLDB  Conference, Brighton, England</CONFTITLE>
+<CONFNUM>1987</CONFNUM>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON89">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON89">
+-->
+<TITLE>A Commentary on the <ProductName>Postgres</ProductName> Rules System</TITLE>
+<TITLEABBREV>STON89</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Hearst</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>S.</FIRSTNAME>
+<SURNAME>Potamianos</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>Sept. 1989</CONFDATES>
+<CONFTITLE>Record 18(3)</CONFTITLE>
+<CONFSPONSOR>SIGMOD</CONFSPONSOR>
+<CONFNUM>1987</CONFNUM>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON90a">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON90a">
+-->
+<TITLE>The Implementation of <ProductName>Postgres</ProductName></TITLE>
+<TITLEABBREV>STON90a</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>L. A.</FIRSTNAME>
+<SURNAME>Rowe</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Hirohama</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>March 1990</CONFDATES>
+<CONFTITLE>Transactions on Knowledge and Data Engineering 2(1)</CONFTITLE>
+<CONFSPONSOR>IEEE</CONFSPONSOR>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+<BIBLIOENTRY ID="STON90b">
+<!--
+<BIBLIOMISC>&dash;</BIBLIOMISC>
+
+<BOOKBIBLIO ID="STON90b">
+-->
+<TITLE>On Rules, Procedures, Caching and Views in Database Systems</TITLE>
+<TITLEABBREV>STON90b</TITLEABBREV>
+<AUTHORGROUP>
+<AUTHOR>
+<FIRSTNAME>M.</FIRSTNAME>
+<SURNAME>Stonebraker</SURNAME>
+</AUTHOR>
+<AUTHOR>
+<SURNAME>et. al.</SURNAME>
+</AUTHOR>
+</AUTHORGROUP>
+<CONFGROUP>
+<CONFDATES>June 1990</CONFDATES>
+<CONFTITLE>Conference on Management of Data</CONFTITLE>
+<CONFSPONSOR>ACM-SIGMOD</CONFSPONSOR>
+</CONFGROUP>
+<!--
+</BOOKBIBLIO>
+-->
+</BIBLIOENTRY>
+
+</BIBLIODIV>
+</BIBLIOGRAPHY>
diff --git a/doc/src/sgml/compiler.sgml b/doc/src/sgml/compiler.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..5d9c0eb07555ce5288057f95a431813c04e40aff
--- /dev/null
+++ b/doc/src/sgml/compiler.sgml
@@ -0,0 +1,73 @@
+<Chapter>
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Brian</FirstName>
+<Surname>Gallew</Surname>
+</Author>
+</AuthorGroup>
+<Date>Transcribed 1998-02-12</Date>
+</DocInfo>
+
+<Title>GCC Default Optimizations</Title>
+
+<Para>
+<Note>
+<Para>
+Contributed by <ULink url="mailto:geek+@cmu.edu">Brian Gallew</ULink>
+</Para>
+</Note>
+
+<Para>
+Configuring gcc to use certain flags by default is a simple matter of
+editing the 
+<FileName>/usr/local/lib/gcc-lib/<Replaceable>platform</Replaceable>/<Replaceable>version</Replaceable>/specs</FileName>
+file.
+The format of this file pretty simple.  The file is broken into
+sections, each of which is three lines long.  The first line is
+"*<Replaceable>section_name</Replaceable>:" (e.g. "*asm:").
+The second line is a list of flags,
+and the third line is blank.
+
+<Para>
+The easiest change to make is to append
+the desired default flags to the list in the appropriate section.  As
+an example, let's suppose that I have linux running on a '486 with gcc
+2.7.2 installed in the default location.  In the file
+/usr/local/lib/gcc-lib/i486-linux/2.7.2/specs, 13 lines down I find
+the following section:
+<ProgramListing>
+- ----------SECTION----------
+*cc1:
+
+
+- ----------SECTION----------
+</ProgramListing>
+As you can see, there aren't any default flags.  If I always wanted
+compiles of C code to use "-m486 -fomit-frame-pointer", I would
+change it to look like:
+<ProgramListing>
+- ----------SECTION----------
+*cc1:
+- -m486 -fomit-frame-pointer
+
+- ----------SECTION----------
+</ProgramListing>
+If I wanted to be able to generate 386 code for another, older linux
+box lying around, I'd have to make it look like this:
+<ProgramListing>
+- ----------SECTION----------
+*cc1:
+%{!m386:-m486} -fomit-frame-pointer
+
+- ----------SECTION----------
+</ProgramListing>
+This will always omit frame pointers, any will build 486-optimized
+code unless -m386 is specified on the command line.
+
+<Para>
+You can actually do quite a lot of customization with the specs file.
+Always remember, however, that these changes are global, and affect
+all users of the system.
+
+</Chapter>
diff --git a/doc/src/sgml/contacts.sgml b/doc/src/sgml/contacts.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..8979cfdbdcc56580b201cec3f5faec9b1ee8a60d
--- /dev/null
+++ b/doc/src/sgml/contacts.sgml
@@ -0,0 +1,23 @@
+<Appendix label="B">
+<Title>Contacts</Title>
+
+<Sect1>
+<Title>Introduction</Title>
+<Para>
+</Para>
+
+<Sect1>
+<Title>People</Title>
+
+<Para>
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+<ULink url="http://alumni.caltech.edu/~lockhart">Thomas Lockhart</ULink>
+ works on SQL standards compliance and documentation.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+</Appendix>
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..37da846b7bd469bd7af0477eab415eaded88a6ee
--- /dev/null
+++ b/doc/src/sgml/datatype.sgml
@@ -0,0 +1,2064 @@
+<Chapter>
+<Title>Data Types</Title>
+
+<Abstract>
+<Para>
+Describes the built-in data types available in <ProductName>Postgres</ProductName>.
+</Para>
+</Abstract>
+
+<Para>
+<ProductName>Postgres</ProductName> has a rich set of native data types available to users.
+Users may add new types to <ProductName>Postgres</ProductName> using the
+<Command>define type</Command>
+command described elsewhere.
+
+<Para>
+In the context of data types, the following sections will discuss SQL standards
+compliance, porting issues, and usage.
+
+Some <ProductName>Postgres</ProductName> types correspond directly to SQL92-compatible types. In other
+cases, data types defined by SQL92 syntax are mapped directly
+into native <ProductName>Postgres</ProductName> types. 
+
+Many of the built-in types have obvious external formats. However, several
+types are either unique to <ProductName>Postgres</ProductName>, such as open and closed paths, or have
+several possibilities for formats, such as date and time types.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Data Types</TITLE>
+<TITLEABBREV>Data Types</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY><ProductName>Postgres</ProductName> Type</ENTRY>
+    <ENTRY><Acronym>SQL92</Acronym> or <Acronym>SQL3</Acronym> Type</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>bool</ENTRY>
+    <ENTRY>boolean</ENTRY>
+    <ENTRY>logical boolean (true/false)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>box</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>rectangular box in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>char(n)</ENTRY>
+    <ENTRY>character(n)</ENTRY>
+    <ENTRY>fixed-length character string</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>circle</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>circle in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>date</ENTRY>
+    <ENTRY>date</ENTRY>
+    <ENTRY>calendar date without time of day</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>float4/8</ENTRY>
+    <ENTRY>float(p)</ENTRY>
+    <ENTRY>floating-point number with precision p</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>float8</ENTRY>
+    <ENTRY>real, double precision</ENTRY>
+    <ENTRY>double-precision floating-point number</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>int2</ENTRY>
+    <ENTRY>smallint</ENTRY>
+    <ENTRY>signed two-byte integer</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>int4</ENTRY>
+    <ENTRY>int, integer</ENTRY>
+    <ENTRY>signed 4-byte integer</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>int4</ENTRY>
+    <ENTRY>decimal(p,s)</ENTRY>
+    <ENTRY>exact numeric for p <= 9, s = 0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>int4</ENTRY>
+    <ENTRY>numeric(p,s)</ENTRY>
+    <ENTRY>exact numeric for p == 9, s = 0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>line</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>infinite line in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>lseg</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>line segment in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>money</ENTRY>
+    <ENTRY>decimal(9,2)</ENTRY>
+    <ENTRY>US-style currency</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>path</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>open and closed geometric path in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>point</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>geometric point in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>polygon</ENTRY>
+    <ENTRY></ENTRY>
+    <ENTRY>closed geometric path in 2D plane</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>time</ENTRY>
+    <ENTRY>time</ENTRY>
+    <ENTRY>time of day</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timespan</ENTRY>
+    <ENTRY>interval</ENTRY>
+    <ENTRY>general-use time span</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timestamp</ENTRY>
+    <ENTRY>timestamp with time zone</ENTRY>
+    <ENTRY>date/time</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>varchar(n)</ENTRY>
+    <ENTRY>character varying(n)</ENTRY>
+    <ENTRY>variable-length character string</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Function Constants</TITLE>
+<TITLEABBREV>Constants</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY><ProductName>Postgres</ProductName> Function</ENTRY>
+    <ENTRY><Acronym>SQL92</Acronym> Constant</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>getpgusername()</ENTRY>
+    <ENTRY>current_user</ENTRY>
+    <ENTRY>user name in current session</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>date('now')</ENTRY>
+    <ENTRY>current_date</ENTRY>
+    <ENTRY>date of current transaction</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>time('now')</ENTRY>
+    <ENTRY>current_time</ENTRY>
+    <ENTRY>time of current transaction</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timestamp('now')</ENTRY>
+    <ENTRY>current_timestamp</ENTRY>
+    <ENTRY>date and time of current transaction</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<ProductName>Postgres</ProductName> has features at the forefront of ORDBMS development. In addition to
+SQL3 conformance, substantial portions of SQL92 are also supported.
+Although we strive for SQL92 compliance, there are some cases in the standard
+which are ill considered and which should not live through subsequent standards.
+<ProductName>Postgres</ProductName> will not make great efforts to conform to these cases. However, these
+cases tend to be little-used and obsure, and a typical user is not likely to
+run into them.
+
+<Para>
+Although most of the input and output functions corresponding to the
+base types (e.g., integers and floating point numbers) do some
+error-checking, some are not particularly rigorous about it.  More
+importantly, few of the operators and functions (e.g.,
+addition and multiplication) perform any error-checking at all.
+Consequently, many of the numeric operators can (for example)
+silently underflow or overflow.
+</Para>
+
+<Para>
+Some of the input and output functions are not invertible.  That is,
+the result of an output function may lose precision when compared to
+the original input.
+</Para>
+
+<Sect1>
+<Title>Numeric Types</Title>
+
+<Para>
+Numeric types consist of two- and four-byte integers and four- and eight-byte
+floating point numbers.
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Numeric Types</TITLE>
+<TITLEABBREV>Numerics</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Numeric Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Range</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>int2</ENTRY>
+    <ENTRY>2 bytes</ENTRY>
+    <ENTRY>Fixed-precision</ENTRY>
+    <ENTRY>-32768 to +32767</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>int4</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>Usual choice for fixed-precision</ENTRY>
+    <ENTRY>-2147483648 to +2147483647</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>float4</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>Variable-precision</ENTRY>
+    <ENTRY>7 decimal places</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>float8</ENTRY>
+    <ENTRY>8 bytes</ENTRY>
+    <ENTRY>Variable-precision</ENTRY>
+    <ENTRY>14 decimal places</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+The <FirstTerm>exact numerics</FirstTerm> <Type>decimal</Type> and <Type>numeric</Type>
+have fully implemented syntax but currently (<ProductName>Postgres</ProductName> v6.3)
+ support only a small range of precision and/or range values.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Monetary Type</Title>
+
+<Para>
+The <Type>money</Type> type supports US-style currency with fixed decimal point representation.
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Numeric Types</TITLE>
+<TITLEABBREV>Numerics</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Monetary Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Range</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>money</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>Fixed-precision</ENTRY>
+    <ENTRY>-21474836.48 to +21474836.47</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+The <FirstTerm>exact numerics</FirstTerm> <Type>decimal</Type> and <Type>numeric</Type>
+have fully implemented syntax but currently (<ProductName>Postgres</ProductName> v6.3)
+ support only a small range of precision and/or range values.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Character Types</Title>
+
+<Para>
+<Acronym>SQL92</Acronym> defines two primary character types: <Type>char</Type> and
+<Type>varchar</Type>. <ProductName>Postgres</ProductName> supports these types, in
+addition to the more general <Type>text</Type> type, which unlike <Type>varchar</Type>
+does not require an upper
+limit to be declared on the size of the field.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Character Types</TITLE>
+<TITLEABBREV>Characters</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Character Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Recommendation</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>char</ENTRY>
+    <ENTRY>1 byte</ENTRY>
+    <ENTRY>SQL92-compatible</ENTRY>
+    <ENTRY>Single character</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>char(n)</ENTRY>
+    <ENTRY>(4+n) bytes</ENTRY>
+    <ENTRY>SQL92-compatible</ENTRY>
+    <ENTRY>Fixed-length blank padded</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>text</ENTRY>
+    <ENTRY>(4+x) bytes</ENTRY>
+    <ENTRY>Best choice</ENTRY>
+    <ENTRY>Variable-length</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>varchar(n)</ENTRY>
+    <ENTRY>(4+n) bytes</ENTRY>
+    <ENTRY>SQL92-compatible</ENTRY>
+    <ENTRY>Variable-length with limit</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+There are currently other fixed-length character types. These provide no additional
+functionality and are likely to be deprecated in the future.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Specialty Character Types</TITLE>
+<TITLEABBREV>Specialty Characters</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Character Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>char2</ENTRY>
+    <ENTRY>2 bytes</ENTRY>
+    <ENTRY>Two characters</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>char4</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>Four characters</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>char8</ENTRY>
+    <ENTRY>8 bytes</ENTRY>
+    <ENTRY>Eight characters</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>char16</ENTRY>
+    <ENTRY>16 bytes</ENTRY>
+    <ENTRY>Sixteen characters</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Date/Time Types</Title>
+
+<Para>
+There are two fundamental kinds of date and time measurements: clock time and time interval.
+Both quantities have continuity and smoothness, as does time itself.
+<ProductName>Postgres</ProductName> supplies two primary user-oriented date and time types,
+<Type>datetime</Type> and timespan, as well as the related SQL92 types date and time.
+</Para>
+
+<Para>
+Other date and time types are available
+also, mostly
+for historical reasons.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Date/Time Types</TITLE>
+<TITLEABBREV>Date/Time</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Date/Time Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Recommendation</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>abstime</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>original date and time</ENTRY>
+    <ENTRY>limited range</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>date</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>SQL92 type</ENTRY>
+    <ENTRY>wide range</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>datetime</ENTRY>
+    <ENTRY>8 bytes</ENTRY>
+    <ENTRY>best general date and time</ENTRY>
+    <ENTRY>wide range, high precision</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>interval</ENTRY>
+    <ENTRY>12 bytes</ENTRY>
+    <ENTRY>SQL92 type</ENTRY>
+    <ENTRY>equivalent to timespan</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>reltime</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>original time interval</ENTRY>
+    <ENTRY>limited range, low precision</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>time</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>SQL92 type</ENTRY>
+    <ENTRY>wide range</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timespan</ENTRY>
+    <ENTRY>12 bytes</ENTRY>
+    <ENTRY>best general time interval</ENTRY>
+    <ENTRY>wide range, high precision</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timestamp</ENTRY>
+    <ENTRY>4 bytes</ENTRY>
+    <ENTRY>SQL92 type</ENTRY>
+    <ENTRY>limited range</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Date/Time Ranges</TITLE>
+<TITLEABBREV>Ranges</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Date/Time Type</ENTRY>
+    <ENTRY>Earliest</ENTRY>
+    <ENTRY>Latest</ENTRY>
+    <ENTRY>Resolution</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>abstime</ENTRY>
+    <ENTRY>1901-12-14</ENTRY>
+    <ENTRY>2038-01-19</ENTRY>
+    <ENTRY>1 sec</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>date</ENTRY>
+    <ENTRY>4713 BC</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>1 day</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>datetime</ENTRY>
+    <ENTRY>4713 BC</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>1 microsec to 14 digits</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>interval</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>1 microsec</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>reltime</ENTRY>
+    <ENTRY>-68 years</ENTRY>
+    <ENTRY>+68 years</ENTRY>
+    <ENTRY>1 sec</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>time</ENTRY>
+    <ENTRY>00:00:00.00</ENTRY>
+    <ENTRY>23:59:59.99</ENTRY>
+    <ENTRY>1 microsec</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timespan</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>no limit</ENTRY>
+    <ENTRY>1 microsec (14 digits)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>timestamp</ENTRY>
+    <ENTRY>1901-12-14</ENTRY>
+    <ENTRY>2038-01-19</ENTRY>
+    <ENTRY>1 sec</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<ProductName>Postgres</ProductName> endevours to be compatible with
+<Acronym>SQL92</Acronym> definitions for typical usage.
+The <Acronym>SQL92</Acronym> standard has an odd mix of date and
+time types and capabilities. For example, although the date type does not have an associated time zone, the
+time type can. The default time zone is specified as a constant offset from GMT/UTC;
+ however, time zones in the real world can have no meaning unless associated with a
+ date as well
+as a time since the offset will vary through the year.
+
+<Para>
+To obviate these difficulties, <ProductName>Postgres</ProductName> associates time zones
+ only with date and time
+types which contain both date and time, and assumes local time for any type containing only
+date or time. Further, time zone support is derived from the underlying operating system
+time zone capabilities, and hence can handle daylight savings time and other expected behavior.
+
+<Para>
+In future releases, the number of date/time types will decrease, with the current
+implementation of <Type>datetime</Type> becoming <Type>timestamp</Type>, timespan becoming interval,
+and (possibly) abstime
+and reltime being deprecated in favor of <Type>timestamp</Type> and interval.
+The more arcane features
+of the date/time definitions from the <Acronym>SQL92</Acronym> standard are not likely to be pursued.
+</Para>
+
+<Sect2>
+<Title>Date/Time Styles</Title>
+
+<Para>
+Output formats can be set to one of four styles: 
+ISO-8601, SQL (Ingres), traditional
+Postgres, and German.
+
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Date Styles</TITLE>
+<TITLEABBREV>Styles</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Style Specification</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>ISO</ENTRY>
+    <ENTRY>ISO-8601 standard</ENTRY>
+    <ENTRY>1997-12-17 07:37:16-08</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>SQL</ENTRY>
+    <ENTRY>Traditional style</ENTRY>
+    <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Postgres</ENTRY>
+    <ENTRY>Original style</ENTRY>
+    <ENTRY>Wed Dec 17 07:37:16 1997 PST</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>German</ENTRY>
+    <ENTRY>Regional style</ENTRY>
+    <ENTRY>17.12.1997 07:37:16.00 PST</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+The SQL style has European and non-European (US) variants, which determines whether
+month follows day or vica versa.
+
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Date Order Conventions</TITLE>
+<TITLEABBREV>Order</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Style Specification</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>European</ENTRY>
+    <ENTRY>Regional convention</ENTRY>
+    <ENTRY>17/12/1997 15:37:16.00 MET</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NonEuropean</ENTRY>
+    <ENTRY>Regional convention</ENTRY>
+    <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>US</ENTRY>
+    <ENTRY>Regional convention</ENTRY>
+    <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+There are several ways to affect the appearance of date/time types:
+
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+The PGDATESTYLE environment variable used by the backend directly on postmaster startup.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The PGDATESTYLE environment variable used by the frontend libpq on session startup.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+SET DateStyle <Acronym>SQL</Acronym> command.
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+For <ProductName>Postgres</ProductName> v6.3 (and earlier) the default date/time style is
+"traditional Postgres". In future releases, the default may become ISO-8601, which alleviates
+date specification ambiguities and Y2K collation problems.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Time Zones</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> obtains time zone support from the underlying operating system.
+All dates and times are stored internally in Universal Coordinated Time (UTC), alternately known as
+Greenwich Mean Time (GMT). Times are converted to local time on the database server before being
+sent to the client frontend, hence by default are in the server time zone.
+
+<Para>
+There are several ways to affect the time zone behavior:
+
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+The TZ environment variable used by the backend directly
+ on postmaster startup as the default time zone.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The PGTZ environment variable set at the client used by libpq to send time zone information to the backend upon connection.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Command>set timezone</Command> <Acronym>SQL</Acronym> sets the time zone for the session.
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+ If an invalid time zone is specified,
+the time zone becomes GMT (on most systems anyway).
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Date/Time Input</Title>
+
+<Para>
+General-use date and time is input using a wide range of
+styles, including ISO-compatible, SQL-compatible, traditional
+<ProductName>Postgres</ProductName> 
+and other permutations of date and time. In cases where interpretation
+can be ambiguous (quite possible with many traditional styles of date specification)
+<ProductName>Postgres</ProductName> uses a style setting to resolve the ambiguity.
+</Para>
+
+<Para>
+Most date and time types share code for data input. For those types
+the input can have any of a wide variety of styles. For numeric date representations,
+European and US conventions can differ, and the proper interpretation is obtained
+by using the
+<Command>set datestyle</Command>
+command before entering data.
+Note that the style setting does not preclude use of various styles for input; it is
+used primarily to determine the output style and to resolve ambiguities.
+</Para>
+
+<Para>
+The special values `current',
+`infinity' and `-infinity' are provided.
+`infinity' specifies a time later than any other valid time, and
+`-infinity' specifies a time earlier than any other valid time.
+`current' indicates that the current time should be
+substituted whenever this value appears in a computation.
+
+The strings
+`now',
+`today',
+`yesterday',
+`tomorrow',
+and `epoch' can be used to specify
+time values.  `now' means the current transaction time, and differs from
+`current' in that the current time is immediately substituted
+for it.  `epoch' means Jan 1 00:00:00 1970 GMT.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Date/Time Special Constants</TITLE>
+<TITLEABBREV>Constants</TITLEABBREV>
+<TGROUP COLS="2">
+<THEAD>
+  <ROW>
+    <ENTRY>Constant</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>current</ENTRY>
+    <ENTRY>Current transaction time, deferred</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>epoch</ENTRY>
+    <ENTRY>1970-01-01 00:00:00+00 (Unix system time zero)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>infinity</ENTRY>
+    <ENTRY>Later than other valid times</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>-infinity</ENTRY>
+    <ENTRY>Earlier than other valid times</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>invalid</ENTRY>
+    <ENTRY>Illegal entry</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>now</ENTRY>
+    <ENTRY>Current transaction time</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>today</ENTRY>
+    <ENTRY>Midnight today</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>tomorrow</ENTRY>
+    <ENTRY>Midnight tomorrow</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>yesterday</ENTRY>
+    <ENTRY>Midnight yesterday</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>datetime</Title>
+
+<Para>
+General-use date and time is input using a wide range of
+styles, including ISO-compatible, SQL-compatible, traditional
+<ProductName>Postgres</ProductName> (see section on "absolute time")
+and other permutations of date and time. Output styles can be ISO-compatible,
+SQL-compatible, or traditional <ProductName>Postgres</ProductName>, with the default set to be compatible
+with <ProductName>Postgres</ProductName> v6.0.
+</Para>
+
+<Para>
+<Type>datetime</Type> is specified using the following syntax:
+
+<ProgramListing>
+Year-Month-Day [ Hour : Minute : Second ]      [AD,BC] [ Timezone ]
+  YearMonthDay [ Hour : Minute : Second ]      [AD,BC] [ Timezone ]
+     Month Day [ Hour : Minute : Second ] Year [AD,BC] [ Timezone ]
+where	
+    Year is 4013 BC, ..., very large
+    Month is Jan, Feb, ..., Dec or 1, 2, ..., 12
+    Day is 1, 2, ..., 31
+    Hour is 00, 02, ..., 23
+    Minute is 00, 01, ..., 59
+    Second is 00, 01, ..., 59 (60 for leap second)
+    Timezone is 3 characters or ISO offset to GMT
+</ProgramListing>
+
+<Para>
+Valid dates are from Nov 13 00:00:00 4013 BC GMT to far into the future.
+Timezones are either three characters (e.g. "GMT" or "PST") or ISO-compatible
+offsets to GMT (e.g. "-08" or "-08:00" when in Pacific Standard Time).
+Dates are stored internally in Greenwich Mean Time. Input and output routines 
+translate time to the local time zone of the server.
+</Para>
+
+<Sect2>
+<Title><Type>timespan</Type></Title>
+
+<Para>
+General-use time span is input using a wide range of
+syntaxes, including ISO-compatible, SQL-compatible, traditional
+<ProductName>Postgres</ProductName> (see section on "relative time")
+ and other permutations of time span. Output formats can be ISO-compatible,
+SQL-compatible, or traditional <ProductName>Postgres</ProductName>, with the default set to be <ProductName>Postgres</ProductName>-compatible.
+Months and years are a "qualitative" time interval, and are stored separately
+from the other "quantitative" time intervals such as day or hour. For date arithmetic,
+the qualitative time units are instantiated in the context of the relevant date or time.
+
+<Para>
+Time span is specified with the following syntax:
+
+<ProgramListing>
+  Quantity Unit [Quantity Unit...] [Direction]
+@ Quantity Unit [Direction]
+where 	
+    Quantity is ..., `-1', `0', `1', `2', ...
+    Unit is `second', `minute', `hour', `day', `week', `month', `year',
+    'decade', 'century', millenium', or abbreviations or plurals of these units.
+    Direction is `ago'.
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>abstime</Title>
+
+<Para>
+Absolute time (abstime) is a limited-range (+/- 68 years) and limited-precision (1 sec)
+date data type. <Type>datetime</Type> may be preferred, since it
+covers a larger range with greater precision.
+
+<Para>
+Absolute time is specified using the following syntax:
+
+<ProgramListing>
+Month  Day [ Hour : Minute : Second ]  Year [ Timezone ]
+where	
+    Month is Jan, Feb, ..., Dec
+    Day is 1, 2, ..., 31
+    Hour is 01, 02, ..., 24
+    Minute is 00, 01, ..., 59
+    Second is 00, 01, ..., 59
+    Year is 1901, 1902, ..., 2038
+</ProgramListing>
+</Para>
+
+<Para>
+Valid dates are from Dec 13 20:45:53 1901 GMT to Jan 19 03:14:04
+2038 GMT.  As of Version 3.0, times are no longer read and written
+using Greenwich Mean Time; the input and output routines default to
+the local time zone.
+
+All special values allowed for <Type>datetime</Type> are also allowed for "absolute time".
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>reltime</Title>
+
+<Para>
+Relative time <Type>reltime</Type> is a limited-range (+/- 68 years)
+ and limited-precision (1 sec) time span data type.
+<Type>timespan</Type> should be preferred, since it
+covers a larger range with greater precision and, more importantly, can distinguish between
+relative units (months and years) and quantitative units (days, hours, etc). Instead, reltime
+must force months to be exactly 30 days, so time arithmetic does not always work as expected.
+For example, adding one reltime year to abstime today does not produce today's date one year from
+now, but rather a date 360 days from today.
+</Para>
+
+<Para>
+<Type>reltime</Type> shares input and output routines with the other time span types.
+The section on <Type>timespan</Type> covers this in more detail.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title><Type>timestamp</Type></Title>
+
+<Para>
+This is currently a limited-range absolute time which closely resembles the
+abstime
+data type. It shares the general input parser with the other date/time types.
+In future releases this type will absorb the capabilities of the <Type>datetime</Type> type
+and will move toward SQL92 compliance.
+</Para>
+
+<Para>
+<Type>timestamp</Type> is specified using the same syntax as for <Type>datetime</Type>.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title><Type>interval</Type></Title>
+
+<Para>
+<Type>interval</Type> is an <Acronym>SQL92</Acronym> data type which is
+currently mapped to the <Type>timespan</Type> <ProductName>Postgres</ProductName>
+data type.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>tinterval</Title>
+
+<Para>
+Time ranges are specified as:
+
+<ProgramListing>
+[ 'abstime' 'abstime']
+where
+    abstime is a time in the absolute time format.
+</ProgramListing>
+
+Special abstime values such as 
+`current', `infinity' and `-infinity' can be used.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Boolean Type</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> supports <Type>bool</Type> as
+the <Acronym>SQL3</Acronym> boolean type.
+<Type>bool</Type> can have one of only two states: 'true' or 'false'. A third state, 'unknown', is not
+implemented and is not suggested in <Acronym>SQL3</Acronym>; <Acronym>NULL</Acronym> is an
+effective substitute. <Type>bool</Type> can be used in any boolean expression, and boolean expressions
+always evaluate to a result compatible with this type.
+
+<Para>
+<Type>bool</Type> uses 4 bytes of storage.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Boolean Type</TITLE>
+<TITLEABBREV>Booleans</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>State</ENTRY>
+    <ENTRY>Output</ENTRY>
+    <ENTRY>Input</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>True</ENTRY>
+    <ENTRY>'t'</ENTRY>
+    <ENTRY>TRUE, 't', 'true', 'y', 'yes', '1'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>False</ENTRY>
+    <ENTRY>'f'</ENTRY>
+    <ENTRY>FALSE, 'f', 'false', 'n', 'no', '0'</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Geometric Types</Title>
+
+<Para>
+Geometric types represent two-dimensional spatial objects. The most fundamental type,
+the point, forms the basis for all of the other types.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Geometric Types</TITLE>
+<TITLEABBREV>Geometrics</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Geometric Type</ENTRY>
+    <ENTRY>Storage</ENTRY>
+    <ENTRY>Representation</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>point</ENTRY>
+    <ENTRY>16 bytes</ENTRY>
+    <ENTRY>(x,y)</ENTRY>
+    <ENTRY>Point in space</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>line</ENTRY>
+    <ENTRY>32 bytes</ENTRY>
+    <ENTRY>((x1,y1),(x2,y2))</ENTRY>
+    <ENTRY>Infinite line</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>lseg</ENTRY>
+    <ENTRY>32 bytes</ENTRY>
+    <ENTRY>((x1,y1),(x2,y2))</ENTRY>
+    <ENTRY>Finite line segment</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>box</ENTRY>
+    <ENTRY>32 bytes</ENTRY>
+    <ENTRY>((x1,y1),(x2,y2))</ENTRY>
+    <ENTRY>Rectangular box</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>path</ENTRY>
+    <ENTRY>4+32n bytes</ENTRY>
+    <ENTRY>((x1,y1),...)</ENTRY>
+    <ENTRY>Closed path (similar to polygon)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>path</ENTRY>
+    <ENTRY>4+32n bytes</ENTRY>
+    <ENTRY>[(x1,y1),...]</ENTRY>
+    <ENTRY>Open path</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>polygon</ENTRY>
+    <ENTRY>4+32n bytes</ENTRY>
+    <ENTRY>((x1,y1),...)</ENTRY>
+    <ENTRY>Polygon (similar to closed path)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>circle</ENTRY>
+    <ENTRY>24 bytes</ENTRY>
+    <ENTRY><(x,y),r></ENTRY>
+    <ENTRY>Circle (center and radius)</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+A rich set of functions and operators is available to perform various geometric
+operations such as scaling, translation, rotation, and determining intersections.
+</Para>
+
+<Sect2>
+<Title>Point</Title>
+
+<Para>
+Points are specified using the following syntax:
+
+<ProgramListing>
+( x , y )
+  x , y
+where
+    x is the x-axis coordinate as a floating point number
+    y is the y-axis coordinate as a floating point number
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Line Segment</Title>
+
+<Para>
+Line segments (lseg) are represented by pairs of points.
+</Para>
+
+<Para>
+lseg is specified using the following syntax:
+<ProgramListing>
+( ( x1 , y1 ) , ( x2 , y2 ) )
+  ( x1 , y1 ) , ( x2 , y2 )  
+    x1 , y1   ,   x2 , y2    
+where
+    (x1,y1) and (x2,y2) are the endpoints of the segment
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Box</Title>
+
+<Para>
+Boxes are represented by pairs of points which are opposite
+corners of the box.
+</Para>
+
+<Para>
+box is specified using the following syntax:
+
+<ProgramListing>
+( ( x1 , y1 ) , ( x2 , y2 ) )
+  ( x1 , y1 ) , ( x2 , y2 )  
+    x1 , y1   ,   x2 , y2    
+where
+    (x1,y1) and (x2,y2) are opposite corners
+</ProgramListing>
+
+Boxes are output using the first syntax.
+The corners are reordered on input to store
+the lower left corner first and the upper right corner last.
+Other corners of the box can be entered, but the lower
+left and upper right corners are determined from the input and stored.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Path</Title>
+
+<Para>
+Paths are represented by connected sets of points. Paths can be "open", where
+the first and last points in the set are not connected, and "closed",
+where the first and last point are connected. Functions
+<Function>popen(p)</Function>
+and
+<Function>pclose(p)</Function>
+are supplied to force a path to be open or closed, and functions
+<Function>isopen(p)</Function>
+and
+<Function>isclosed(p)</Function>
+are supplied to select either type in a query.
+</Para>
+
+<Para>
+path is specified using the following syntax:
+
+<ProgramListing>
+( ( x1 , y1 ) , ... , ( xn , yn ) )
+[ ( x1 , y1 ) , ... , ( xn , yn ) ]
+  ( x1 , y1 ) , ... , ( xn , yn )  
+  ( x1 , y1   , ... ,   xn , yn )  
+    x1 , y1   , ... ,   xn , yn    
+where
+    (x1,y1),...,(xn,yn) are points 1 through n
+    a leading "[" indicates an open path
+    a leading "(" indicates a closed path
+</ProgramListing>
+Paths are output using the first syntax.
+Note that <ProductName>Postgres</ProductName> versions prior to
+v6.1 used a format for paths which had a single leading parenthesis, a "closed" flag,
+an integer count of the number of points, then the list of points followed by a
+closing parenthesis. The built-in function <Function>upgradepath</Function> is supplied to convert
+paths dumped and reloaded from pre-v6.1 databases.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Polygon</Title>
+
+<Para>
+Polygons are represented by sets of points. Polygons should probably be
+considered 
+equivalent to closed paths, but are stored differently and have their own
+set of support routines.
+</Para>
+
+<Para>
+polygon is specified using the following syntax:
+
+<ProgramListing>
+( ( x1 , y1 ) , ... , ( xn , yn ) )
+  ( x1 , y1 ) , ... , ( xn , yn )  
+  ( x1 , y1   , ... ,   xn , yn )  
+    x1 , y1   , ... ,   xn , yn    
+where
+    (x1,y1),...,(xn,yn) are points 1 through n
+</ProgramListing>
+
+Polygons are output using the first syntax.
+Note that <ProductName>Postgres</ProductName> versions prior to
+v6.1 used a format for polygons which had a single leading parenthesis, the list
+of x-axis coordinates, the list of y-axis coordinates, followed by a closing parenthesis.
+The built-in function <Function>upgradepoly</Function> is supplied to convert
+polygons dumped and reloaded from pre-v6.1 databases.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Circle</Title>
+
+<Para>
+Circles are represented by a center point and a radius.
+</Para>
+
+<Para>
+circle is specified using the following syntax:
+
+<ProgramListing>
+< ( x , y ) , r >
+( ( x , y ) , r )
+  ( x , y ) , r  
+    x , y   , r  
+where
+    (x,y) is the center of the circle
+    r is the radius of the circle
+</ProgramListing>
+
+Circles are output using the first syntax.
+</Para>
+</Sect2>
+
+</Sect1>
+
+<Chapter>
+<Title>Operators</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> provides a large number of built-in operators on system types.
+These operators are declared in the system catalog
+pg_operator.  Every entry in pg_operator includes
+the name of the procedure that implements the operator and the
+class <Acronym>OIDs</Acronym> of the input and output types.
+
+<Para>
+To view all variations of the <Quote>||</Quote> string concatenation operator, try
+<ProgramListing>
+    SELECT oprleft, oprright, oprresult, oprcode
+    FROM pg_operator WHERE oprname = '||';
+
+oprleft|oprright|oprresult|oprcode
+-------+--------+---------+-------
+     25|      25|       25|textcat
+   1042|    1042|     1042|textcat
+   1043|    1043|     1043|textcat
+(3 rows)
+</ProgramListing>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Operators</TITLE>
+<TITLEABBREV>Operators</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Operator</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Usage</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY> &lt; </ENTRY>
+    <ENTRY>Less than?</ENTRY>
+    <ENTRY>1 &lt; 2</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;= </ENTRY>
+    <ENTRY>Less than or equal to?</ENTRY>
+    <ENTRY>1 &lt;= 2</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;&gt; </ENTRY>
+    <ENTRY>Not equal?</ENTRY>
+    <ENTRY>1 &lt;&gt; 2</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> = </ENTRY>
+    <ENTRY>Equal?</ENTRY>
+    <ENTRY>1 = 1</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &gt; </ENTRY>
+    <ENTRY>Greater than?</ENTRY>
+    <ENTRY>2 &gt; 1</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &gt;= </ENTRY>
+    <ENTRY>Greater than or equal to?</ENTRY>
+    <ENTRY>2 &gt;= 1</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> || </ENTRY>
+    <ENTRY>Concatenate strings</ENTRY>
+    <ENTRY>'Postgre' || 'SQL'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> !!= </ENTRY>
+    <ENTRY>NOT IN</ENTRY>
+    <ENTRY>3 !!= i</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ~~ </ENTRY>
+    <ENTRY>LIKE</ENTRY>
+    <ENTRY>'scrappy,marc,hermit' ~~ '%scrappy%'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> !~~ </ENTRY>
+    <ENTRY>NOT LIKE</ENTRY>
+    <ENTRY>'bruce' !~~ '%al%'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ~ </ENTRY>
+    <ENTRY>Match (regex), case sensitive</ENTRY>
+    <ENTRY>'thomas' ~ '*.thomas*.'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ~* </ENTRY>
+    <ENTRY>Match (regex), case insensitive</ENTRY>
+    <ENTRY>'thomas' ~* '*.Thomas*.'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> !~ </ENTRY>
+    <ENTRY>Does not match (regex), case sensitive</ENTRY>
+    <ENTRY>'thomas' !~ '*.Thomas*.'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> !~* </ENTRY>
+    <ENTRY>Does not match (regex), case insensitive</ENTRY>
+    <ENTRY>'thomas' !~ '*.vadim*.'</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Numerical Operators</TITLE>
+<TITLEABBREV>Operators</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Operator</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Usage</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY> !  </ENTRY>
+    <ENTRY>Factorial</ENTRY>
+    <ENTRY>3 !</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> !!  </ENTRY>
+    <ENTRY>Factorial (left operator)</ENTRY>
+    <ENTRY>!! 3</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> % </ENTRY>
+    <ENTRY>Modulo</ENTRY>
+    <ENTRY>5 % 4</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> % </ENTRY>
+    <ENTRY>Truncate</ENTRY>
+    <ENTRY>% 4.5</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> * </ENTRY>
+    <ENTRY>Multiplication</ENTRY>
+    <ENTRY>2 * 3</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> + </ENTRY>
+    <ENTRY>Addition</ENTRY>
+    <ENTRY>2 + 3</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> - </ENTRY>
+    <ENTRY>Subtraction</ENTRY>
+    <ENTRY>2 - 3</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> / </ENTRY>
+    <ENTRY>Division</ENTRY>
+    <ENTRY>4 / 2</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> : </ENTRY>
+    <ENTRY>Natural Exponentiation</ENTRY>
+    <ENTRY>: 3.0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ; </ENTRY>
+    <ENTRY>Natural Logarithm</ENTRY>
+    <ENTRY>(; 5.0)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> @ </ENTRY>
+    <ENTRY>Absolute value</ENTRY>
+    <ENTRY>@ -5.0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ^ </ENTRY>
+    <ENTRY>Exponentiation</ENTRY>
+    <ENTRY>2.0 ^ 3.0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> |/ </ENTRY>
+    <ENTRY>Square root</ENTRY>
+    <ENTRY>|/ 25.0</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ||/ </ENTRY>
+    <ENTRY>Cube root</ENTRY>
+    <ENTRY>||/ 27.0</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Geometric Operators</TITLE>
+<TITLEABBREV>Operators</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Operator</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Usage</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY> + </ENTRY>
+    <ENTRY>Translation</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::box + '(2.0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> - </ENTRY>
+    <ENTRY>Translation</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::box - '(2.0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> * </ENTRY>
+    <ENTRY>Scaling/rotation</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::box * '(2.0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> / </ENTRY>
+    <ENTRY>Scaling/rotation</ENTRY>
+    <ENTRY>'((0,0),(2,2))'::box / '(2.0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> # </ENTRY>
+    <ENTRY>Intersection</ENTRY>
+    <ENTRY>'((1,-1),(-1,1))' # '((1,1),(-1,-1))'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> # </ENTRY>
+    <ENTRY>Number of points in polygon</ENTRY>
+    <ENTRY># '((1,0),(0,1),(-1,0))'</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ## </ENTRY>
+    <ENTRY>Point of closest proximity</ENTRY>
+    <ENTRY>'(0,0)'::point ## '((2,0),(0,2))'::lseg</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &amp;&amp; </ENTRY>
+    <ENTRY>Overlaps?</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::box &amp;&amp; '((0,0),(2,2))'::box</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &amp;&lt; </ENTRY>
+    <ENTRY>Overlaps to left?</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::box &amp;&lt; '((0,0),(2,2))'::box</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &amp;&gt; </ENTRY>
+    <ENTRY>Overlaps to right?</ENTRY>
+    <ENTRY>'((0,0),(3,3))'::box &amp;&gt; '((0,0),(2,2))'::box</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;-&gt; </ENTRY>
+    <ENTRY>Distance between</ENTRY>
+    <ENTRY>'((0,0),1)'::circle &lt;-&gt; '((5,0),1)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;&lt; </ENTRY>
+    <ENTRY>Left of?</ENTRY>
+    <ENTRY>'((0,0),1)'::circle &lt;&lt; '((5,0),1)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;^ </ENTRY>
+    <ENTRY>Is below?</ENTRY>
+    <ENTRY>'((0,0),1)'::circle &lt;^ '((0,5),1)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &gt;&gt; </ENTRY>
+    <ENTRY>Is right of?</ENTRY>
+    <ENTRY>'((5,0),1)'::circle &gt;&gt; '((0,0),1)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &gt;^ </ENTRY>
+    <ENTRY>Is above?</ENTRY>
+    <ENTRY>'((0,5),1)'::circle >^ '((0,0),1)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ?# </ENTRY>
+    <ENTRY>Intersects or overlaps</ENTRY>
+    <ENTRY>'((-1,0),(1,0))'::lseg ?# '((-2,-2),(2,2))'::box;</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ?- </ENTRY>
+    <ENTRY>Is horizontal?</ENTRY>
+    <ENTRY>'(1,0)'::point ?- '(0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ?-| </ENTRY>
+    <ENTRY>Is perpendicular?</ENTRY>
+    <ENTRY>'((0,0),(0,1))'::lseg ?-| '((0,0),(1,0))'::lseg</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> @-@  </ENTRY>
+    <ENTRY>Length or circumference</ENTRY>
+    <ENTRY>@-@ '((0,0),(1,0))'::path</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ?| </ENTRY>
+    <ENTRY>Is vertical?</ENTRY>
+    <ENTRY>'(0,1)'::point ?| '(0,0)'::point</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ?|| </ENTRY>
+    <ENTRY>Is parallel?</ENTRY>
+    <ENTRY>'((-1,0),(1,0))'::lseg ?|| '((-1,2),(1,2))'::lseg</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> @ </ENTRY>
+    <ENTRY>Contained or on</ENTRY>
+    <ENTRY>'(1,1)'::point @ '((0,0),2)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> @@ </ENTRY>
+    <ENTRY>Center of</ENTRY>
+    <ENTRY>@@ '((0,0),10)'::circle</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ~= </ENTRY>
+    <ENTRY>Same as</ENTRY>
+    <ENTRY>'((0,0),(1,1))'::polygon ~= '((1,1),(0,0))'::polygon</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+The time interval data type <Type>tinterval</Type> is a legacy from the original
+date/time types and is not as well supported as the more modern types. There
+are several operators for this type.
+
+<TABLE TOCENTRY="1">
+<TITLE><ProductName>Postgres</ProductName> Time Interval Operators</TITLE>
+<TITLEABBREV>Operators</TITLEABBREV>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Operator</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Usage</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY> #&lt; </ENTRY>
+    <ENTRY>Interval less than?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> #&lt;= </ENTRY>
+    <ENTRY>Interval less than or equal to?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> #&lt;&gt; </ENTRY>
+    <ENTRY>Interval not equal?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> #= </ENTRY>
+    <ENTRY>Interval equal?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> #&gt; </ENTRY>
+    <ENTRY>Interval greater than?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> #&gt;= </ENTRY>
+    <ENTRY>Interval greater than or equal to?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;#&gt; </ENTRY>
+    <ENTRY>Convert to time interval</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;&lt; </ENTRY>
+    <ENTRY>Interval less than?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> | </ENTRY>
+    <ENTRY>Start of interval</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> ~= </ENTRY>
+    <ENTRY>Same as</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY> &lt;?&gt; </ENTRY>
+    <ENTRY>Time inside interval?</ENTRY>
+    <ENTRY></ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+
+<Para>
+Users may invoke operators using the operator name, as in:
+
+<ProgramListing>
+select * from emp where salary < 40000;
+</ProgramListing>
+
+Alternatively, users may call the functions that implement the
+operators directly.  In this case, the query above would be expressed
+as:
+<ProgramListing>
+select * from emp where int4lt(salary, 40000);
+</ProgramListing>
+
+<Para>
+<Application>psql</Application>
+has a <Command>\dd</Command> command to show these operators.
+</Chapter>
+
+<Chapter>
+<Title>Functions</Title>
+
+<Para>
+Many data types have functions available for conversion to other related types.
+In addition, there are some type-specific functions. Functions which are also
+available through operators are documented as operators only.
+</Para>
+
+<Para>
+Some functions defined for text are also available for char() and varchar().
+</Para>
+
+<Para>
+For the
+<Function>date_part</Function> and <Function>date_trunc</Function>
+functions, arguments can be
+`year', `month', `day', `hour', `minute', and `second',
+as well as the more specialized quantities
+`decade', `century', `millenium', `millisecond', and `microsecond'.
+<Function>date_part</Function> allows `dow'
+to return day of week and `epoch' to return seconds since 1970 (for <Type>datetime</Type>)
+or 'epoch' to return total elapsed seconds (for <Type>timespan</Type>).
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE>Mathematical Functions</TITLE>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Function</ENTRY>
+    <ENTRY>Returns</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+<ENTRY> float(int) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> convert integer to floating point </ENTRY>
+<ENTRY> float(2) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> float4(int) </ENTRY>
+<ENTRY> float4 </ENTRY>
+<ENTRY> convert integer to floating point </ENTRY>
+<ENTRY> float4(2) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> int </ENTRY>
+<ENTRY> integer(float) </ENTRY>
+<ENTRY> convert floating point to integer </ENTRY>
+<ENTRY> integer(2.0) </ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+Many of the string functions are available for text, varchar(), and char() types.
+At the moment, some functions are available only for the text type.
+
+<TABLE TOCENTRY="1">
+<TITLE>String Functions</TITLE>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Function</ENTRY>
+    <ENTRY>Returns</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+<ENTRY> lower(text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> convert text to lower case </ENTRY>
+<ENTRY> lower('TOM') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> lpad(text,int,text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> left pad string to specified length </ENTRY>
+<ENTRY> lpad('hi',4,'??') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> ltrim(text,text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> left trim characters from text </ENTRY>
+<ENTRY> ltrim('xxxxtrim','x') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> position(text,text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> extract specified substring </ENTRY>
+<ENTRY> position('high','ig') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> rpad(text,int,text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> right pad string to specified length </ENTRY>
+<ENTRY> rpad('hi',4,'x') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> rtrim(text,text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> right trim characters from text </ENTRY>
+<ENTRY> rtrim('trimxxxx','x') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> substr(text,int[,int]) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> extract specified substring </ENTRY>
+<ENTRY> substr('hi there',3,5) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> upper(text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> convert text to upper case </ENTRY>
+<ENTRY> upper('tom') </ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE>Date/Time Functions</TITLE>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY>Function</ENTRY>
+    <ENTRY>Returns</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+<ENTRY> isfinite(abstime) </ENTRY>
+<ENTRY> bool </ENTRY>
+<ENTRY> TRUE if this is a finite time </ENTRY>
+<ENTRY> isfinite('now'::abstime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> datetime(abstime) </ENTRY>
+<ENTRY> datetime </ENTRY>
+<ENTRY> convert to datetime </ENTRY>
+<ENTRY> datetime('now'::abstime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> datetime(date) </ENTRY>
+<ENTRY> datetime </ENTRY>
+<ENTRY> convert to datetime </ENTRY>
+<ENTRY> datetime('today'::date) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> datetime(date,time) </ENTRY>
+<ENTRY> datetime </ENTRY>
+<ENTRY> convert to datetime </ENTRY>
+<ENTRY> datetime('1998-02-24':datetime, '23:07'::time);
+  </ROW>
+  <ROW>
+<ENTRY> age(datetime,datetime) </ENTRY>
+<ENTRY> timespan </ENTRY>
+<ENTRY> span preserving months and years </ENTRY>
+<ENTRY> age('now','1957-06-13':datetime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> date_part(text,datetime) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> specified portion of date field </ENTRY>
+<ENTRY> date_part('dow','now'::datetime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> date_trunc(text,datetime) </ENTRY>
+<ENTRY> datetime </ENTRY>
+<ENTRY> truncate date at specified units </ENTRY>
+<ENTRY> date_trunc('month','now'::abstime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> isfinite(datetime) </ENTRY>
+<ENTRY> bool </ENTRY>
+<ENTRY> TRUE if this is a finite time </ENTRY>
+<ENTRY> isfinite('now'::datetime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> abstime(datetime) </ENTRY>
+<ENTRY> abstime </ENTRY>
+<ENTRY> convert to abstime </ENTRY>
+<ENTRY> abstime('now'::datetime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> timespan(reltime) </ENTRY>
+<ENTRY> timespan </ENTRY>
+<ENTRY> convert to timespan </ENTRY>
+<ENTRY> timespan('4 hours'::reltime) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> datetime(date,time) </ENTRY>
+<ENTRY> datetime </ENTRY>
+<ENTRY> convert to datetime </ENTRY>
+<ENTRY> datetime('1998-02-25'::date,'06:41'::time) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> date_part(text,timespan) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> specified portion of time field </ENTRY>
+<ENTRY> date_part('hour','4 hrs 3 mins'::timespan) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> isfinite(timespan) </ENTRY>
+<ENTRY> bool </ENTRY>
+<ENTRY> TRUE if this is a finite time </ENTRY>
+<ENTRY> isfinite('4 hrs'::timespan) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> reltime(timespan) </ENTRY>
+<ENTRY> reltime </ENTRY>
+<ENTRY> convert to reltime </ENTRY>
+<ENTRY> reltime('4 hrs'::timespan) </ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE>Geometric Functions</TITLE>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Function</ENTRY>
+    <ENTRY>Returns</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+<ENTRY> box(point,point) </ENTRY>
+<ENTRY> box </ENTRY>
+<ENTRY> convert points to box </ENTRY>
+<ENTRY> box('(0,0)'::point,'(1,1)'::point) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> area(box) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> area of box </ENTRY>
+<ENTRY> area('((0,0),(1,1))'::box) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> isopen(path) </ENTRY>
+<ENTRY> bool </ENTRY>
+<ENTRY> TRUE if this is an open path </ENTRY>
+<ENTRY> isopen('[(0,0),(1,1),(2,0)]'::path) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> isclosed(path) </ENTRY>
+<ENTRY> bool </ENTRY>
+<ENTRY> TRUE if this is a closed path </ENTRY>
+<ENTRY> isclosed('((0,0),(1,1),(2,0))'::path) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> circle(point,float8) </ENTRY>
+<ENTRY> circle </ENTRY>
+<ENTRY> convert to circle </ENTRY>
+<ENTRY> circle('(0,0)'::point,2.0) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> polygon(npts,circle) </ENTRY>
+<ENTRY> polygon </ENTRY>
+<ENTRY> convert to polygon with npts points </ENTRY>
+<ENTRY> polygon(12,'((0,0),2.0)'::circle) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> center(circle) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> center of object </ENTRY>
+<ENTRY> center('((0,0),2.0)'::circle) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> radius(circle) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> radius of circle </ENTRY>
+<ENTRY> radius('((0,0),2.0)'::circle) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> diameter(circle) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> diameter of circle </ENTRY>
+<ENTRY> diameter('((0,0),2.0)'::circle) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> area(circle) </ENTRY>
+<ENTRY> float8 </ENTRY>
+<ENTRY> area of circle </ENTRY>
+<ENTRY> area('((0,0),2.0)'::circle) </ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+SQL92 defines functions with specific syntax. Some of these
+are implemented using other <ProductName>Postgres</ProductName> functions.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE><Acronym>SQL92</Acronym> Text Functions</TITLE>
+<TGROUP COLS="3">
+<THEAD>
+  <ROW>
+    <ENTRY>Function</ENTRY>
+    <ENTRY>Returns</ENTRY>
+    <ENTRY>Description</ENTRY>
+    <ENTRY>Example</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+<ENTRY> position(text in text) </ENTRY>
+<ENTRY> int4 </ENTRY>
+<ENTRY> extract specified substring </ENTRY>
+<ENTRY> position('o' in 'Tom') </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> substring(text [from int] [for int]) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> extract specified substring </ENTRY>
+<ENTRY> substring('Tom' from 2 for 2) </ENTRY>
+  </ROW>
+  <ROW>
+<ENTRY> trim([leading|trailing|both] [text] from text) </ENTRY>
+<ENTRY> text </ENTRY>
+<ENTRY> trim characters from text </ENTRY>
+<ENTRY> trim(both 'x' from 'xTomx') </ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..7a719b7ed3e436d5597d815e1afa7b96b051199b
--- /dev/null
+++ b/doc/src/sgml/dfunc.sgml
@@ -0,0 +1,242 @@
+<Chapter>
+<Title>Linking Dynamically-Loaded Functions</Title>
+
+<Para>
+     After you have created and  registered  a  user-defined
+     function,  your  work  is  essentially done.  <ProductName>Postgres</ProductName>,
+     however, must load the object code (e.g., a <FileName>.o</FileName> file, or
+     a  shared  library)  that implements your function.  As
+     previously mentioned, <ProductName>Postgres</ProductName> loads your code at  
+     runtime,  as  required.  In order to allow your code to be
+     dynamically loaded, you may have to compile  and  
+     linkedit  it  in  a  special  way.   This  section  briefly
+     describes how to  perform  the  compilation  and  
+     linkediting  required before you can load your user-defined
+     functions into a running <ProductName>Postgres</ProductName>  server.   Note  that
+     this process has  changed  as  of  Version  4.2.
+<Tip>
+<Para>
+The  old  <ProductName>Postgres</ProductName> dynamic 
+loading mechanism required
+in-depth knowledge in terms of executable format,  placement
+and alignment of executable instructions within memory, etc.
+on the part of the person writing the dynamic loader.   Such
+loaders tended to be slow and buggy.  As of Version 4.2, the
+<ProductName>Postgres</ProductName> dynamic loading mechanism has been rewritten to use
+the dynamic loading mechanism provided by the operating 
+system.  This approach is generally faster, more  reliable  and
+more  portable  than our previous dynamic loading mechanism.
+The reason for this is that nearly all  modern  versions  of
+UNIX use a dynamic loading mechanism to implement shared 
+libraries and must therefore provide a fast and reliable 
+mechanism.   On  the  other  hand, the object file must be 
+postprocessed a bit before it can be loaded into  <ProductName>Postgres</ProductName>.   We
+hope  that  the large increase in speed and reliability will
+make up for the slight decrease in convenience.
+<Para>
+</Tip>
+  You should  expect  to read (and reread, and re-reread) the
+     manual pages for the C compiler, cc(1),  and  the  link
+     editor,  ld(1),  if  you  have  specific questions.  In
+     addition, the regression test suites in  the  directory
+     <FileName>PGROOT/src/regress</FileName> contain several 
+     working examples of this process.  If you copy  what  these
+     tests do, you should not have any problems.
+     The following terminology will be used below:
+<ItemizedList>
+<ListItem>
+<Para>
+     <FirstTerm>Dynamic loading</FirstTerm>
+          is  what  <ProductName>Postgres</ProductName>  does  to  an object file.  The
+          object file is copied into  the  running  <ProductName>Postgres</ProductName>
+          server  and the functions and variables within the
+          file are made available to  the  functions  within
+          the  <ProductName>Postgres</ProductName>  process.   <ProductName>Postgres</ProductName> does this using
+          the dynamic  loading  mechanism  provided  by  the
+          operating system.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+     <FirstTerm>Loading and link editing</FirstTerm>
+          is  what you do to an object file in order to produce 
+          another kind of object file  (e.g.,  an  executable 
+          program or a shared library).  You perform
+          this using the link editing program, ld(1).
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+<Para>
+     The following general restrictions and notes also apply
+     to the discussion below:
+<ItemizedList>
+<ListItem>
+<Para>
+Paths  given  to the create function command must be
+        absolute paths (i.e., start with "/") that refer  to
+        directories  visible  on  the  machine  on which the
+        <ProductName>Postgres</ProductName> server is running.
+<Tip>
+<Para>
+Relative paths do in fact work, 
+but  are  relative  to
+the directory where the database resides (which is generally
+invisible to the frontend application).  Obviously, it makes
+no sense to make the path relative to the directory in which
+the user started the frontend application, since the  server
+could be running on a completely different machine!
+</Para>
+</Tip>
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The  <ProductName>Postgres</ProductName> user must be able to traverse the path
+        given to the create function command and be able  to
+        read  the object file.  This is because the <ProductName>Postgres</ProductName>
+        server runs as the <ProductName>Postgres</ProductName> user, not  as  the  user
+        who  starts  up  the  frontend process.  (Making the
+        file or a higher-level directory  unreadable  and/or
+        unexecutable  by the "postgres" user is an extremely
+        common mistake.)
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Symbol names defined within object  files  must  not
+        conflict  with each other or with symbols defined in
+        <ProductName>Postgres</ProductName>.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The GNU C compiler usually does not provide the special  
+        options that are required to use the operating
+        system's dynamic loader interface.  In  such  cases,
+        the  C compiler that comes with the operating system
+        must be used.
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Sect1>
+<Title><Acronym>ULTRIX</Acronym></Title>
+
+<Para>
+     It is very  easy  to  build  dynamically-loaded  object
+     files  under  ULTRIX.  ULTRIX does not have any sharedlibrary 
+     mechanism and hence does not place any restrictions  on  
+     the  dynamic loader interface.  On the other
+     hand, we had to (re)write a non-portable dynamic loader
+     ourselves and could not use true shared libraries.
+     Under  ULTRIX,  the  only  restriction is that you must
+     produce each object file with the option -G 0.  (Notice
+     that  that's  the  numeral  ``0''  and  not  the letter
+     ``O'').  For example,
+<ProgramListing>
+# simple ULTRIX example
+% cc -G 0 -c foo.c
+</ProgramListing>
+     produces an object file called foo.o that can  then  be
+     dynamically  loaded into <ProductName>Postgres</ProductName>.  No additional loading or link-editing must be performed.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title><Acronym>DEC OSF/1</Acronym></Title>
+
+<Para>
+     Under DEC OSF/1, you can take any  simple  object  file
+     and produce a shared object file by running the ld command over it with the correct options.  The commands to
+     do this look like:
+<ProgramListing>
+# simple DEC OSF/1 example
+% cc -c foo.c
+% ld -shared -expect_unresolved '*' -o foo.so foo.o
+</ProgramListing>
+
+     The  resulting  shared  object  file can then be loaded
+     into <ProductName>Postgres</ProductName>.  When specifying the object file name to
+     the  create function command, one must give it the name
+     of the shared object file (ending in .so)  rather  than
+     the  simple  object  file.
+<Tip>
+<Para>
+Actually, <ProductName>Postgres</ProductName> does not care
+what  you  name  the
+file  as  long as it is a shared object file.  If you prefer
+to name your shared object files with the extension .o, this
+is fine with <ProductName>Postgres</ProductName> so long as you make sure that the correct 
+file name is given to the create function command.   In
+other words, you must simply be consistent.  However, from a
+pragmatic point of view, we discourage this practice because
+you  will undoubtedly confuse yourself with regards to which
+files have been made into shared object files and which have
+not.   For  example, it's very hard to write Makefiles to do
+the link-editing automatically if both the object  file  and
+the shared object file end in .o!
+</Para>
+</Tip>
+
+If the file you specify is
+     not a shared object, the backend will hang!
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>
+<Acronym>SunOS 4.x</Acronym>, <Acronym>Solaris 2.x</Acronym> and <Acronym>HP-UX</Acronym></Title>
+
+<Para>
+     Under SunOS 4.x, Solaris 2.x and HP-UX, the simple
+     object file must be created  by  compiling  the  source
+     file  with  special compiler flags and a shared library
+     must be produced.
+     The necessary steps with HP-UX are as follows.  The  +z
+     flag  to the HP-UX C compiler produces so-called 
+     "Position Independent Code" (PIC) and the  +u  flag  
+     removes
+     some  alignment restrictions that the PA-RISC architecture 
+     normally enforces.  The object file must be turned
+     into  a shared library using the HP-UX link editor with
+     the -b option.  This sounds complicated but is actually
+     very simple, since the commands to do it are just:
+<ProgramListing>
+# simple HP-UX example
+              &percnt; cc +z +u -c foo.c
+              &percnt; ld -b -o foo.sl foo.o
+</ProgramListing>
+</Para>
+
+<Para>
+     As with the .so files mentioned in the last subsection,
+     the create function command must be told which file  is
+     the  correct  file  to load (i.e., you must give it the
+     location of the shared library, or .sl file).
+     Under SunOS 4.x, the commands look like:
+<ProgramListing>
+# simple SunOS 4.x example
+              &percnt; cc -PIC -c foo.c
+              &percnt; ld -dc -dp -Bdynamic -o foo.so foo.o
+</ProgramListing>
+
+     and the equivalent lines under Solaris 2.x are:
+<ProgramListing>
+# simple Solaris 2.x example
+              &percnt; cc -K PIC -c foo.c
+                   or
+              &percnt; gcc -fPIC -c foo.c
+              &percnt; ld -G -Bdynamic -o foo.so foo.o
+</ProgramListing>
+</Para>
+
+<Para>
+     When linking shared libraries, you may have to  specify
+     some  additional  shared  libraries  (typically  system
+     libraries, such as the C and math libraries) on your ld
+     command line.
+</Para>
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/docguide.sgml b/doc/src/sgml/docguide.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..4b2a59602a3063ca4175dcd2e5cc1f3333c13c94
--- /dev/null
+++ b/doc/src/sgml/docguide.sgml
@@ -0,0 +1,347 @@
+<Appendix label="A">
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Thomas</FirstName>
+<Surname>Lockhart</Surname>
+</Author>
+</AuthorGroup>
+<Date>1998-02-26</Date>
+</DocInfo>
+
+<Title>Documentation</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> documentation is written using 
+the <FirstTerm>Standard Generalized Markup Language</FirstTerm>
+(<Acronym>SGML</Acronym>)
+<ULink url="http://www.ora.com/davenport/"><ProductName>DocBook</ProductName></ULink>
+<FirstTerm>Document Type Definition</FirstTerm> (<Acronym>DTD</Acronym>).
+
+<Para>
+Packaged documentation is available in both <FirstTerm>HTML</FirstTerm> and <FirstTerm>Postscript</FirstTerm>
+formats. These are available as part of the standard <ProductName>Postgres</ProductName> installation.
+We discuss here working with the documentation sources and generating documentation packages.
+
+<Note>
+<Para>
+This is the first release of new <ProductName>Postgres</ProductName> documentation in three years.
+The content and environment are in flux and still evolving.
+</Para>
+</Note>
+
+<Sect1>
+<Title>Introduction</Title>
+
+<Para>
+The purpose of <Acronym>SGML</Acronym> is to allow an author to specify the structure and content of
+a document (e.g. using the <ProductName>DocBook</ProductName> <Acronym>DTD</Acronym>), 
+and to have the document style define
+how that content is rendered into a final form
+(e.g. using Norm Walsh's stylesheets).
+
+<Para>
+See
+<ULink url="http://nis-www.lanl.gov/~rosalia/mydocs/docbook-intro.html">Introduction to DocBook</ULink>
+for a nice "quickstart" summary of DocBook features.
+<ULink url="http://www.ora.com/homepages/dtdparse/docbook/3.0/">DocBook Elements</ULink>
+provides a powerful cross-reference for features of <ProductName>DocBook</ProductName>.
+
+<Para>
+This documentation set is constructed using several tools,
+including James Clark's
+<ULink url="http://www.jclark.com/jade/"><ProductName>jade</ProductName></ULink>
+and Norm Walsh's 
+<ULink url="http://www.berkshire.net/~norm/docbook/dsssl">Modular DocBook Stylesheets</ULink>.
+
+<Para>
+Currently, hardcopy is produced by importing <FirstTerm>Rich Text Format</FirstTerm> (<Acronym>RTF</Acronym>)
+output from <Application>jade</Application> to <ProductName>ApplixWare</ProductName>
+for minor formatting fixups then exporting as a Postscript file.
+
+<Para>
+<ULink url="http://sunsite.unc.edu/pub/packages/TeX/systems/unix/"><ProductName>TeX</ProductName></ULink>
+is a supported format for <Application>jade</Application> output, but was not used at this time for
+several reasons, including the inability to make minor format fixes before committing to hardcopy and
+generally inadequate table support in the <ProductName>TeX</ProductName> stylesheets.
+
+<Sect1>
+<Title>Styles and Conventions</Title>
+
+<Para>
+<ProductName>DocBook</ProductName> has a rich set of tags and constructs, and a suprisingly large
+percentage are directly and obviously useful for well-formed documentation.
+The <ProductName>Postgres</ProductName> documentation set has only recently
+been adapted to <Acronym>SGML</Acronym>, and in the near future several sections of the set
+will be selected and maintained as prototypical examples of <ProductName>DocBook</ProductName>
+usage. Also, a short summary of <ProductName>DocBook</ProductName> tags will be included below.
+
+<!--
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE>SGML Constructs</TITLE>
+<TITLEABBREV>SGML Constructs</TITLEABBREV>
+<TGROUP COLS="2">
+<THEAD>
+  <ROW>
+    <ENTRY>SGML Tag</ENTRY>
+    <ENTRY>Usage</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+-->
+
+</Sect1>
+
+<Sect1>
+<Title>Building Documentation</Title>
+
+<Para>
+HTML documentation packages can be generated from the SGML source by typing
+
+<ProgramListing>
+% cd doc/src
+% make tutorial.tar.gz
+% make user.tar.gz
+% make admin.tar.gz
+% make programmer.tar.gz
+% make postgres.tar.gz
+% make install
+</ProgramListing>
+</Para>
+
+<Para>
+These packages can be installed from the main documentation directory by typing
+<ProgramListing>
+% cd doc
+% make install
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Toolsets</Title>
+
+<Sect2>
+<Title><ProductName>jade</ProductName></Title>
+
+<Para>
+The current stable release of <ProductName>jade</ProductName> is version 1.0.1.
+</Para>
+
+<Sect3>
+<Title>Installation for Linux</Title>
+
+<Para>
+Install <ULink url="ftp://ftp.cygnus.com/pub/home/rosalia/"><Acronym>RPMs</Acronym></ULink>
+for <ProductName>jade</ProductName> and related packages.
+</Para>
+</Sect3>
+
+<Sect3>
+<Title>Installation for non-Linux Platforms</Title>
+
+<Para>
+There are some other packaged distributions for jade. <ProductName>FreeBSD</ProductName> seems
+to have one available. Please report package status to the docs mailing list and we will
+include that information here.
+
+<Para>
+For other platforms, install <ULink url="ftp://ftp.cygnus.com/pub/eichin/docware/SOURCES/">sources</ULink>
+for <ProductName>jade</ProductName> and related packages and build from scratch.
+</Para>
+</Sect3>
+
+<Sect2>
+<Title><ProductName>Modular Style Sheets</ProductName></Title>
+
+<Para>
+The current stable release of the <ProductName>Modular Style Sheets</ProductName> is version 1.0.7.
+</Para>
+
+<Sect1>
+<Title>Hardcopy Generation for v6.3</Title>
+
+<Para>
+The hardcopy Postscript documentation is generated by converting the <Acronym>SGML</Acronym>
+source code to <Acronym>RTF</Acronym>, then importing into Applixware. After a little cleanup
+(see the following section) the output is "printed" to a postscript file.
+
+<Para>
+Some figures were redrawn to avoid having bitmap <Acronym>GIF</Acronym> files in the hardcopy
+documentation. One figure, of the system catalogs, was sufficiently complex that there was
+not time to redraw it. It was converted to fit using the following commands:
+
+<ProgramListing>
+% convert -v -geometry 400x400'>' figure03.gif con.gif
+% convert -v -crop 400x380 con.gif connections.gif
+</ProgramListing>
+
+<Sect2>
+<Title>RTF Cleanup Procedure</Title>
+
+<Para>
+Several items must be addressed in generating Postscript hardcopy:
+
+<Procedure>
+<Title>Applixware RTF Cleanup</Title>
+
+<Para>
+Applixware does not seem to do a complete job of importing RTF generated by jade/MSS. In particular,
+all text is given the <Quote>Header1</Quote> style attribute label, although the text formatting itself
+is acceptable. Also, the Table of Contents page numbers do not refer to the section listed in the
+table, but rather refer to the page of the ToC itself.
+
+<Step Performance="required">
+<Para>
+Generate the <Acronym>RTF</Acronym> input by typing
+<ProgramListing>
+% cd doc/src/sgml
+% make tutorial.rtf
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Open a new document in <ProductName>Applix Words</ProductName> and then import the RTF file.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Print out the existing Table of Contents, to mark up in the following few steps.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Insert figures into the document. Center each figure on the page using the centering margins button.
+
+<Para>
+Not all documents have figures. You can grep the SGML source files for the string <Quote>Graphic</Quote>
+to identify those parts of the documentation which may have figures. A few figures are replicated in
+various parts of the documentation.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Work through the document, adjusting page breaks and table column widths.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+If a bibliography is present, Applix Words seems to mark all remaining text after the first title
+as having an underlined attribute. Select all remaining text, turn off underlining using the underlining button,
+then explicitly underline each document and book title.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Work through the document, marking up the ToC hardcopy with the actual page number of each ToC entry.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Replace the right-justified incorrect page numbers in the ToC with correct values. This only takes a few
+minutes per document.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Save the document as native Applix Words format to allow easier last minute editing later.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Export the document to a file in Postscript format.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Compress the Postscript file using <Application>gzip</Application>. Place the compressed file into the
+<FileName>doc</FileName> directory.
+</Para>
+</Step>
+</Procedure>
+
+</Sect2>
+</Sect1>
+
+<Sect1>
+<Title>Alternate Toolsets</Title>
+
+<Para>
+The current stable release of <ProductName>sgml-tools</ProductName> is version 1.0.4.
+The v1.0 release includes some restructuring of the directory tree
+to more easily support additional document styles, possibly including <ProductName>DocBook</ProductName>.
+The only version of <ProductName>sgml-tools</ProductName> evaluated for <ProductName>Postgres</ProductName> was v0.99.0. 
+</Para>
+
+<Sect2>
+<Title><ProductName>sgml-tools</ProductName></Title>
+
+<Para>
+Install
+<ProductName>sgml-tools-0.99.0</ProductName>
+</Para>
+
+<Para>
+Apply 
+<ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/sgml-tools-patches-0.99.0.tar.gz">
+<ProductName>sgml-tools-patches</ProductName>
+</ULink>
+to the linuxdoc styles. These patches fix small problems with
+table formatting and with figure file names on conversion to postscript or html.
+</Para>
+
+<Sect2>
+<Title><ProductName>sgml2latex</ProductName></Title>
+
+<Para>
+The current stable release of <ProductName>sgml2latex</ProductName> is version 1.4.
+I have misplaced the original reference
+for this package, so will temporarily post it with this example.
+</Para>
+
+<Para>
+Install <ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/sgml2latex-format.1.4.tar.gz">
+<ProductName>sgml2latex</ProductName>
+</ULink>.
+</Para>
+
+<Sect2>
+<Title><ProductName>latex</ProductName></Title>
+
+<Para>
+Get and install <ProductName>texmf</ProductName>, <ProductName>teTeX</ProductName>,
+ or another package providing full tex/latex functionality.
+</Para>
+
+<Para>
+Add the 
+<ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/latex-styles-0.99.0.tar.gz">required styles</ULink>
+ linuxdoc-sgml.sty, linuxdoc-sgml-a4.sty isolatin.sty, qwertz.sty, and null.sty
+ to texmf/tex/latex/tools/ or the appropriate area.
+<ProgramListing>
+% cat latex-styles-0.99.0.tar.gz | (cd texmf/tex/latex/tools/; tar zxvf -)
+</ProgramListing>
+
+Run <ProductName>texhash</ProductName> to update the tex database.
+</Para>
+
+
+</Appendix>
diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..32fd459e52536b8a13a51ec9ec8f18ecaf280da3
--- /dev/null
+++ b/doc/src/sgml/ecpg.sgml
@@ -0,0 +1,836 @@
+<Chapter>
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Linux</FirstName>
+<Surname>Tolke</Surname>
+</Author>
+<Author>
+<FirstName>Michael</FirstName>
+<Surname>Meskes</Surname>
+</Author>
+</AuthorGroup>
+<Copyright>
+<Year>1996-1997</Year>
+<Holder>Linus Tolke</Holder>
+</Copyright>
+<Copyright>
+<Year>1998</Year>
+<Holder>Michael Meskes</Holder>
+</Copyright>
+<Date>Transcribed 1998-02-12</Date>
+</DocInfo>
+
+<Title><Application>ecpg</Application> - Embedded <Acronym>SQL</Acronym> in <Acronym>C</Acronym></Title>
+
+<Para>
+This describes an embedded <Acronym>SQL</Acronym> in <Acronym>C</Acronym> package for <ProductName>Postgres</ProductName>.
+
+It is written by <ULink url="mailto:linus@epact.se">Linus Tolke</ULink>
+and <ULink url="mailto:meskes@debian.org">Michael Meskes</ULink>.
+
+<Note>
+<Para>
+Permission is granted to copy and use in the same way as you are allowed
+to copy and use the rest of the <ProductName>PostgreSQL</ProductName>.
+</Para>
+</Note>
+
+<Sect1>
+<Title>Why Embedded <Acronym>SQL</Acronym>?</Title>
+
+<Para>
+Embedded <Acronym>SQL</Acronym> has some small advantages over other ways to handle <Acronym>SQL</Acronym>
+queries. It takes care of all the tedious moving of information to and
+from variables in your <Acronym>C</Acronym> program. Many <Acronym>RDBMS</Acronym> packages
+support this embedded language.
+
+<Para>
+There is an ANSI-standard describing how the embedded language should
+work. Most embedded <Acronym>SQL</Acronym> preprocessors I have seen and heard of make
+extensions so it is difficult to obtain portability between them
+anyway. I have not read the standard but I hope that my implementation
+does not deviate too much and that it would be possible to port programs
+with embedded <Acronym>SQL</Acronym> written for other <Acronym>RDBMS</Acronym> packages 
+to <ProductName>Postgres</ProductName> and thus
+promoting the spirit of free software.
+
+<Sect1>
+<Title>The Concept</Title>
+
+<Para>
+You write your program in <Acronym>C</Acronym> with some special <Acronym>SQL</Acronym> things.
+For declaring variables that can be used in <Acronym>SQL</Acronym> statements you need to
+put them in a special declare section.
+You use a special syntax for the <Acronym>SQL</Acronym> queries.
+
+<Para>
+Before compiling you run the file through the embedded <Acronym>SQL</Acronym> <Acronym>C</Acronym>
+preprocessor and it converts the <Acronym>SQL</Acronym> statements you used to function
+calls with the variables used as arguments. Both variables that are used
+as input to the <Acronym>SQL</Acronym> statements and variables that will contain the
+result are passed.
+
+<Para>
+Then you compile and at link time you link with a special library that
+contains the functions used. These functions (actually it is mostly one
+single function) fetches the information from the arguments, performs
+the <Acronym>SQL</Acronym> query using the ordinary interface (<FileName>libpq</FileName>) and puts back
+the result in the arguments dedicated for output.
+
+<Para>
+Then you run your program and when the control arrives to the <Acronym>SQL</Acronym>
+statement the <Acronym>SQL</Acronym> statement is performed against the database and you
+can continue with the result.
+
+
+<Sect1>
+<Title>How To Use <Application>egpc</Application></Title>
+
+<Para>
+This section describes how to use the <Application>egpc</Application> tool.
+
+<Sect2>
+<Title>Preprocessor
+
+<Para>
+The preprocessor is called <Application>ecpg</Application>. After installation it resides in
+the <ProductName>Postgres</ProductName> <FileName>bin/</FileName> directory. 
+
+<Sect2>
+<Title>Library
+
+<Para>
+The <Application>ecpg</Application> library is called <FileName>libecpg.a</FileName> or
+<FileName>libecpg.so</FileName>. Additionally, the library
+uses the <FileName>libpq</FileName> library for communication to the 
+<ProductName>Postgres</ProductName> server so you will
+have to link your program with <Parameter>-lecpg -lpq</Parameter>.
+
+<Para>
+The library has some methods that are "hidden" but that could prove very
+useful sometime.
+
+<VariableList>
+<VarListEntry>
+<Term>ECPGdebug(int, FILE *stream)</Term>
+<ListItem>
+<Para>
+If this is called, with the first argument non-zero, then debuglogging is turned
+on. Debuglogging is done on <Function>stream</Function>. Most <Acronym>SQL</Acronym> statement logs its
+arguments and result.
+
+<Para>
+The most important one (<Function>ECPGdo</Function>) that is called on all <Acronym>SQL</Acronym>
+statements except <Command>EXEC SQL COMMIT</Command>, <Command>EXEC SQL ROLLBACK</Command>, 
+<Command>EXEC SQL CONNECT</Command> logs both its expanded string, i.e. the string
+with all the input variables inserted, and the result from the
+<ProductName>Postgres</ProductName> server. This can be very useful when searching for errors
+in your <Acronym>SQL</Acronym> statements.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>ECPGstatus()</Term>
+<ListItem>
+<Para>
+This method returns TRUE if we are connected to a database and FALSE if not.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Sect2>
+<Title>Error handling
+
+<Para>
+To be able to detect errors from the <ProductName>Postgres</ProductName> server you include a line
+like
+<ProgramListing>
+exec sql include sqlca;
+</ProgramListing>
+in the include section of your file. This will define a struct and a
+variable with the name <Parameter>sqlca</Parameter> as following:
+<ProgramListing>
+struct sqlca {
+    int sqlcode;
+    struct {
+        int sqlerrml;
+        char sqlerrmc[1000];
+    } sqlerrm;
+} sqlca;
+</ProgramListing>
+
+<Para>
+If an error occured in the last <Acronym>SQL</Acronym> statement then <Parameter>sqlca.sqlcode</Parameter>
+will be non-zero. If <Parameter>sqlca.sqlcode</Parameter> is less that 0 then this is
+some kind of serious error, like the database definition does not match
+the query given. If it is bigger than 0 then this is a normal error like
+the table did not contain the requested row.
+
+<Para>
+sqlca.sqlerrm.sqlerrmc will contain a string that describes the error.
+The string ends with <Quote>line 23.</Quote> where the line is the line number
+in the source file (actually the file generated by the preprocessor but
+I hope I can fix this to be the line number in the input file.)
+
+<Para>
+List of errors that can occur:
+
+<VariableList>
+<VarListEntry>
+<Term>-1, Unsupported type %s on line %d.</Term>
+<ListItem>
+<Para>
+Does not normally occur. This is a sign that the preprocessor has
+generated something that the library does not know about. Perhaps you
+are running incompatible versions of the preprocessor and the library.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Too many arguments line %d.</Term>
+<ListItem>
+<Para>
+The preprocessor has goofed up and generated some incorrect code.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Too few arguments line %d.</Term>
+<ListItem>
+<Para>
+The preprocessor has goofed up and generated some incorrect code.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Error starting transaction line %d.</Term>
+<ListItem>
+<Para>
+<ProductName>Postgres</ProductName> signalled to us that we cannot open the connection.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Postgres error: %s line %d.</Term>
+<ListItem>
+<Para>
+Some <ProductName>Postgres</ProductName> error. The message contains the error message from the
+<ProductName>Postgres</ProductName> backend.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>1, Data not found line %d.</Term>
+<ListItem>
+<Para>
+This is a "normal" error that tells you that what you are quering cannot
+be found or we have gone through the cursor.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, To many matches line %d.</Term>
+<ListItem>
+<Para>
+This means that the query has returned several lines. The <Command>SELECT</Command>
+you made probably was not unique.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Not correctly formatted int type: %s line %d.</Term>
+<ListItem>
+<Para>
+This means that the host variable is of an <Type>int</Type> type and the field
+in the <ProductName>Postgres</ProductName> database is of another type and contains a value that
+cannot be interpreted as an <Type>int</Type>. The library uses <Function>strtol</Function>
+for this conversion.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Not correctly formatted unsigned type: %s line %d.</Term>
+<ListItem>
+<Para>
+This means that the host variable is of an <Type>unsigned int</Type> type and
+the field in the <ProductName>Postgres</ProductName> database is of another type and contains a
+value that cannot be interpreted as an <Type>unsigned int</Type>. The library
+uses <Function>strtoul</Function> for this conversion.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Not correctly formatted floating point type: %s line %d.</Term>
+<ListItem>
+<Para>
+This means that the host variable is of an <Type>float</Type> type and
+the field in the <ProductName>Postgres</ProductName> database is of another type and contains a
+value that cannot be interpreted as an <Type>float</Type>. The library
+uses <Function>strtod</Function> for this conversion.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Too few arguments line %d.</Term>
+<ListItem>
+<Para>
+This means that <ProductName>Postgres</ProductName> has returned more records than we have
+matching variables. Perhaps you have forgotten a couple of the host
+variables in the <Command>INTO :var1,:var2</Command>-list.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Too many arguments line %d.</Term>
+<ListItem>
+<Para>
+This means that <ProductName>Postgres</ProductName> has returned fewer records than we have
+host variables. Perhaps you have to many host variables in the 
+<Command>INTO :var1,:var2</Command>-list.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Empty query line %d.</Term>
+<ListItem>
+<Para>
+<ProductName>Postgres</ProductName> returned PGRES_EMPTY_QUERY.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Error: %s line %d.</Term>
+<ListItem>
+<Para>
+This means that <ProductName>Postgres</ProductName> returned on of the errors
+PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR or PGRES_BAD_RESPONSE. Which one
+and why is explained in the message.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Postgres error line %d.</Term>
+<ListItem>
+<Para>
+<ProductName>Postgres</ProductName> returns something that the library does not know how to
+handle. This is probably because the version of <ProductName>Postgres</ProductName> does not
+match the version of the <Application>ecpg</Application> library.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Error committing line %d.</Term>
+<ListItem>
+<Para>
+Error during <Command>COMMIT</Command>. <Command>EXEC SQL COMMIT</Command> is translated to an
+<Command>end</Command> operation in <ProductName>Postgres</ProductName> and that is the operation that could
+not be performed.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, Error rolling back line %d.</Term>
+<ListItem>
+<Para>
+Error during <Command>ROLLBACK</Command>. <Command>EXEC SQL ROLLBACK</Command> is translated to
+an <Command>abort</Command> operation in <ProductName>Postgres</ProductName> and that is the operation that
+could not be performed.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>-1, ECPGconnect: could not open database %s.</Term>
+<ListItem>
+<Para>
+The connect to the database did not work.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Sect2>
+
+<Sect1>
+<Title>Limitations</Title>
+
+<Para>
+What will never be included and why or what cannot be done with this
+concept.
+
+<VariableList>
+<VarListEntry>
+<Term>oracles single tasking possibility</Term>
+<ListItem>
+<Para>
+Oracle version 7.0 on AIX 3 uses the OS-supported locks on the shared
+memory segments and allows the application designer to link an
+application in a so called single tasking way. Instead of starting one
+client process per application process both the database part and the
+application part is run in the same process. In later versions of oracle
+this is no longer supported.
+
+<Para>
+This would require a total redesign of the <ProductName>Postgres</ProductName> access model and
+that effort can not justify the performance gained.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Sect1>
+<Title>Porting From Other <Acronym>RDBMS</Acronym> Packages</Title>
+
+<Para>
+To be written by persons that knows the different <Acronym>RDBMS</Acronym> packages and that
+actually does port something...
+
+<Sect1>
+<Title>Installation</Title>
+
+<Para>
+Since version 0.5 <Application>ecpg</Application> is distributed together with <ProductName>Postgres</ProductName>. So you
+should get your precompiler, libraries and header files compiled and
+installed on the fly.
+
+<Sect1>
+<Title>For the Developer</Title>
+
+<Para>
+This section is for those that wants to develop the <Application>ecpg</Application> interface. It
+describes how the things work. The ambition is to make this section
+contain things for those that want to have a look inside and the section
+on How to use it should be enough for all normal questions.
+
+So, read this before looking at the internals of the <Application>ecpg</Application>. If
+you are not interested in how it really works, skip this section.
+
+<Sect2>
+<Title>ToDo List</Title>
+
+<Para>
+This version the preprocessor has some flaws:
+
+<VariableList>
+<VarListEntry>
+<Term>Preprocessor output</Term>
+<ListItem>
+<Para>
+The variables should be static.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Preprocessor cannot do syntax checking on your <Acronym>SQL</Acronym> statements</Term>
+<ListItem>
+<Para>
+Whatever you write is copied more or less exactly to the <ProductName>Postgres</ProductName> and
+you will not be able to locate your errors until run-time.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>no restriction to strings only</Term>
+<ListItem>
+<Para>
+The PQ interface, and most of all the PQexec function, that is used by
+the <Application>ecpg</Application> relies on that the request is built up as a string. In some
+cases, like when the data contains the null character, this will be a
+serious problem.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>error codes</Term>
+<ListItem>
+<Para>
+There should be different error numbers for the different errors instead
+of just -1 for them all.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>library functions</Term>
+<ListItem>
+<Para>
+to_date et al.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>records</Term>
+<ListItem>
+<Para>
+Possibility to define records or structures in the declare section
+in a way that the record can be filled from one row in the database.
+
+<Para>
+This is a simpler way to handle an entire row at a time.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>array operations</Term>
+<ListItem>
+<Para>
+Oracle has array operations that enhances speed. When implementing it in
+<Application>ecpg</Application> it is done for compatibility reasons only. For them to
+improve speed would require a lot more insight in the <ProductName>Postgres</ProductName> internal
+mechanisms than I possess.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>indicator variables</Term>
+<ListItem>
+<Para>
+Oracle has indicator variables that tell if a value is <Type>null</Type> or if
+it is empty. This largely simplifies array operations and provides for a
+way to hack around some design flaws in the handling of <Type>VARCHAR2</Type>
+(like that an empty string isn't distinguishable from a
+<Type>null</Type> value). I am not sure if this is an Oracle extension or part
+of the ANSI standard.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>typedefs</Term>
+<ListItem>
+<Para>
+As well as complex types like records and arrays, typedefs would be
+a good thing to take care of.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>conversion of scripts</Term>
+<ListItem>
+<Para>
+To set up a database you need a few scripts with table definitions and
+other configuration parameters. If you have these scripts for an old
+database you would like to just apply them to get a <ProductName>Postgres</ProductName> database
+that works in the same way.
+
+<Para>
+To set up a database you need a few scripts with table definitions and
+The functionality could be accomplished with some conversion scripts.
+Speed will never be accomplished in this way. To do this you need a
+bigger insight in the database construction and the use of the database
+than could be realised in a script.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Sect2>
+<Title>The Preprocessor</Title>
+
+<Para>
+First four lines are written to the output. Two comments and two include
+lines necessary for the interface to the library. 
+
+<Para>
+Then the preprocessor works in one pass only reading the input file and
+writing to the output as it goes along. Normally it just echoes
+everything to the output without looking at it further.
+
+<Para>
+When it comes to an <Command>EXEC SQL</Command> statements it interviens and
+changes them depending on what iit is. The <Command>EXEC SQL</Command> statement can
+be one of these:
+
+<VariableList>
+<VarListEntry>
+<Term>Declare sections</Term>
+<ListItem>
+<Para>
+Declare sections begins with
+<ProgramListing>
+exec sql begin declare section;
+</ProgramListing>
+and ends with
+<ProgramListing>
+exec sql end declare section;
+</ProgramListing>
+In the section only variable declarations are allowed. Every variable
+declare within this section is also entered in a list of variables
+indexed on their name together with the corresponding type.
+
+<Para>
+The declaration is echoed to the file to make the variable a normal
+C-variable also.
+
+<Para>
+The special types VARCHAR and VARCHAR2 are converted into a named struct
+for every variable. A declaration like:
+<ProgramListing>
+VARCHAR var[180];
+</ProgramListing>
+is converted into
+<ProgramListing>
+struct varchar_var { int len; char arr[180]; } var;
+</ProgramListing>
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Include statements</Term>
+<ListItem>
+<Para>
+An include statement looks like:
+<ProgramListing>
+exec sql include filename;
+</ProgramListing>
+It is converted into
+<ProgramListing>
+#include &lt;filename.h&gt;
+</ProgramListing>
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Connect statement</Term>
+<ListItem>
+<Para>
+A connect statement looks like:
+<ProgramListing>
+exec sql connect '<Replaceable>database</Replaceable>';
+</ProgramListing>
+That statement is converted into
+<ProgramListing>
+ECPGconnect("<Replaceable>database</Replaceable>");
+</ProgramListing>
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Open cursor statement</Term>
+<ListItem>
+<Para>
+An open cursor statement looks like:
+<ProgramListing>
+exec sql open <Replaceable>cursor</Replaceable>;
+</ProgramListing>
+and is ignore and not copied from the output.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Commit statement</Term>
+<ListItem>
+<Para>
+A commit statement looks like
+<ProgramListing>
+exec sql commit;
+</ProgramListing>
+and is translated on the output to
+<ProgramListing>
+ECPGcommit(__LINE__);
+</ProgramListing>
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Rollback statement</Term>
+<ListItem>
+<Para>
+A rollback statement looks like
+<ProgramListing>
+exec sql rollback;
+</ProgramListing>
+and is translated on the output to
+<ProgramListing>
+ECPGrollback(__LINE__);
+</ProgramListing>
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Other statements</Term>
+<ListItem>
+<Para>
+Other <Acronym>SQL</Acronym> statements are other statements that start with 
+<Command>exec sql</Command> and ends with <Command>;</Command>. Everything inbetween is treated
+as an <Acronym>SQL</Acronym> statement and parsed for variable substitution.
+
+<Para>
+Variable substitution occur when a symbol starts with a colon
+(<Command>:</Command>). Then a variable with that name is found among the variables
+that were previously declared within a declare section and depending on
+whether or not the <Acronym>SQL</Acronym> statements knows it to be a variable for input or
+output the pointers to the variables are written to the output to allow
+for access by the function.
+
+<Para>
+For every variable that is part of the <Acronym>SQL</Acronym> request the function gets
+another five arguments.
+
+<SimpleList>
+<Member>The type as a special symbol</Member>
+<Member>A pointer to the value</Member>
+<Member>The size of the variable if it is a varchar</Member>
+<Member>Number of elements in the array (for array fetches)</Member>
+<Member>The offset to the next element in the array (for array fetches)</Member>
+</SimpleList>
+
+<Para>
+Since the array fetches are not implemented yet the two last arguments
+are not really important. They could perhaps have been left out.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Sect2>
+
+<Sect2>
+<Title>A Complete Example</Title>
+
+<Para>
+Here is a complete example describing the output of the preprocessor:
+<ProgramListing>
+exec sql begin declare section;
+int index;
+int result;
+exec sql end declare section;
+...
+    exec sql select res into :result from mytable where index = :index;
+</ProgramListing>
+is translated into:
+<ProgramListing>
+/* These two include files are added by the preprocessor */
+#include &lt;ecpgtype.h&gt;
+#include &lt;ecpglib.h&gt;
+/* exec sql begin declare section */
+
+ int index;
+ int result;
+/* exec sql end declare section */
+
+...
+    ECPGdo(__LINE__, "select res from mytable where index = ;;", 
+           ECPGt_int,&amp;index,0,0,sizeof(int), 
+           ECPGt_EOIT, 
+           ECPGt_int,&amp;result,0,0,sizeof(int), 
+           ECPGt_EORT );
+</ProgramListing>
+(the indentation in this manual is added for readability and not
+something that the preprocessor can do.)
+
+<Sect2>
+<Title>The Library</Title>
+
+<Para>
+The most important function in the library is the <Function>ECPGdo</Function>
+function. It takes a variable amount of arguments. Hopefully we wont run
+into machines with limits on the amount of variables that can be
+accepted by a varchar function. This could easily add up to 50 or so
+arguments.
+
+<Para>
+The arguments are:
+
+<VariableList>
+<VarListEntry>
+<Term>A line number</Term>
+<ListItem>
+<Para>
+This is a line number for the original line used in error messages only.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>A string</Term>
+<ListItem>
+<Para>
+This is the <Acronym>SQL</Acronym> request that is to be issued. This request is modified
+by the input variables, i.e. the variables that where not known at
+compile time but are to be entered in the request. Where the variables
+should go the string contains <Quote>;</Quote>.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Input variables</Term>
+<ListItem>
+<Para>
+As described in the section about the preprocessor every input variable
+gets five arguments.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>ECPGt_EOIT</Term>
+<ListItem>
+<Para>
+An enum telling that there are no more input variables.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Output variables</Term>
+<ListItem>
+<Para>
+As described in the section about the preprocessor every input variable
+gets five arguments. These variables are filled by the function.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>ECPGt_EORT</Term>
+<ListItem>
+<Para>
+An enum telling that there are no more variables.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Para>
+All the <Acronym>SQL</Acronym> statements are performed in one transaction unless you issue
+a commit transaction. This works so that the first transaction or the
+first after a commit or rollback always begins a transaction.
+
+<Para>
+To be completed: entries describing the other entries.
+
+</Chapter>
diff --git a/doc/src/sgml/environ.sgml b/doc/src/sgml/environ.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..64d9506423ea1e221c9df64472ef73a1126c0e82
--- /dev/null
+++ b/doc/src/sgml/environ.sgml
@@ -0,0 +1,62 @@
+<Chapter>
+<Title>Setting Up Your Environment</Title>
+
+<Para>
+     This section discusses how to set up
+     your own environment  so  that  you  can  use  frontend
+     applications.  We assume <ProductName>Postgres</ProductName> has already been 
+     successfully installed and started; refer to the Administrator's Guide
+and the installation  notes
+     for how to install Postgres.
+</Para>
+
+<Para>
+<ProductName>Postgres</ProductName> is a client/server application. As a user,
+you only need access to the client portions of the installation (an example
+of a client application is the interactive monitor <Application>psql</Application>).
+     For simplicity,
+     we will assume that <ProductName>Postgres</ProductName> has been installed in  the
+     directory  <FileName>/usr/local/pgsql</FileName>.   Therefore, wherever
+     you see the directory <FileName>/usr/local/pgsql</FileName> you  should
+     substitute  the name of the directory where <ProductName>Postgres</ProductName> is
+     actually installed.
+     All <ProductName>Postgres</ProductName> commands are installed  in  the  directory
+     <FileName>/usr/local/pgsql/bin</FileName>.   Therefore,  you should add
+     this directory to your shell command path.  If you  use
+     a variant of the Berkeley C shell, such as <Application>csh</Application> or <Application>tcsh</Application>,
+     you would add
+<ProgramListing>
+set path = ( /usr/local/pgsql/bin path )
+</ProgramListing>
+     in the <FileName>.login</FileName> file in your home directory.  If you  use
+     a  variant  of  the  Bourne  shell, such as <Application>sh</Application>, <Application>ksh</Application>, or
+     <Application>bash</Application>, then you would add
+<ProgramListing>
+PATH=/usr/local/pgsql/bin PATH
+export PATH
+</ProgramListing>
+     to the <FileName>.profile</FileName> file in your home directory.
+     From now on, we will assume that  you  have  added  the
+     <ProductName>Postgres</ProductName>  bin  directory to your path.  In addition, we
+     will make frequent reference to <Quote>setting a shell  
+     variable</Quote>  or  <Quote>setting an environment variable</Quote> throughout
+     this document.  If you did  not  fully  understand  the
+     last  paragraph  on  modifying  your  search  path, you
+     should consult the UNIX manual pages that describe your
+     shell before going any further.
+</Para>
+
+<Para>
+If your site administrator has not set things up in the
+default  way,  you may have some more work to do.  For example, if the database
+ server machine is a remote machine, you
+will need to set the <Acronym>PGHOST</Acronym> environment variable to the name
+of the database server machine.   The  environment  variable
+<Acronym>PGPORT</Acronym> may also have to be set.  The bottom line is this: if
+you try to start an application  program  and  it  complains
+that it cannot connect to the <Application>postmaster</Application>,
+ you should immediately consult your site administrator to make sure that your
+environment is properly set up.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..fe790b2542daf260f9497cb476b86921e391ca7a
--- /dev/null
+++ b/doc/src/sgml/extend.sgml
@@ -0,0 +1,250 @@
+<Chapter>
+<Title>Extending <Acronym>SQL</Acronym>: An Overview</Title>
+
+<Para>
+     In  the  sections  that follow, we will discuss how you
+     can extend the <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> query language by adding:
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+      functions
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      types
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      operators
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      aggregates
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+<Sect1>
+<Title>How Extensibility Works</Title>
+
+<Para>
+     <ProductName>Postgres</ProductName> is extensible because its operation  is  
+     catalog-driven.   If  you  are familiar with standard 
+     relational systems, you know that  they  store  information
+     about  databases,  tables,  columns,  etc., in what are
+     commonly known as system catalogs.  (Some systems  call
+     this  the data dictionary).  The catalogs appear to the
+     user as classes, like any other, but  the  <Acronym>DBMS</Acronym>  stores
+     its  internal  bookkeeping in them.  One key difference
+     between <ProductName>Postgres</ProductName> and  standard  relational  systems  is
+     that <ProductName>Postgres</ProductName> stores much more information in its 
+     catalogs -- not only information about tables and  columns,
+     but also information about its types, functions, access
+     methods, and so on.  These classes can be  modified  by
+     the  user, and since <ProductName>Postgres</ProductName> bases its internal operation 
+     on these classes, this means that <ProductName>Postgres</ProductName> can  be
+     extended   by   users.    By  comparison,  conventional
+     database systems can only be extended by changing hardcoded  
+     procedures within the <Acronym>DBMS</Acronym> or by loading modules
+     specially-written by the <Acronym>DBMS</Acronym> vendor.
+</Para>
+<Para>
+     <ProductName>Postgres</ProductName> is also unlike most  other  data  managers  in
+     that  the server can incorporate user-written code into
+     itself through dynamic loading.  That is, the user  can
+     specify  an  object code file (e.g., a compiled .o file
+     or shared library) that implements a new type or  function 
+     and <ProductName>Postgres</ProductName> will load it as required.  Code written 
+     in <Acronym>SQL</Acronym> are even more trivial to add to the  server.
+     This ability to modify its operation "on the fly" makes
+     <ProductName>Postgres</ProductName> uniquely suited for rapid prototyping  of  new
+     applications and storage structures.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>The <ProductName>Postgres</ProductName> Type System</Title>
+
+<Para>
+     The  <ProductName>Postgres</ProductName> type system can be broken down in several ways.
+     Types are divided into base types and composite  types.
+     Base  types  are those, like <FirstTerm>int4</FirstTerm>, that are implemented
+     in a language such as <ProductName>C</ProductName>.  They generally correspond  to
+     what are often known as "abstract data types"; <ProductName>Postgres</ProductName>
+     can only operate on such types through methods provided
+     by  the  user and only understands the behavior of such
+     types to the extent that the user describes them.  
+     Composite  types  are  created whenever the user creates a
+     class.  EMP is an example of a composite  type.   
+</Para>
+<Para>
+     <ProductName>Postgres</ProductName>  stores  these  types  in only one way (within the
+     file that stores all instances of the  class)  but  the
+     user can "look inside" at the attributes of these types
+     from the query language and optimize their retrieval by
+     (for example) defining indices on the attributes.
+     <ProductName>Postgres</ProductName>  base  types are further divided into built-in
+     types and user-defined  types.   Built-in  types  (like
+     <FirstTerm>int4</FirstTerm>)  are  those  that  are  compiled into the system.
+     User-defined types are those created by the user in the
+     manner to be described below.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>About the <ProductName>Postgres</ProductName> System Catalogs</Title>
+
+<Para>
+     Having  introduced the basic extensibility concepts, we
+     can now take a look at how the  catalogs  are  actually
+     laid  out.  You can skip this section for now, but some
+     later sections will  be  incomprehensible  without  the
+     information  given  here,  so  mark this page for later
+     reference.
+     All system catalogs have names  that  begin  with  <FirstTerm>pg_</FirstTerm>.
+     The  following  classes contain information that may be
+     useful to the end user.  (There are many  other  system
+     catalogs,  but there should rarely be a reason to query
+     them directly.)
+
+<TABLE TOCENTRY="1">
+<TITLE>Postgres System Catalogs</TITLE>
+<TITLEABBREV>Catalogs</TITLEABBREV>
+<TGROUP COLS="2">
+<THEAD>
+<ROW>
+<ENTRY>Catalog Name</ENTRY>
+<ENTRY>Description</ENTRY>
+</ROW>
+</THEAD>
+<TBODY>
+<ROW>
+<ENTRY>pg_database</ENTRY>
+<ENTRY> databases</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_class</ENTRY>
+<ENTRY> classes</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_attribute</ENTRY>
+<ENTRY> class attributes</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_index</ENTRY>
+<ENTRY> secondary indices</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_proc</ENTRY>
+<ENTRY> procedures (both C and SQL)</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_type</ENTRY>
+<ENTRY> types (both base and complex)</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_operator</ENTRY>
+<ENTRY> operators</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_aggregate</ENTRY>
+<ENTRY> aggregates and aggregate functions</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_am</ENTRY>
+<ENTRY> access methods</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_amop</ENTRY>
+<ENTRY> access method operators</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_amproc</ENTRY>
+<ENTRY> access method support functions</ENTRY>
+</ROW>
+<ROW>
+<ENTRY>pg_opclass</ENTRY>
+<ENTRY> access method operator classes</ENTRY>
+</ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+<Figure Id="EXTEND-CATALOGS" Float="1">
+<Title>The major <ProductName>Postgres</ProductName> system catalogs</Title>
+<Graphic Align="center" FileRef="catalogs.gif" Format="GIF"></Graphic>
+</Figure>
+
+     The Reference Manual gives a more detailed  explanation
+     of  these catalogs and their attributes.  However,
+<XRef LinkEnd="EXTEND-CATALOGS" EndTerm="EXTEND-CATALOGS">
+     shows the major entities and their  relationships
+     in  the system catalogs.  (Attributes that do not refer
+     to other entities are not shown unless they are part of
+     a primary key.)
+     This diagram is more or less incomprehensible until you
+     actually start looking at the contents of the  catalogs
+     and  see  how  they relate to each other.  For now, the
+     main things to take away from this diagram are as  follows:
+     
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+      In  several of the sections that follow, we will
+            present various join queries on the system 
+            catalogs  that display information we need to extend
+            the system.  Looking at this diagram should make
+            some  of  these  join  queries  (which are often
+            three- or four-way joins)  more  understandable,
+            because  you  will  be  able  to  see  that  the
+            attributes used in the queries form foreign keys
+            in other classes.
+</Para>
+</ListItem>
+<ListItem>
+<Para>  Many  different  features  (classes, attributes,
+            functions,  types,  access  methods,  etc.)  are
+            tightly  integrated  in  this  schema.  A simple
+            create command may modify many  of  these  catalogs.
+</Para>
+</ListItem>
+<ListItem>
+<Para>  Types and procedures
+            are central to the schema.
+
+<Note>
+<Para>
+We  use  the words <FirstTerm>procedure</FirstTerm> and <FirstTerm>function</FirstTerm> more or less
+interchangably.
+</Para>
+</Note>
+
+            Nearly  every catalog contains some reference to
+            instances in one or both of these classes.   For
+            example,  <ProductName>Postgres</ProductName>  frequently  uses type 
+            signatures (e.g.,  of  functions  and  operators)  to
+            identify unique instances of other catalogs.
+
+</Para>
+</ListItem>
+<ListItem>
+<Para>  There are many attributes and relationships that
+            have obvious meanings, but there are many  
+            (particularly  those  that  have  to  do with access
+            methods) that do not.  The relationships between
+            pg_am,   pg_amop,   pg_amproc,  pg_operator  and
+            pg_opclass are particularly hard  to  understand
+            and  will  be described in depth (in the section
+            on interfacing types and operators  to  indices)
+            after we have discussed basic extensions.
+</ListItem>
+</ItemizedList>
+
+</Para>
+</Chapter>
diff --git a/doc/src/sgml/func-ref.sgml b/doc/src/sgml/func-ref.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..66f476fb2e9d21ad362c679a4e2408467e05a171
--- /dev/null
+++ b/doc/src/sgml/func-ref.sgml
@@ -0,0 +1,19 @@
+<Chapter>
+<Title>Functions</Title>
+
+<Abstract>
+<Para>
+Reference information for user-callable functions.
+</Para>
+</Abstract>
+
+<Note>
+<Para>
+This section needs to be written. Volunteers?
+</Para>
+</Note>
+
+<Para>
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/geqo.sgml b/doc/src/sgml/geqo.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..725504c28fb991cf8d2638374d274c341e0236a8
--- /dev/null
+++ b/doc/src/sgml/geqo.sgml
@@ -0,0 +1,228 @@
+<Chapter>
+<DocInfo>
+<Author>
+<FirstName>Martin</FirstName>
+<SurName>Utesch</SurName>
+</Author>
+</DocInfo>
+
+<Title>Genetic Query Optimization in Database Systems</Title>
+
+<Para>
+<ProgramListing>
+<ULink url="utesch@aut.tu-freiberg.de">Martin Utesch</ULink>
+
+          Institute of Automatic Control
+        University of Mining and Technology
+                 Freiberg, Germany
+
+                    02/10/1997
+
+
+1.) Query Handling as a Complex Optimization Problem
+====================================================
+
+   Among all relational operators the most difficult one to process and
+optimize is the JOIN. The number of alternative plans to answer a query
+grows exponentially with the number of JOINs included in it. Further
+optimization effort is caused by the support of a variety of *JOIN
+methods* (e.g., nested loop, index scan, merge join in Postgres) to
+process individual JOINs and a diversity of *indices* (e.g., r-tree,
+b-tree, hash in Postgres) as access paths for relations.
+
+   The current Postgres optimizer implementation performs a *near-
+exhaustive search* over the space of alternative strategies. This query
+optimization technique is inadequate to support database application
+domains that involve the need for extensive queries, such as artificial
+intelligence.
+
+   The Institute of Automatic Control at the University of Mining and
+Technology, in Freiberg, Germany, encountered the described problems as its
+folks wanted to take the Postgres DBMS as the backend for a decision
+support knowledge based system for the maintenance of an electrical
+power grid. The DBMS needed to handle large JOIN queries for the
+inference machine of the knowledge based system.
+
+   Performance difficulties within exploring the space of possible query
+plans arose the demand for a new optimization technique being developed.
+
+   In the following we propose the implementation of a *Genetic
+Algorithm* as an option for the database query optimization problem.
+
+
+2.) Genetic Algorithms (GA)
+===========================
+
+   The GA is a heuristic optimization method which operates through 
+determined, randomized search. The set of possible solutions for the
+optimization problem is considered as a *population* of *individuals*.
+The degree of adaption of an individual to its environment is specified
+by its *fitness*.
+
+   The coordinates of an individual in the search space are represented
+by *chromosomes*, in essence a set of character strings. A *gene* is a
+subsection of a chromosome which encodes the value of a single parameter
+being optimized. Typical encodings for a gene could be *binary* or
+*integer*.
+
+   Through simulation of the evolutionary operations *recombination*,
+*mutation*, and *selection* new generations of search points are found
+that show a higher average fitness than their ancestors.
+
+   According to the "comp.ai.genetic" FAQ it cannot be stressed too
+strongly that a GA is not a pure random search for a solution to a
+problem. A GA uses stochastic processes, but the result is distinctly
+non-random (better than random). 
+
+Structured Diagram of a GA:
+---------------------------
+
+P(t)    generation of ancestors at a time t
+P''(t)  generation of descendants at a time t
+
++=========================================+
+|>>>>>>>>>>>  Algorithm GA  <<<<<<<<<<<<<<|
++=========================================+
+| INITIALIZE t := 0                       |
++=========================================+
+| INITIALIZE P(t)                         |
++=========================================+
+| evalute FITNESS of P(t)                 |
++=========================================+
+| while not STOPPING CRITERION do         |
+|   +-------------------------------------+
+|   | P'(t)  := RECOMBINATION{P(t)}       |
+|   +-------------------------------------+
+|   | P''(t) := MUTATION{P'(t)}           |
+|   +-------------------------------------+
+|   | P(t+1) := SELECTION{P''(t) + P(t)}  |
+|   +-------------------------------------+
+|   | evalute FITNESS of P''(t)           |
+|   +-------------------------------------+
+|   | t := t + 1                          |
++===+=====================================+
+
+
+3.) Genetic Query Optimization (GEQO) in PostgreSQL
+===================================================
+
+   The GEQO module is intended for the solution of the query
+optimization problem similar to a traveling salesman problem (TSP).
+Possible query plans are encoded as integer strings. Each string
+represents the JOIN order from one relation of the query to the next.
+E. g., the query tree  /\
+                      /\ 2
+                     /\ 3
+                    4  1  is encoded by the integer string '4-1-3-2',
+which means, first join relation '4' and '1', then '3', and
+then '2', where 1, 2, 3, 4 are relids in PostgreSQL.
+
+   Parts of the GEQO module are adapted from D. Whitley's Genitor
+algorithm.
+
+   Specific characteristics of the GEQO implementation in PostgreSQL
+are:
+
+o  usage of a *steady state* GA (replacement of the least fit
+   individuals in a population, not whole-generational replacement)
+   allows fast convergence towards improved query plans. This is
+   essential for query handling with reasonable time;
+
+o  usage of *edge recombination crossover* which is especially suited
+   to keep edge losses low for the solution of the TSP by means of a GA;
+
+o  mutation as genetic operator is deprecated so that no repair
+   mechanisms are needed to generate legal TSP tours.
+
+   The GEQO module gives the following benefits to the PostgreSQL DBMS
+compared to the Postgres query optimizer implementation:
+
+o  handling of large JOIN queries through non-exhaustive search;
+
+o  improved cost size approximation of query plans since no longer
+   plan merging is needed (the GEQO module evaluates the cost for a
+   query plan as an individual).
+
+
+References
+==========
+
+J. Heitk"otter, D. Beasley:
+---------------------------
+   "The Hitch-Hicker's Guide to Evolutionary Computation",
+   FAQ in 'comp.ai.genetic',
+   'ftp://ftp.Germany.EU.net/pub/research/softcomp/EC/Welcome.html'
+
+Z. Fong:
+--------
+   "The Design and Implementation of the Postgres Query Optimizer",
+   file 'planner/Report.ps' in the 'postgres-papers' distribution
+
+R. Elmasri, S. Navathe:
+-----------------------
+   "Fundamentals of Database Systems",
+   The Benjamin/Cummings Pub., Inc.
+
+
+=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+*         Things left to done for the PostgreSQL                    *
+=           Genetic Query Optimization (GEQO)                       =
+*              module implementation                                *
+=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+* Martin Utesch		      * Institute of Automatic Control      *
+=                             = University of Mining and Technology =
+* utesch@aut.tu-freiberg.de   * Freiberg, Germany                   *
+=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+
+
+1.) Basic Improvements
+===============================================================
+
+a) improve freeing of memory when query is already processed:
+-------------------------------------------------------------
+with large JOIN queries the computing time spent for the genetic query
+optimization seems to be a mere *fraction* of the time Postgres
+needs for freeing memory via routine 'MemoryContextFree',
+file 'backend/utils/mmgr/mcxt.c';
+debugging showed that it get stucked in a loop of routine
+'OrderedElemPop', file 'backend/utils/mmgr/oset.c';
+the same problems arise with long queries when using the normal
+Postgres query optimization algorithm;
+
+b) improve genetic algorithm parameter settings:
+------------------------------------------------
+file 'backend/optimizer/geqo/geqo_params.c', routines
+'gimme_pool_size' and 'gimme_number_generations';
+we have to find a compromise for the parameter settings
+to satisfy two competing demands:
+1.  optimality of the query plan
+2.  computing time
+
+c) find better solution for integer overflow:
+---------------------------------------------
+file 'backend/optimizer/geqo/geqo_eval.c', routine
+'geqo_joinrel_size';
+the present hack for MAXINT overflow is to set the Postgres integer
+value of 'rel->size' to its logarithm;
+modifications of 'struct Rel' in 'backend/nodes/relation.h' will
+surely have severe impacts on the whole PostgreSQL implementation.
+
+d) find solution for exhausted memory:
+--------------------------------------
+that may occur with more than 10 relations involved in a query,
+file 'backend/optimizer/geqo/geqo_eval.c', routine
+'gimme_tree' which is recursively called;
+maybe I forgot something to be freed correctly, but I dunno what;
+of course the 'rel' data structure of the JOIN keeps growing and
+growing the more relations are packed into it;
+suggestions are welcome :-(
+
+
+2.) Further Improvements
+===============================================================
+Enable bushy query tree processing within PostgreSQL;
+that may improve the quality of query plans.
+
+</ProgramListing>
+</Para>
+</Chapter>
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..c522d2fa936c24749c5047f3c24b0cb3207a2c8b
--- /dev/null
+++ b/doc/src/sgml/gist.sgml
@@ -0,0 +1,98 @@
+<Chapter>
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Gene</FirstName>
+<Surname>Selkov</Surname>
+</Author>
+</AuthorGroup>
+<Date>Transcribed 1998-02-19</Date>
+</DocInfo>
+<Title>GiST Indices</Title>
+
+<Para>
+<Note>
+<Title>Caveat</Title>
+<Para>
+This extraction from an e-mail sent by 
+<ULink url="mailto:selkovjr@mcs.anl.gov">Eugene Selkov Jr.</ULink>
+contains good information
+on GiST. Hopefully we will learn more in the future and update this information.
+- thomas
+</Para>
+</Note>
+
+<Para>
+Well, I can't say I quite understand what's going on, but at least
+I (almost) succeeded in porting GiST examples to linux. The GiST access
+method is already in the postgres tree (<FileName>src/backend/access/gist</FileName>).
+
+<Para>
+<ULink url="ftp://s2k-ftp.cs.berkeley.edu/pub/gist/pggist/pggist.tgz">Examples at Berkeley</ULink>
+come with an overview of the methods and demonstrate spatial index 
+mechanisms for 2D boxes, polygons, integer intervals and text
+(see also <ULink url="http://gist.cs.berkeley.edu:8000/gist/">GiST at Berkeley</ULink>).
+In the box example, we
+are supposed to see a performance gain when using the GiST index; it did
+work for me but I do not have a reasonably large collection of boxes
+to check that. Other examples also worked, except polygons: I got an 
+error doing
+
+<ProgramListing>
+test=> create index pix on polytmp using gist (p:box gist_poly_ops) with
+(islossy);
+ERROR:  cannot open pix
+
+(PostgreSQL 6.3               Sun Feb  1 14:57:30 EST 1998)
+</ProgramListing>
+
+<Para>
+I could not get sense of this error message; it appears to be something
+we'd rather ask the developers about (see also Note 4 below). What I
+would suggest here is that someone of you linux guys (linux==gcc?) fetch the 
+original sources quoted above and apply my patch (see attachment) and 
+tell us what you feel about it. Looks cool to me, but I would not like 
+to hold it up while there are so many competent people around.
+
+<Para>
+A few notes on the sources:
+
+<Para>
+1. I failed to make use of the original (HPUX) Makefile and rearranged
+   the Makefile from the ancient postgres95 tutorial to do the job. I
+tried
+   to keep it generic, but I am a very poor makefile writer -- just did
+   some monkey work. Sorry about that, but I guess it is now a little
+   more portable that the original makefile.
+
+<Para>
+2. I built the example sources right under pgsql/src (just extracted the
+   tar file there). The aforementioned Makefile assumes it is one level
+   below pgsql/src (in our case, in pgsql/src/pggist).
+
+<Para>
+3. The changes I made to the *.c files were all about #include's,
+   function prototypes and typecasting. Other than that, I just threw 
+   away a bunch of unused vars and added a couple parentheses to please
+   gcc. I hope I did not screw up too much :)
+
+<Para>
+4. There is a comment in polyproc.sql:
+
+<ProgramListing>
+-- -- there's a memory leak in rtree poly_ops!!
+-- -- create index pix2 on polytmp using rtree (p poly_ops);
+</ProgramListing>
+
+   Roger that!! I thought it could be related to a number of
+   <ProductName>Postgres</ProductName> versions
+   back and tried the query. My system went nuts and I had to shoot down
+   the postmaster in about ten minutes.
+
+
+<Para>
+I will continue to look into GiST for a while, but I would also
+appreciate
+more examples of R-tree usage.
+
+</Chapter>
diff --git a/doc/src/sgml/inherit.sgml b/doc/src/sgml/inherit.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..be2bcfa237fe1834fe3d266eece793f405359d8b
--- /dev/null
+++ b/doc/src/sgml/inherit.sgml
@@ -0,0 +1,87 @@
+<Chapter>
+<Title>Inheritance</Title>
+
+<Para>
+     Let's create two classes. The capitals  class  contains
+     state  capitals  which  are also cities. Naturally, the
+     capitals class should inherit from cities.
+     
+<ProgramListing>
+CREATE TABLE cities (
+    name            text,
+    population      float,
+    altitude        int            -- (in ft)
+);
+
+CREATE TABLE capitals (
+    state           char2
+) INHERITS (cities);
+</ProgramListing>
+
+     In this case, an  instance  of  capitals  <FirstTerm>inherits</FirstTerm>  all
+     attributes  (name,  population,  and altitude) from its
+     parent, cities.  The type  of  the  attribute  name  is
+     <Type>text</Type>,  a  native  <ProductName>Postgres</ProductName>  type  for variable length
+     ASCII strings.  The type of the attribute population is
+     <Type>float</Type>,  a  native <ProductName>Postgres</ProductName> type for double precision
+     floating point numbers.  State capitals have  an  extra
+     attribute, state, that shows their state.  In <ProductName>Postgres</ProductName>,
+     a  class  can inherit from zero or more other classes,
+     and a query can reference either  all  instances  of  a
+     class  or  all  instances  of  a  class plus all of its
+     descendants. 
+<Note>
+<Para>
+The inheritance hierarchy is a actually a directed acyclic graph.
+</Para>
+</Note>
+For example, the  following  query  finds
+     all  the cities that are situated at an attitude of 500ft or higher:
+     
+<ProgramListing>
+SELECT name, altitude
+    FROM cities
+    WHERE altitude &gt; 500;
+
++----------+----------+
+|name      | altitude |
++----------+----------+
+|Las Vegas | 2174     |
++----------+----------+
+|Mariposa  | 1953     |
++----------+----------+
+</ProgramListing>         
+
+<Para>
+     On the other hand, to find the  names  of  all  cities,
+     including  state capitals, that are located at an altitude 
+     over 500ft, the query is:
+
+<ProgramListing>
+SELECT c.name, c.altitude
+    FROM cities* c
+    WHERE c.altitude > 500;
+</ProgramListing>
+
+     which returns:
+     
+<ProgramListing>
++----------+----------+
+|name      | altitude |
++----------+----------+
+|Las Vegas | 2174     |
++----------+----------+
+|Mariposa  | 1953     |
++----------+----------+
+|Madison   | 845      |
++----------+----------+
+</ProgramListing>
+
+     Here the <Quote>*</Quote> after cities indicates that the query should
+     be  run over cities and all classes below cities in the
+     inheritance hierarchy.  Many of the  commands  that  we
+     have  already discussed -- <Command>select</Command>, <Command>update</Command> and <Command>delete</Command> --
+     support this <Quote>*</Quote> notation, as do others, like <Command>alter</Command>.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/install.sgml b/doc/src/sgml/install.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..06b284882fe350109830ffef50069476d829d502
--- /dev/null
+++ b/doc/src/sgml/install.sgml
@@ -0,0 +1,1032 @@
+<Chapter>
+<Title>Installation</Title>
+
+<Abstract>
+<Para>
+Complete installation instructions for <ProductName>Postgres</ProductName> v6.3.
+</Para>
+</Abstract>
+
+<Para>
+  This procedure is
+This is based on the installation instructions 
+for <ProductName>Postgres</ProductName> v6.3
+found in <FileName>&dollar;PGROOT/INSTALL</FileName>.
+  Up to date information on <ProductName>Postgres</ProductName> may be found at
+<ULink url="http://www.postgresql.org">www.postgresql.org</ULink>.
+</Para>
+
+<Para>
+The installation notes below assume the following (except where noted):
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+Commands are Unix-compatible. See note below.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Defaults are used except where noted.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+User postgres is the <ProductName>Postgres</ProductName> superuser.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The source path is /usr/src/pgsql (other paths are possible).
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The runtime path is /usr/local/pgsql (other paths are possible).
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+Commands were tested on RedHat Linux version 4.2 using the tcsh shell.
+Except where noted, they will probably work on most systems. Commands
+like ps and tar vary wildly on what options you should use on each
+platform. <Emphasis>Use common sense</Emphasis> before typing in these commands.
+</Para>
+
+<Para>
+Our Makefiles require GNU <Application>make</Application> (called <Quote>gmake</Quote> in this document) and
+also assume that <Application>install</Application> accepts BSD options. The INSTALL
+variable in the Makefiles is set to the BSD-compatible version of
+<Application>install</Application>. On some systems, you will have to find a BSD-compatible
+<Application>install</Application> (eg. <Application>bsdinst</Application>, which comes with the MIT X Window System
+distribution).
+</Para>
+
+<Sect1>
+<Title>Requirements to Run <ProductName>Postgres</ProductName></Title>
+
+<Para>
+Information on supported platforms is another chapter. In general, most Unix-compatible
+platforms with modern libraries should be able to run <ProductName>Postgres</ProductName>.
+
+<Para>
+You should have at least 8 MB of memory and at least 45 MB of disk space
+to hold the source, binaries, and user databases.  After installation
+you may reduce this to about 3 Mbytes plus space for user databases.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Installation Procedure</Title>
+
+<Para>
+<Procedure>
+<Title><ProductName>Postgres</ProductName> Installation</Title>
+
+<Para>
+For a fresh install or upgrading from previous releases of
+<ProductName>Postgres</ProductName>:
+</Para>
+
+<Step Performance="required">
+<Para>
+Read any last minute information and platform specific porting
+     notes.  There are some platform specific notes at the end of this
+     file for Ultrix4.x, Linux, BSD/OS and NeXT.  There are other
+     files in directory <FileName>/usr/src/pgsql/doc</FileName>, including files FAQ-Irix
+     and FAQ-Linux.  Also look in directory
+<ULink url="ftp://ftp.postgresql.org/pub">ftp://ftp.postgresql.org/pub</ULink>.
+     If there is a file called INSTALL in this directory then this
+     file will contain the latest installation information.
+</Para>
+
+<Para>
+     Please note that a "tested" platform in the list given earlier
+     simply means that someone went to the effort at some point of making
+     sure that a <ProductName>Postgres</ProductName> distribution would compile and run on this
+     platform without modifying the code.  Since the current developers
+     will not have access to all of these platforms, some of them may not
+     compile cleanly and pass the regression tests in the current
+     release due to minor problems.  Any such known problems and their
+     solutions will be posted in 
+<ULink url="ftp://ftp.postgresql.org/pub/INSTALL">ftp://ftp.postgresql.org/pub/INSTALL</ULink>.
+</Para>
+</Step>
+
+<Step Performance="optional">
+<Para>
+Create account postgres if it does not already exist.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Log into account postgres.
+</Para>
+
+<SubSteps>
+<Step Performance="required">
+<Para>
+Check that you have sufficient disk space.  You will need about
+      17 Mbytes for /usr/src/pgsql, about 2 Mbytes for /usr/local/pgsql
+      (excluding your database) and 1 Mbyte for an empty database.
+      The database will temporarily grow to about 20 Mbytes during the
+      regression tests.  You will also need about 3 Mbytes for the
+      distribution tar file.
+</Para>
+
+<Para>
+      We therefore recommend that during installation and testing you
+      have well over 20 Mbytes free under /usr/local and another 25 Mbytes
+      free on the disk partition containing your database.  Once you
+      delete the source files, tar file and regression database, you
+      will need 2 Mbytes for /usr/local/pgsql, 1 Mbyte for the empty
+      database, plus about five times the space you would require to
+      store your database data in a flat file.
+</Para>
+
+<Para>
+      To check for disk space, use <Command>df -k</Command>.
+</Para>
+</Step>
+</SubSteps>
+</Step>
+
+<Step Performance="required">
+<Para>
+Ftp file ftp://ftp.postgresql.org/pub/postgresql-v6.3.tar.gz from the
+     Internet.  Store it in your home directory.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Some platforms use flex.  If your system uses flex then make sure
+     you have a good version.  To check, type <Command>flex --version</Command>.
+</Para>
+
+<Para>
+     If the flex command is not found then you probably do not need it.
+     If the version is 2.5.2 or 2.5.4 or greater then you are okay.  If it
+     is 2.5.3 or before 2.5.2 then you will have to upgrade flex.  You may
+     get it at ftp://prep.ai.mit.edu/pub/gnu/flex-2.5.4.tar.gz.
+</Para>
+
+<Para>
+     If you need flex and don't have it or have the wrong version, then
+     you will be told so when you attempt to compile the program.  Feel
+     free to skip this step if you aren't sure you need it.  If you do
+     need it then you will be told to install/upgrade flex when you try to
+     compile.
+</Para>
+
+<Para>
+     To install it, type the following:
+<ProgramListing>
+    cd
+    gunzip -c flex-2.5.4.tar.gz | tar xvf -
+    cd flex-2.5.4
+    configure --prefix=/usr
+    make
+    make check
+    # You must be root when typing the next line.
+    make install
+    cd
+    rm -rf flex-2.5.4
+</ProgramListing>
+</Para>
+
+<Para>
+     This will update files /usr/man/man1/flex.1, /usr/bin/flex,
+     /usr/lib/libfl.a, /usr/include/FlexLexer.h and will add link
+     /usr/bin/flex++ which points to flex.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+If you are upgrading an existing system then back up your database.
+     For alpha- and beta-level releases, the database format is liable
+     to change often every few weeks with no notice besides a quick comment
+     in the HACKERS mailing list.  Full releases always require a dump/reload
+     from previous releases.  It is therefore a bad idea to skip this
+     step.  Also, do not use the pg_dumpall script from v6.0 or everything
+     will be owned by the <ProductName>Postgres</ProductName> super user.
+  Type (with the gunzip line
+     and the following line typed as one line):
+<ProgramListing>
+    cd
+    gunzip -c postgresql-v6.3.tar.gz |
+    tar xvf - src/bin/pg_dump/pg_dumpall
+    chmod a+x src/bin/pg_dump/pg_dumpall
+    src/bin/pg_dump/pg_dumpall > db.out
+    rm -rf src
+</ProgramListing>
+</Para>
+
+<Para>
+     If you wish to preserve object id's (oids), then use the -o
+     option when running pg_dumpall.  However, unless you have a
+     special reason for doing this, don't do it.
+</Para>
+
+<Para>
+     If the pg_dumpall command seems to take a long time and you think
+     it might have died, then, from another terminal, use "ls -l db.out"
+     several times to see if the size of the file is growing.
+</Para>
+
+<Para>
+     Please note that if you are upgrading from a version prior to
+     <ProductName>Postgres95</ProductName> v1.09 then you must back up your database, install
+     <ProductName>Postgres95</ProductName> v1.09, restore your database, then back it up again.
+     You should also read files /usr/src/pgsql/migration/*.
+</Para>
+
+<Para>
+     You must make sure that your database is not updated in the middle of
+     your backup.  If necessary, bring down postmaster, edit the permissions
+     in file /usr/local/pgsql/data/pg_hba.conf to allow only you on, then
+     bring postmaster back up.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+If you are upgrading an existing system then kill the postmaster.  Type
+<ProgramListing>
+    ps -ax | grep postmaster
+</ProgramListing>
+     This should list the process numbers for a number of processes.  Type
+     the following line, with "???" replaced by the process id for process
+     "postmaster".  (Do not use the id for process "grep postmaster".)  Type
+       kill ???
+     with "???" modified as indicated.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+If you are upgrading an existing system then move the old directories
+     out of the way.  If you are short of disk space then you may have to
+     back up and delete the directories instead.  If you do this, save the
+     old database in the /usr/local/pgsql/data directory tree.  At a
+     minimum, save file /usr/local/pgsql/data/pg_hba.conf.
+</Para>
+
+<Para>
+     Type the following:
+        su
+        cd /usr/src
+        mv pgsql pgsql_6_0
+        cd /usr/local
+        mv pgsql pgsql_6_0
+        exit
+</Para>
+
+<Para>
+     If you are not using /usr/local/pgsql/data as your data directory
+     (check to see if environment variable PGDATA is set to something
+     else) then you will also want to move this directory in the same
+     manner.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+  Make new source and install directories.  The actual paths can be
+     different for your installation; be consistant throughout this procedure.
+     Type
+<ProgramListing>
+    su
+    cd /usr/src
+    mkdir pgsql
+    chown postgres:postgres pgsql
+    cd /usr/local
+    mkdir pgsql
+    chown postgres:postgres pgsql
+    exit
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Unzip and untar the new source file.  Type
+<ProgramListing>
+    cd /usr/src/pgsql
+    gunzip -c ~/postgresql-v6.3.tar.gz | tar xvf -
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Configure the source code for your system.  It is this step at which
+     you can specify your actual source path and installation paths for
+     the build process (see the --prefix option below).  Type
+<ProgramListing>
+    cd /usr/src/pgsql/src
+    ./configure
+</ProgramListing>
+</Para>
+
+<Para>
+     The configure program will list the template files available and
+     ask you to choose one.  A lot of times, an appropriate template
+     file is chosen for you, and you can just press Enter to accept the
+     default.  If the default is not appropriate, then type in the
+     appropriate template file and press Enter.  (If you do this, then
+     send email to scrappy@hub.org stating the output of the program
+     './config.guess' and what the template file should be.)
+</Para>
+
+<Para>
+     Once you have entered the template file, you will be asked a
+     number of questions about your particular configuration.  These
+     can be skipped by adding parameters to the configure command above.
+     The following parameters can be tagged onto the end of the configure
+     command:
+
+<ProgramListing>
+       --prefix=BASEDIR   Selects a different base directory for the
+                          installation of the <ProductName>Postgres</ProductName> configuration.
+                          The default is /usr/local/pgsql.
+
+       --enable-hba       Enables Host Based Authentication (DEFAULT)
+
+       --disable-hba      Disables Host Based Authentication
+
+       --enable-locale    Enables USE_LOCALE
+
+       --disable-locale   Disables USE_LOCALE (DEFAULT)
+
+       --enable-cassert   Enables ASSERT_CHECKING
+
+       --disable-cassert  Disables ASSERT_CHECKING (DEFAULT)
+
+       --with-template=TEMPLATE
+                          Use template file TEMPLATE - the template
+                          files are assumed to be in the directory
+                          src/template, so look there for proper values.
+                          (If the configure script cannot find the
+                          specified template file, it will ask you for
+                          one).
+
+       --with-pgport=PORT Sets the port that the postmaster process
+                          listens for incoming connections on.  The
+                          default for this is port 5432.
+</ProgramListing>
+</Para>
+
+<Para>
+     As an example, here is the configure script I use on a Sparc
+     Solaris 2.5 system with /opt/postgres being the install base.
+
+<ProgramListing>
+    ./configure --prefix=/opt/postgres \
+	--with-template=sparc_solaris-gcc --with-pgport=5432 \
+	--enable-hba --disable-locale
+</ProgramListing>
+
+     Of course, in a real shell, you would type these three lines all
+     on the same line.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+Compile the program.  Type
+<ProgramListing>
+    cd /usr/src/pgsql/src
+    gmake all >& make.log &
+    tail -f make.log
+</ProgramListing>
+</Para>
+
+<Para>
+     The last line displayed will hopefully be "All of PostgreSQL is
+     successfully made. Ready to install."  At this point, or earlier
+     if you wish, type control-C to get out of tail.  (If you have
+     problems later on you may wish to examine file make.log for
+     warning and error messages.)
+</Para>
+
+<Para>
+     If your computer does not have gmake (GNU make) then try running
+     make instead throughout the rest of these notes.
+</Para>
+
+<Para>
+     Please note that you will probably find a number of warning
+     messages in make.log.  Unless you have problems later on, these
+     messages may be safely ignored.
+</Para>
+
+<Para>
+     If the compiler fails with an error stating that the flex command
+     cannot be found then install flex as described earlier.  Next,
+     change directory back to this directory, type "make clean", then
+     recompile again.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Install the program.  Type
+<ProgramListing>
+    cd /usr/src/pgsql/src
+    gmake install >& make.install.log &
+    tail -f make.install.log
+</ProgramListing>
+</Para>
+
+<Para>
+     The last line displayed will be "gmake[1]: Leaving directory
+     `/usr/src/pgsql/src/man'".  At this point, or earlier if you wish,
+     type control-C to get out of tail.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If necessary, tell UNIX how to find your shared libraries.  If you
+     are using Linux-ELF do ONE of the following, preferably the first:
+<SubSteps>
+<Step Performance="optional">
+<Para>
+       As root, edit file /etc/ld.so.conf.  Add line
+             <FileName>/usr/local/pgsql/lib</FileName>
+          to the file.  Then run command <Command>/sbin/ldconfig</Command>.
+</Para>
+</Step>
+<Step Performance="optional">
+<Para>
+       In a bash shell, type
+<ProgramListing>
+    export LD_LIBRARY_PATH=/usr/local/pgsql/lib
+</ProgramListing>
+</Para>
+</Step>
+<Step Performance="optional">
+<Para>
+       In a csh shell, type
+<ProgramListing>
+    setenv LD_LIBRARY_PATH /usr/local/pgsql/lib
+</ProgramListing>
+</Step>
+</SubSteps>
+
+<Para>
+     Please note that the above commands may vary wildly for different
+     operating systems.  Check the platform specific notes, such as
+     those for Ultrix4.x or and for non-ELF Linux.
+</Para>
+
+<Para>
+     If, when you create the database, you get the message "pg_id: can't
+     load library 'libpq.so'" then the above step was necessary.  Simply
+     do this step, then try to create the database again.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If it has not already been done, then prepare account postgres
+     for using <ProductName>Postgres</ProductName>.  Any account that will use <ProductName>Postgres</ProductName> must
+     be similarily prepared.  (The following instructions are for a
+     bash shell.  Adapt accordingly for other shells.)
+</Para>
+
+<Para>
+     Add the following lines to your login shell, ~/.bash_profile:
+<ProgramListing>
+    PATH=$PATH:/usr/local/pgsql/bin
+    MANPATH=$MANPATH:/usr/local/pgsql/man
+    PGLIB=/usr/local/pgsql/lib
+    PGDATA=/usr/local/pgsql/data
+    export PATH MANPATH PGLIB PGDATA
+</ProgramListing>
+</Para>
+
+<Para>
+     Make sure that you have defined these variables before continuing
+     with the remaining steps.  The easiest way to do this is to type:
+<ProgramListing>
+    source ~/.bash_profile
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Create the database.  <Emphasis>Do not do the following as root!</Emphasis>
+ This would be a major security hole.  Type
+<ProgramListing>
+    initdb
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Set up permissions to access the database system.  Do this by editing
+     file /usr/local/pgsql/data/pg_hba.conf.  The instructions are
+     included in the file.  (If your database is not located in the
+     default location, i.e. if PGDATA is set to point elsewhere, then the
+     location of this file will change accordingly.)  This file should be
+     made read only again once you are finsihed.
+
+     If you are upgrading from v6.0 you can copy file pg_hba.conf from
+     your old database on top of the one in your new database, rather than
+     redoing this from scratch.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+You may wish to skip the regression tests.
+     However, we think skipping the tests is a BAD idea!
+</Para>
+
+<Para>
+     The file /usr/src/pgsql/src/test/regress/README has detailed
+     instructions for running and interpreting the regression tests.
+     A short version follows here:
+</Para>
+
+<Para>
+     Start the postmaster daemon running in the background by typing
+<ProgramListing>
+    cd
+    nohup postmaster > regress.log 2>&1 &
+</ProgramListing>
+</Para>
+
+<Para>
+     Run postmaster from your <ProductName>Postgres</ProductName> super user account (typically
+     account postgres).  DO NOT RUN POSTMASTER FROM THE ROOT ACCOUNT.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+
+ Run the regression tests.  Type
+
+<ProgramListing>
+    cd
+    cd /usr/src/pgsql/src/test/regress
+    gmake clean
+    gmake all runtest
+</ProgramListing>
+</Para>
+
+<Para>
+
+     You do not need to type "gmake clean" if this is the first time you
+     are running the tests.
+</Para>
+
+<Para>
+
+     You should get on the screen (and also written to file ./regress.out)
+     a series of statements stating which tests passed and which tests
+     failed.  Please note that it can be normal for some of the tests to
+     "fail".  For the failed tests, use diff to compare the files in
+     directories ./results and ./expected.  If float8 failed, type
+     something like:
+<ProgramListing>
+    cd /usr/src/pgsql/src/test/regress
+    diff -w expected/float8.out results
+</ProgramListing>
+</Para>
+
+<Para>
+
+    "Failed" tests may have failed due to slightly different error messages,
+     output formatting, failure to set the timezone correctly for your
+     platform, etc.  "Failures" of this type do not indicate a problem with
+     <ProductName>Postgres</ProductName>.
+</Para>
+
+<Para>
+
+     For a i686/Linux-ELF platform, no tests failed since this is the
+     v6.3 regression testing reference platform.
+</Para>
+
+<Para>
+     For the SPARC/Linux-ELF platform, using the 970525 beta version of
+     <ProductName>Postgres</ProductName> v6.2 the following tests "failed":
+     float8 and geometry "failed" due to minor precision differences in
+     floating point numbers.  select_views produces massively different output,
+     but the differences are due to minor floating point differences.
+</Para>
+
+<Para>
+     Conclusion?  If you do see failures, try to understand the nature of
+     the differences and then decide if those differences will affect your
+     intended use of <ProductName>Postgres</ProductName>.  However, keep in mind that this is likely
+     to be the most solid release of <ProductName>Postgres</ProductName> to date, incorporating many
+     bug fixes from v6.2.1, and that previous versions of <ProductName>Postgres</ProductName> have been
+     in use successfully for some time now.
+</Para>
+
+<Para>
+     After running the tests, type
+<ProgramListing>
+    destroydb regression
+    cd /usr/src/pgsql/src/test/regress
+    gmake clean
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+
+ Stop the postmaster as described in step 7.  Then restore the
+     timezone to it's normal setting.  If you changed the timezone by
+     modifying environment variable TZ then one way to do this is to
+     log out of, then back into, account postgres.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+
+ Start the postmaster daemon running.  Type
+<ProgramListing>
+    cd
+    nohup postmaster > server.log 2>&1 &
+</ProgramListing>
+     Run postmaster from your <ProductName>Postgres</ProductName> super user account (typically
+     account postgres).  DO NOT RUN POSTMASTER FROM THE ROOT ACCOUNT.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If you haven't already done so, this would be a good time to modify
+     your computer so that it will automatically start postmaster whenever
+     you boot your computer.
+
+     Here are some suggestions on how to do this, contributed by various
+     users.
+
+     Whatever you do, postmaster must be run by user postgres AND NOT BY
+     ROOT.  This is why all of the examples below start by switching user
+     (su) to postgres.  These commands also take into account the fact
+     that environment variables like PATH and PGDATA may not be set properly.
+
+     The examples are as follows.  Use them with extreme caution.
+
+       a) Edit file rc.local on NetBSD or file rc2.d on SPARC Solaris
+          2.5.1 to contain the following single line:
+             su postgres -c "/usr/local/pgsql/bin/postmaster -S -D
+                     /usr/local/pgsql/data"
+
+       b) In FreeBSD 2.2-RELEASE edit /usr/local/etc/rc.d/pgsql.sh to
+          contain the following lines and make it chmod 755 and chown
+          root:bin.
+             #!/bin/sh
+             [ -x /usr/local/pgsql/bin/postmaster ] && {
+               su -l pgsql -c 'exec /usr/local/pgsql/bin/postmaster
+                       -D/usr/local/pgsql/data
+                       -S -o -F > /usr/local/pgsql/errlog' &
+               echo -n ' pgsql'
+             }
+          You may put the line breaks as shown above.  The shell is smart
+          enough to keep parsing beyond end-of-line if there is an
+          expression unfinished.  The exec saves one layer of shell under
+          the postmaster process so the parent is init.  Note:  Unlike most
+          other examples, this one has been tested.
+
+       c) In RedHat v4.0 Linux edit file /etc/inittab to contain the
+          following single line:
+             pg:2345:respawn:/bin/su - postgres -c
+                     "/usr/local/pgsql/bin/postmaster -D/usr/local/pgsql/data
+                     >> /usr/local/pgsql/server.log 2>&1" /dev/null
+          (The author of this example says this example will revive the
+          postmaster if it dies, but he doesn't know if there are other side
+          effects.)
+
+       d) The contrib/linux area of the <ProductName>Postgres</ProductName> distribution has an example
+          init.d script compatible with and tested using recent RedHat packages.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If you haven't already done so, this would be a good time to modify
+      your computer to do regular maintainence.  The following should be
+      done at regular intervals:
+
+        a) Run the SQL command vacuum.  This will clean up your database.
+        b) Back up your system.  (You should probably keep the last few
+           backups on hand.)  Ideally, no one else should be using the
+           system at the time.
+
+      Ideally, the above tasks should be done by a shell script that is
+      run nightly or weekly by cron.  Look at the man page for crontab
+      for a starting point on how to do this.  (If you do it, please
+      e-mail us a copy of your shell script.  We would like to set up
+      our own systems to do this too.)
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If you are upgrading an existing system then install your old database.
+     Type
+<ProgramListing>
+    cd
+    psql -e template1 < db.out
+</ProgramListing>
+
+     If your pre-v6.2 database uses either path or polygon geometric data types,
+     then you will need to upgrade any columns containing those types. To
+     do so, type (from within psql)
+<ProgramListing>
+    update YourTable set PathCol = UpgradePath(PathCol);
+    update YourTable set PolyCol = UpgradePoly(PolyCol);
+    ...
+    vacuum;
+</ProgramListing>
+
+     UpgradePath() checks to see that a path value is consistant with the
+     old syntax, and will not update a column which fails that examination.
+     UpgradePoly() cannot verify that a polygon is in fact from an old
+     syntax, but RevertPoly() is provided to reverse the effects of a
+     mis-applied upgrade.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ If you are a new user, you may wish to play with <ProductName>Postgres</ProductName> as described
+     below.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Clean up after yourself.  Type
+<ProgramListing>
+    rm -rf /usr/src/pgsql_6_0
+    rm -rf /usr/local/pgsql_6_0
+    # Also delete old database directory tree if it is not in
+    #  /usr/local/pgsql_6_0/data
+    rm ~/postgresql-v6.2.1.tar.gz
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ You will probably want to print out the documentation.  Here is how
+     you might do it if you have Ghostscript on your system and are
+     writing to a laserjet printer.
+        alias gshp='gs -sDEVICE=laserjet -r300 -dNOPAUSE'
+        export GS_LIB=/usr/share/ghostscript:/usr/share/ghostscript/fonts
+        # Print out the man pages.
+        man -a -t /usr/local/pgsql/man/*/* > manpage.ps
+        gshp -sOUTPUTFILE=manpage.hp manpage.ps
+        rm manpage.ps
+        lpr -l -s -r manpage.hp
+        # Print out the Postgres95 User Manual, version 1.0,
+        #  Sept. 5, 1996.
+        cd /usr/src/pgsql/doc
+        gshp -sOUTPUTFILE=userguide.hp userguide.ps
+        lpr -l -s -r userguide.hp
+
+     If you are a developer, you will probably want to also print out
+     the Postgres Implemention Guide, version 1.0, October 1, 1995.
+     This is a WWW document located at
+     http://www.postgresql.org/docs/impguide.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ The <ProductName>Postgres</ProductName> team wants to keep <ProductName>Postgres</ProductName> working on all of the
+     supported platforms.  We therefore ask you to let us know if you did
+     or did not get <ProductName>Postgres</ProductName> to work on you system.  Please send a
+     mail message to pgsql-ports@postgresql.org telling us the following:
+       - The version of <ProductName>Postgres</ProductName> (v6.2.1, 6.1.1, beta 970703, etc.).
+       - Your operating system (i.e. RedHat v4.0 Linux v2.0.26).
+       - Your hardware (SPARC, i486, etc.).
+       - Did you compile, install and run the regression tests cleanly?
+         If not, what source code did you change (i.e. patches you
+         applied, changes you made, etc.), what tests failed, etc.
+         It is normal to get many warning when you compile.  You do
+         not need to report these.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Now create, access and manipulate databases as desired.  Write client
+     programs to access the database server.  In other words, ENJOY!
+</Para>
+</Step>
+</Procedure>
+
+<Sect1>
+<Title>Playing with <ProductName>Postgres</ProductName></Title>
+
+<Para>
+After <ProductName>Postgres</ProductName> is installed, a database system is created, a postmaster
+daemon is running, and the regression tests have passed, you'll want to 
+see <ProductName>Postgres</ProductName> do something.  That's easy.  Invoke the interactive interface
+to <ProductName>Postgres</ProductName>, <Application>psql</Application>:
+
+<ProgramListing>
+    % psql template1
+</ProgramListing>
+
+(psql has to open a particular database, but at this point the only one
+that exists is the template1 database, which always exists.  We will connect
+to it only long enough to create another one and switch to it.)
+</Para>
+
+<Para>
+The response from psql is:
+
+<ProgramListing>
+Welcome to the POSTGRESQL interactive sql monitor:
+  Please read the file COPYRIGHT for copyright terms of POSTGRESQL
+
+   type \? for help on slash commands
+   type \q to quit
+   type \g or terminate with semicolon to execute query
+ You are currently connected to the database: template1
+
+template1=>
+</ProgramListing>
+</Para>
+
+<Para>
+Create the database foo:
+
+<ProgramListing>
+template1=> create database foo;
+CREATEDB
+</ProgramListing>
+
+(Get in the habit of including those SQL semicolons.  Psql won't execute
+anything until it sees the semicolon or a "\g" and the semicolon is required
+to delimit multiple statements.)
+</Para>
+
+<Para>
+Now connect to the new database:
+
+<ProgramListing>
+template1=> \c foo
+connecting to new database: foo
+</ProgramListing>
+
+("slash" commands aren't SQL, so no semicolon.  Use \? to see all the slash commands.)
+</Para>
+
+<Para>
+And create a table:
+
+<ProgramListing>
+foo=> create table bar (i int4, c char(16));
+CREATE
+</ProgramListing>
+</Para>
+
+<Para>
+Then inspect the new table:
+
+<ProgramListing>
+foo=> \d bar
+
+Table    = bar
++----------------------------------+----------------------------------+-------+
+|              Field               |              Type                | Length|
++----------------------------------+----------------------------------+-------+
+| i                                | int4                             |     4 |
+| c                                | (bp)char                         |    16 |
++----------------------------------+----------------------------------+-------+
+</ProgramListing>
+</Para>
+
+<Para>
+And so on.  You get the idea.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>The Next Step</Title>
+
+<Para>
+Questions? Bugs? Feedback?
+First, read the files in directory /usr/src/pgsql/doc.  The FAQ in
+this directory may be particularly useful.
+</Para>
+
+<Para>
+If <ProductName>Postgres</ProductName> failed to compile on your computer then fill out the form
+in file /usr/src/pgsql/doc/bug.template and mail it to the location
+indicated at the top of the form.
+</Para>
+
+<Para>
+Mail questions to
+<ULink url="pgsql-questions@postgresql.org">pgsql-questions@postgresql.org</ULink>.
+For more information on the various mailing lists, see 
+<ULink url="http://www.postgresql.org">http://www.postgresql.org</ULink>
+and look for the mailing lists.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Porting Notes</Title>
+
+<Note>
+<Para>
+For some ports, these notes may be out of date.
+</Para>
+</Note>
+
+<Sect2>
+<Title>Ultrix4.x</Title>
+
+<Para>
+        You need to install the libdl-1.1 package since Ultrix 4.x doesn't
+        have a dynamic loader. It's available in
+           s2k-ftp.CS.Berkeley.EDU:pub/personal/andrew/libdl-1.1.tar.Z
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Linux</Title>
+
+<Sect3>
+<Sect3Info>
+<Author>
+<FirstName>Thomas G.</FirstName>
+<SurName>Lockhart</SurName>
+</Author>
+<Date>1998-02-19</Date>
+</Sect3Info>
+<Title>Linux ELF</Title>
+
+<Para>
+The regression test reference machine is
+a linux-2.0.30/libc-5.3.12/RedHat-4.2 installation running on a dual processor i686.
+The linux-elf port installs cleanly. See the Linux FAQ for more details.
+</Para>
+</Sect3>
+
+<Sect3>
+<Sect3Info>
+<Date>1995-05-11</Date>
+</Sect3Info>
+<Title>Linux a.out</Title>
+
+<Para>
+        For non-ELF Linux, the dld library MUST be obtained and installed on
+        the system. It enables dynamic link loading capability to the <ProductName>Postgres</ProductName>
+        port. The dld library can be obtained from the sunsite linux
+        distributions. The current name is dld-3.2.5.
+<ULink url="sneaker@powergrid.electriciti.com">Jalon Q. Zimmerman</ULink>
+</Para>
+</Sect3>
+</Sect2>
+
+<Sect2>
+<Title>BSD/OS</Title>
+
+<Para>
+        For BSD/OS 2.0 and 2.01, you will need to get the GNU dld library.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>NeXT</Title>
+
+<Para>
+        The NeXT port for v1.09 was supplied by 
+<ULink url="mailto:tom@basil.icce.rug.nl">Tom R. Hageman</ULink>.
+        It requires a SysV IPC emulation library and header files for
+        shared libary and semaphore stuff.   Tom just happens to sell such
+        a product so contact him for information.  He has also indicated that
+        binary releases of <ProductName>Postgres</ProductName> for NEXTSTEP will be made available to
+        the general public.  Contact Info@RnA.nl for information.
+
+<Para>
+We have no recent reports of successful NeXT installations (for v6.2.1). 
+However, the client-side libraries should work even
+if the backend is not supported.
+</Para>
+</Sect2>
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/intro-pg.sgml b/doc/src/sgml/intro-pg.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..1f9cd52f56abc7a5d679bbff7fca725af99d43f5
--- /dev/null
+++ b/doc/src/sgml/intro-pg.sgml
@@ -0,0 +1,74 @@
+<Chapter>
+<TITLE>Introduction</TITLE>
+
+<Para>
+     This document is the programmer's  manual  for  the  
+     <Ulink url="http://postgresql.org/"><ProductName>PostgreSQL</ProductName></Ulink>
+     database  management system, originally developed at the University
+     of California at  Berkeley.   <ProductName>PostgreSQL</ProductName>  is  based  on
+     <Ulink url="http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/postgres.html">
+     <ProductName>Postgres release 4.2</ProductName></Ulink>. 
+The <ProductName>Postgres</ProductName> project, 
+     led by Professor Michael Stonebraker, has been sponsored  by  the
+     Defense  Advanced Research Projects Agency (<Acronym>DARPA</Acronym>), the
+     Army Research Office (<Acronym>ARO</Acronym>), the National Science  
+     Foundation (<Acronym>NSF</Acronym>), and ESL, Inc.
+</Para>
+
+<Para>
+     The first part of this manual 
+     explains  the
+     <ProductName>Postgres</ProductName>  approach  to  extensibility  and describe how
+     users can extend <ProductName>Postgres</ProductName> by adding user-defined types,
+     operators, aggregates, and both query language and programming language functions.
+     After an extremely  brief
+     overview  of  the <ProductName>Postgres</ProductName> rule system, we discuss
+     the trigger and SPI interfaces.
+     The manual concludes with a detailed description of the programming interfaces and
+     support libraries for various languages.
+</Para>
+
+<Para>
+     We assume proficiency with UNIX and C programming.
+</Para>
+
+<Sect1>
+<Title>Copyrights and Trademarks</Title>
+
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1996-8 by the PostgreSQL Global Development Group,
+and is distributed under the terms of the Berkeley license.
+
+<Para>
+<ProductName>Postgres95</ProductName> is copyright (C) 1994-5 by the Regents of the University of California.
+Permission to use, copy, modify, and distribute this software and its documentation
+for any purpose, without fee, and without a written agreement is hereby granted,
+provided that the above copyright notice and this paragraph and the following two
+paragraphs appear in all copies.
+</Para>
+<Para>
+In no event shall the University of California be liable to
+any party for direct, indirect, special, incidental, or consequential
+damages, including lost profits, arising out of the use of this
+software and its documentation, even if the University of California
+has been advised of the possibility of such damage.
+</Para>
+<Para>
+The University of California specifically disclaims any
+warranties, including, but not limited to, the implied warranties
+of merchantability and fitness for a particular purpose.
+The software provided hereunder is on an "as-is" basis, and
+the University of California has no obligations to provide
+maintainance, support, updates, enhancements, or modifications.
+</Para>
+
+<Para>
+<Acronym>UNIX</Acronym> is a trademark of X/Open, Ltd.  Sun4,  SPARC,  SunOS
+and  Solaris  are trademarks of Sun Microsystems, Inc.  DEC,
+DECstation, Alpha AXP and ULTRIX are trademarks  of  Digital
+Equipment   Corp.   PA-RISC  and  HP-UX  are  trademarks  of
+Hewlett-Packard Co.  OSF/1 is a trademark of the Open  
+Software Foundation.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/intro.sgml b/doc/src/sgml/intro.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..09a6ad3b02b42e8b0087b28a179ac3f5a31ed42e
--- /dev/null
+++ b/doc/src/sgml/intro.sgml
@@ -0,0 +1,482 @@
+<Chapter>
+<TITLE>Introduction</TITLE>
+
+<Para>
+     This document is the user  manual  for  the  
+     <Ulink url="http://postgresql.org/"><ProductName>PostgreSQL</ProductName></Ulink>
+     database  management system, originally developed at the University
+     of California at  Berkeley.   <ProductName>PostgreSQL</ProductName>  is  based  on
+     <Ulink url="http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/postgres.html">
+     <ProductName>Postgres release 4.2</ProductName></Ulink>. 
+The <ProductName>Postgres</ProductName> project, 
+     led by Professor Michael Stonebraker, has been sponsored  by  the
+     Defense  Advanced Research Projects Agency (<Acronym>DARPA</Acronym>), the
+     Army Research Office (<Acronym>ARO</Acronym>), the National Science  
+     Foundation (<Acronym>NSF</Acronym>), and ESL, Inc.
+</Para>
+
+<Sect1>
+<Title> What is <ProductName>Postgres</ProductName>?</Title>
+
+<Para>
+     Traditional   relational  database  management  systems
+     (DBMSs) support a data model consisting of a collection
+     of named relations, containing attributes of a specific
+     type.  In current commercial  systems,  possible  types
+     include  floating  point  numbers,  integers, character
+     strings, money, and dates.  It is  commonly  recognized
+     that  this model is inadequate for future data 
+     processing applications.
+     The relational  model  successfully  replaced  previous
+     models  in  part  because  of its "Spartan simplicity".
+     However, as mentioned, this simplicity often makes  the
+     implementation  of  certain applications very difficult.
+     <ProductName>Postgres</ProductName> offers  substantial  additional
+     power  by  incorporating  the following four additional
+     basic concepts in such a way that  users  can  easily
+     extend the system:
+
+<SimpleList>
+<Member>classes</Member>
+<Member>inheritance</Member>
+<Member>types</Member>
+<Member>functions</Member>
+</SimpleList>
+</Para>
+
+<Para>
+Other features provide additional power and flexibility:
+
+<SimpleList>
+<Member>constraints</Member>
+<Member>triggers</Member>
+<Member>rules</Member>
+<Member>transaction integrity</Member>
+</SimpleList>
+</Para>
+
+<Para>
+These features put <ProductName>Postgres</ProductName> into the category of databases
+referred to as <FirstTerm>object-relational</FirstTerm>. Note that this is distinct
+from those referred to as <FirstTerm>object-oriented</FirstTerm>, which in general
+are not as well suited to supporting the traditional relational database languages.
+So, although <ProductName>Postgres</ProductName> has some object-oriented features,
+it is firmly in the relational database world. In fact, some commercial databases
+have recently incorporated features pioneered by <ProductName>Postgres</ProductName>.
+
+</Sect1>
+     
+<Sect1>
+<Title>A Short History of <ProductName>Postgres</ProductName></Title>
+
+<Sect2>
+<Title>The Berkeley <ProductName>Postgres</ProductName> Project</Title>
+
+<Para>
+     Implementation of the <ProductName>Postgres</ProductName> <Acronym>DBMS</Acronym> began in 1986.  The
+     initial  concepts  for  the  system  were  presented in
+<!--
+<XRef LinkEnd="STON86">
+-->
+<Citation>[STON86]</Citation>
+ and the definition of the initial  data  model
+     appeared in 
+<!--
+<XRef LinkEnd="ROWE87">.
+-->
+<Citation>[ROWE87]</Citation>.
+The design of the rule system at
+     that time was described in  
+<!--
+<XRef LinkEnd="STON87a">.
+-->
+<Citation>[STON87a]</Citation>.
+The  rationale
+     and  architecture  of the storage manager were detailed in 
+<!--
+<XRef LinkEnd="STON87b">.
+-->
+<Citation>[STON87b]</Citation>.
+</Para>
+
+<Para>
+     <ProductName>Postgres</ProductName> has undergone  several  major  releases  since
+     then.   The  first "demoware" system became operational
+     in 1987 and was shown at the  1988  <Acronym>ACM-SIGMOD</Acronym>  
+     Conference.   We  released Version 1, described in 
+<!--
+<XRef LinkEnd="STON90a">,
+-->
+<Citation>[STON90a]</Citation>,
+     to a few external users in June 1989.  In response to a
+     critique  of  the  first rule system 
+<!--
+(<XRef LinkEnd="STON89">), 
+-->
+(<Citation>[STON89]</Citation>),
+the rule
+     system was  redesigned 
+<!--
+(<XRef LinkEnd="STON90b">)
+-->
+(<Citation>[STON90b]</Citation>)
+and  Version  2  was
+     released  in  June 1990 with the new rule system.  
+     Version 3 appeared in 1991 and added support for  multiple
+     storage  managers,  an  improved  query executor, and a
+     rewritten rewrite rule  system.   For  the  most  part,
+     releases  since  then  have  focused on portability and
+     reliability.
+</Para>
+
+<Para>
+     <ProductName>Postgres</ProductName> has been  used  to  implement  many  different
+     research and production applications.  These include: a
+     financial data analysis system, a  jet  engine  
+     performance   monitoring   package,   an   asteroid  tracking
+     database, a medical information database,  and  several
+     geographic information systems.  <ProductName>Postgres</ProductName> has also been
+     used as an educational tool  at  several  universities.
+     Finally,  <Ulink url="http://www.illustra.com/">Illustra  Information  Technologies</Ulink> picked up
+     the code and commercialized it.
+     <ProductName>Postgres</ProductName>  became  the  primary  data  manager  for  the
+     <Ulink url="http://www.sdsc.edu/0/Parts_Collabs/S2K/s2k_home.html">Sequoia 2000</Ulink>
+ scientific computing project in late 1992.
+     Furthermore, the size of the  external  user  community
+     nearly  doubled  during  1993.   It became increasingly
+     obvious that maintenance of the prototype code and 
+     support  was  taking  up large amounts of time that should
+     have been devoted to database research.  In  an  effort
+     to  reduce  this support burden, the project officially
+     ended with Version 4.2.
+</Para>
+</Sect2>
+     
+<Sect2>
+<Title><ProductName>Postgres95</ProductName></Title>
+
+<Para>
+In 1994,
+<ULink url="mailto:ayu@informix.com">Andrew Yu</ULink>
+and
+<ULink url="http://http.cs.berkeley.edu/~jolly/">Jolly Chen</ULink>
+added a SQL language interpreter to <ProductName>Postgres</ProductName>, and the code was subsequently released to
+the Web to find its own way in the world. <ProductName>Postgres95</ProductName> was a public-domain, open source descendant
+of this original Berkeley code.
+</Para>
+
+<Para>
+     <ProductName>Postgres95</ProductName> is a derivative of the last official release
+     of  <ProductName>Postgres</ProductName>  (version 4.2). The code is now completely
+     ANSI C and the code size has been trimmed by 25%. There
+     are  a lot of internal changes that improve performance
+     and code maintainability. <ProductName>Postgres95</ProductName> v1.0.x runs about  30-50%
+     faster  on  the  Wisconsin  Benchmark compared to v4.2.
+     Apart from bug fixes, these are the major enhancements:
+
+<ItemizedList>
+<ListItem>
+<Para>
+      	The query language <ProductName>Postquel</ProductName> has been replaced with
+        	<Acronym>SQL</Acronym> (implemented in the server). We do  not yet support
+        	subqueries  (which can be imitated with user defined
+        	<Acronym>SQL</Acronym> functions). Aggregates  have  been
+        	re-implemented.  We also added support for ``GROUP BY''.
+        	The <FileName>libpq</FileName> interface is still available  for  <Acronym>C</Acronym>  
+        	programs.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	In addition to the monitor program, we provide a new
+        	program (<Application>psql</Application>) which supports <Acronym>GNU</Acronym> <FileName>readline</FileName>.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	We added a new  front-end  library,  <FileName>libpgtcl</FileName>,  that
+        	supports  <Acronym>Tcl</Acronym>-based  clients.   A sample shell, 
+        	pgtclsh, provides new Tcl  commands  to  interface  <Application>tcl</Application>
+        	programs with the <ProductName>Postgres95</ProductName> backend.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	The  large  object interface has been overhauled. We
+        	kept Inversion large objects as the  only  mechanism
+        	for  storing  large objects. (This is not to be 
+        	confused with the Inversion file system which has  been
+        	removed.)
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	The  instance-level  rule  system  has been removed.
+        	Rules are still available as rewrite rules.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	A short tutorial introducing regular <Acronym>SQL</Acronym> features as
+        	well as those of ours is distributed with the source
+        	code.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      	<Acronym>GNU</Acronym> make (instead of  <Acronym>BSD</Acronym>  make)  is  used  for  the
+        	build.  Also,  <ProductName>Postgres95</ProductName>  can  be  compiled with an
+        	unpatched <ProductName>gcc</ProductName> (data alignment of  doubles  has  been
+        	fixed).
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title><ProductName>PostgreSQL</ProductName></Title>
+
+<Para>
+By 1996, it became clear that the name <Quote>Postgres95</Quote> would not stand
+the test of time. A new name, <ProductName>PostgreSQL</ProductName>, was chosen to reflect the
+relationship between original <ProductName>Postgres</ProductName> and the more recent
+versions with <Acronym>SQL</Acronym> capability. At the same time, the version numbering
+was reset to start at 6.0, putting the numbers back into the sequence originally begun by
+the <ProductName>Postgres</ProductName> Project.
+
+<Para>
+The emphasis on development for the v1.0.x releases of <ProductName>Postgres95</ProductName>
+was on stabilizing the backend code.
+With the v6.x series of <ProductName>PostgreSQL</ProductName>, the emphasis has shifted from
+identifying and understanding existing problems in the backend to augmenting features and capabilities, although
+work continues in all areas.
+
+<Para>
+Major enhancements include:
+
+<ItemizedList>
+<ListItem>
+<Para>
+Important backend features, including subselects, defaults, constraints, and triggers, have been implemented.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Additional <Acronym>SQL92</Acronym>-compliant language features have been added,
+ including primary keys, quoted identifiers, literal string type coersion, type casting,
+ and binary and hexadecimal integer input.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Built-in types have been improved, including new wide-range date/time types and additional geometric type support.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Overall backend code speed has been increased by approximately 20%, and backend startup speed has decreased 80%.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect2>
+
+<Sect1>
+<Title>About This Release</Title>
+
+<Para>
+     From  now  on, We will use <ProductName>Postgres</ProductName> to mean <ProductName>PostgreSQL</ProductName>.
+
+<Para>
+     <ProductName>PostgreSQL</ProductName>  is  available  without cost. This manual
+     describes version 6.3 of <ProductName>PostgreSQL</ProductName>.
+
+<Para>
+Check the Administrator's Guide for a list of currently supported machines. In general,
+<ProductName>PostgreSQL</ProductName> is portable to any Unix/Posix-compatible system
+with full libc library support.
+
+</Sect1>
+
+<Sect1>
+<Title>Resources</Title>
+
+<Para>
+This manual set is organized into several parts:
+
+<VariableList>
+<VarListEntry>
+<Term>Tutorial</Term>
+<ListItem>
+<Para>
+An introduction for new users. Does not cover advanced features.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>User's Guide</Term>
+<ListItem>
+<Para>
+General information for users, including available commands and data types.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Programmer's Guide</Term>
+<ListItem>
+<Para>
+Advanced information for application programmers. Topics include
+type and function extensibility, library interfaces, and application design issues.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Administrator's Guide</Term>
+<ListItem>
+<Para>
+Installation and management information. List of supported machines.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Developer's Guide</Term>
+<ListItem>
+<Para>
+Information for <ProductName>Postgres</ProductName> developers. This is intended
+for those who are contributing to the <ProductName>Postgres</ProductName>
+project; application development information should appear in the Programmer's Guide.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Reference Manual</Term>
+<ListItem>
+<Para>
+Detailed reference information on command syntax.
+At the moment, this manual is very sparse, but eventually should contain
+information similar to that in the man pages.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Para>
+In addition to this manual set, there are other resources to help you with
+<ProductName>Postgres</ProductName> installation and use:
+
+<VariableList>
+<VarListEntry>
+<Term>man pages</Term>
+<ListItem>
+<Para>
+The man pages have general information on command syntax.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>FAQs</Term>
+<ListItem>
+<Para>
+The Frequently Asked Questions (FAQ) documents address both general issues
+and some platform-specific issues.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>READMEs</Term>
+<ListItem>
+<Para>
+README files are available for some contributed packages.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Web Site</Term>
+<ListItem>
+<Para>
+The <ULink url="postgresql.org"><ProductName>Postgres</ProductName></ULink> web site has some information
+not appearing in the distribution. There is a <ProductName>mhonarc</ProductName> catalog of mailing list traffic
+which is a rich resource for many topics.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Mailing Lists</Term>
+<ListItem>
+<Para>
+The <ULink url="mailto:questions@postgresql.org"><ProductName>Postgres</ProductName> Questions</ULink>
+mailing list is a good place to have user questions answered. Other mailing lists are available; consult
+the web page for details.
+</Para>
+</ListItem>
+</VarListEntry>
+
+<VarListEntry>
+<Term>Yourself!</Term>
+<ListItem>
+<Para>
+<ProductName>Postgres</ProductName> is an open source product. As such, it depends on the user community for
+ongoing support. As you begin to use <ProductName>Postgres</ProductName>, you will rely on others
+for help, either through the documentation or through the mailing lists. Consider contributing your
+knowledge back. If you learn something which is not in the documentation, write it up and contribute it.
+If you add features to the code, contribute it. Even those without a lot of experience can provide
+corrections and minor changes in the documentation, and that is a good way to start.
+The <ULink url="mailto:docs@postgresql.org"><ProductName>Postgres</ProductName> Documentation</ULink>
+mailing list is the place to get going.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Sect1>
+
+<Sect1>
+<Title>Copyrights and Trademarks</Title>
+
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1996-8 by the PostgreSQL Global Development Group,
+and is distributed under the terms of the Berkeley license.
+
+<Para>
+<ProductName>Postgres95</ProductName> is copyright (C) 1994-5 by the Regents of the University of California.
+Permission to use, copy, modify, and distribute this software and its documentation
+for any purpose, without fee, and without a written agreement is hereby granted,
+provided that the above copyright notice and this paragraph and the following two
+paragraphs appear in all copies.
+</Para>
+<Para>
+In no event shall the University of California be liable to
+any party for direct, indirect, special, incidental, or consequential
+damages, including lost profits, arising out of the use of this
+software and its documentation, even if the University of California
+has been advised of the possibility of such damage.
+</Para>
+<Para>
+The University of California specifically disclaims any
+warranties, including, but not limited to, the implied warranties
+of merchantability and fitness for a particular purpose.
+The software provided hereunder is on an "as-is" basis, and
+the University of California has no obligations to provide
+maintainance, support, updates, enhancements, or modifications.
+</Para>
+
+<Para>
+<Acronym>UNIX</Acronym> is a trademark of X/Open, Ltd.  Sun4,  SPARC,  SunOS
+and  Solaris  are trademarks of Sun Microsystems, Inc.  DEC,
+DECstation, Alpha AXP and ULTRIX are trademarks  of  Digital
+Equipment   Corp.   PA-RISC  and  HP-UX  are  trademarks  of
+Hewlett-Packard Co.  OSF/1 is a trademark of the Open  
+Software Foundation.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/jdbc.sgml b/doc/src/sgml/jdbc.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..3b7279762dfa99faf014e0709f4f1340f35c7a0f
--- /dev/null
+++ b/doc/src/sgml/jdbc.sgml
@@ -0,0 +1,8 @@
+<Chapter>
+<Title>JDBC Interface</Title>
+
+<Para>
+There is a JDBC interface available for Postgres. It is documented elsewhere using
+the accepted tool for Java-language code.
+
+</Chapter>
diff --git a/doc/src/sgml/libpgtcl.sgml b/doc/src/sgml/libpgtcl.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..5e51f07ce8f7cf3951187d93e3034c8ec9e2d701
--- /dev/null
+++ b/doc/src/sgml/libpgtcl.sgml
@@ -0,0 +1,1641 @@
+<Chapter>
+<Title>pgtcl</Title>
+
+<Para>
+pgtcl is a tcl package for front-end programs to interface with <ProductName>Postgres</ProductName>
+backends.    pgtcl does not use the libpq library but communicates to
+the backend directly via the frontend-backend protocol.  Thus, it is
+more efficient than previous postgres->tcl bindings which are layered
+on top of libpq.  In addition, pgtcl can handle multiple backend
+connections from a single frontend application.
+</Para>
+
+<Para>
+This package was originally written by Jolly Chen.
+</Para>
+
+<Sect1>
+<Title>Commands</Title>
+
+<Para>
+The pg_lo* routines are interfaces to the Inversion Large Objects in <ProductName>Postgres</ProductName>.
+The functions are designed to mimic the analogous file system functions in
+the standard Unix file system interface.
+</Para>
+
+<Para>
+<TABLE TOCENTRY="1">
+<TITLE>PGTCL Commands</TITLE>
+<TGROUP COLS="2">
+<THEAD>
+  <ROW>
+    <ENTRY>Command</ENTRY>
+    <ENTRY>Description</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>pg_connect</ENTRY>
+    <ENTRY>opens a connection to the backend server</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_disconnect</ENTRY>
+    <ENTRY>closes a connection</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_exec</ENTRY>
+    <ENTRY>send a query to the backend</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_select</ENTRY>
+    <ENTRY>loop over the result of a select statement</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_result</ENTRY>
+    <ENTRY>manipulate the results of a query</ENTRY>
+  </ROW>
+
+  <ROW>
+    <ENTRY>pg_lo_creat</ENTRY>
+    <ENTRY>create a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_open</ENTRY>
+    <ENTRY>open a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_close</ENTRY>
+    <ENTRY>close a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_read</ENTRY>
+    <ENTRY>read a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_write</ENTRY>
+    <ENTRY>write a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_lseek</ENTRY>
+    <ENTRY>seek to a position on a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_tell</ENTRY>
+    <ENTRY>return the current seek position of a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_unlink</ENTRY>
+    <ENTRY>delete a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_import</ENTRY>
+    <ENTRY>import a Unix file into a large object</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>pg_lo_export</ENTRY>
+    <ENTRY>export a large object into a Unix file</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+</Para>
+
+<Para>
+Some commands equivalent to libpq commands are provided for connection
+and query operations.
+</Para>
+
+<Para>
+The pg_lo* routines should typically be used within a BEGIN/END transaction
+block because the file descriptor returned by pg_lo_open is only valid for
+the current transaction.  pg_lo_import and pg_lo_export MUST be used
+in a BEGIN/END transaction block.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Examples</Title>
+
+<Para>
+Here's a small example of how to use the routines:
+
+<ProgramListing>
+# getDBs :
+#   get the names of all the databases at a given host and port number
+#   with the defaults being the localhost and port 5432
+#   return them in alphabetical order
+proc getDBs { {host "localhost"} {port "5432"} } {
+    # datnames is the list to be result
+    set conn [pg_connect template1 -host $host -port $port]
+    set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname"]
+    set ntups [pg_result $res -numTuples]
+    for {set i 0} {$i < $ntups} {incr i} {
+	lappend datnames [pg_result $res -getTuple $i]
+    }
+    pg_disconnect $conn
+    return $datnames
+}
+</ProgramListing>
+
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Reference Information</Title>
+
+<REFENTRY ID="PGTCL-PGCONNECT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_connect</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_connect
+</REFNAME>
+<REFPURPOSE>opens a connection to the backend server
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_connect <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE> <OPTIONAL>-host <REPLACEABLE CLASS="PARAMETER">hostName</REPLACEABLE></OPTIONAL>
+  <OPTIONAL>-port <REPLACEABLE CLASS="PARAMETER">portNumber</REPLACEABLE></OPTIONAL> <OPTIONAL>-tty <REPLACEABLE CLASS="PARAMETER">pqtty</REPLACEABLE></OPTIONAL> <OPTIONAL>-options <REPLACEABLE CLASS="PARAMETER">optionalBackendArgs</REPLACEABLE></OPTIONAL>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGCONNECT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database name.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <OPTIONAL>-host <REPLACEABLE CLASS="PARAMETER">hostName</REPLACEABLE></OPTIONAL>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the domain name of the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <OPTIONAL>-port <REPLACEABLE CLASS="PARAMETER">portNumber</REPLACEABLE></OPTIONAL>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the IP port number of the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <OPTIONAL>-tty <REPLACEABLE CLASS="PARAMETER">pqtty</REPLACEABLE></OPTIONAL>
+</TERM>
+<LISTITEM>
+<PARA>(need information thomas 1997-12-24)
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <OPTIONAL>-options <REPLACEABLE CLASS="PARAMETER">optionalBackendArgs</REPLACEABLE></OPTIONAL>
+</TERM>
+<LISTITEM>
+<PARA>Specifies options for the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGCONNECT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+The return result is either an error message or a handle for a database
+   connection.  Handles start with the prefix "pgp"
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<!-- ********************************************************** -->
+
+<REFSECT1 ID="R1-PGTCL-PGCONNECT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_connect</FUNCTION> opens a connection to the <ProductName>Postgres</ProductName> backend.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGCONNECT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>XXX thomas 1997-12-24
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<REFENTRY ID="PGTCL-PGDISCONNECT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_disconnect</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_disconnect
+</REFNAME>
+<REFPURPOSE>closes a connection to the backend server
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_disconnect <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGDISCONNECT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database handle.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGDISCONNECT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  None
+</TERM>
+<LISTITEM>
+<PARA>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGDISCONNECT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_disconnect</FUNCTION> closes a connection to the <ProductName>Postgres</ProductName> backend.
+</PARA>
+</REFSECT1>
+
+</REFENTRY>
+
+<REFENTRY ID="PGTCL-PGEXEC-1">
+<REFMETA>
+<REFENTRYTITLE>pg_exec</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_exec
+</REFNAME>
+<REFPURPOSE>
+send a query string to the backend 
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGEXEC-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGEXEC-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_exec <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE>
+</SYNOPSIS>
+
+<!-- ********************************************************** -->
+
+<REFSECT2 ID="R2-PGTCL-PGEXEC-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database handle.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid SQL query.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGEXEC-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+   the return result is either an error message or a handle for a query result.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2></REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGEXEC-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>pg_exec</FUNCTION> submits a query to the <ProductName>Postgres</ProductName> backend and returns a result.
+  Handles start with the prefix "pgp".
+</PARA>
+</REFSECT1>
+
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGSELECT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_select</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_select
+</REFNAME>
+<REFPURPOSE>
+loop over the result of a select statement
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGSELECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGSELECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_select <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE>
+  <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryProcedure</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGSELECT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database handle.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid SQL select query.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Array variable for tuples returned.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryProcedure</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Procedure run on each tuple found.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGSELECT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+   the return result is either an error message or a handle for a query result.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2></REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGSELECT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>pg_select</FUNCTION> submits a query to the <ProductName>Postgres</ProductName> backend.
+ and returns the results.
+  The <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE>
+   must be a select statement.  Anything else returns an error.
+  The <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE>
+   variable is an array name used in the loop.  It is filled
+   out with the result of the query for each tuple using the field
+   names as the associative indices.
+</PARA>
+</REFSECT1>
+
+<REFSECT1 ID="R1-PGTCL-PGSELECT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+<ProgramListing>
+	set DB "mydb"
+	set conn [pg_connect $DB]
+	pg_select $conn "SELECT * from table" array {
+		puts [format "%5d %s" array(control) array(name)]
+	}
+	pg_disconnect $conn
+</ProgramListing>
+</PARA>
+</REFSECT1>
+
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGRESULT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_result</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_result
+</REFNAME>
+<REFPURPOSE>
+get information about a query result
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGRESULT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGRESULT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_result <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">resultOption</REPLACEABLE>
+</SYNOPSIS>
+<REFSECT2 ID="R2-PGTCL-PGRESULT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+  The handle for a query result.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">resultOption</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Specifies one of several possible options.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+
+<REFSECT3>
+<TITLE>Options</TITLE>
+
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+-status  
+</TERM>
+<LISTITEM>
+<PARA>
+the status of the result.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-oid
+</TERM>
+<LISTITEM>
+<PARA>
+if the last query was an insert, returns the oid of the 
+inserted tuple
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-conn
+</TERM>
+<LISTITEM>
+<PARA>
+the connection that produced the result
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-assign arrayName
+</TERM>
+<LISTITEM>
+<PARA>
+assign the results to an array
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-numTuples
+</TERM>
+<LISTITEM>
+<PARA>
+the number of tuples in the query
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-attributes
+</TERM>
+<LISTITEM>
+<PARA>
+returns a list of the name/type pairs of the tuple attributes
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-getTuple tupleNumber
+</TERM>
+<LISTITEM>
+<PARA>
+returns the values of the tuple in a list
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+-clear 
+</TERM>
+<LISTITEM>
+<PARA>
+clear the result buffer. Do not reuse after this
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT3>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGRESULT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+   the return result is either an error message or a handle for a query result.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2></REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGRESULT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>pg_result</FUNCTION> returns information about a query.
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOCREAT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_creat</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_creat
+</REFNAME>
+<REFPURPOSE>create a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOCREAT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>creating</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOCREAT-2"><PRIMARY>pg_lo_creat</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_creat <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOCREAT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the access mode for the large object</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOCREAT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+The oid of the large object created.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOCREAT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_creat</FUNCTION> creates an Inversion Large Object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOCREAT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+mode can be any OR'ing together of INV_READ, INV_WRITE, and INV_ARCHIVE. 
+The OR delimiter character is "|".
+<ProgramListing>
+[pg_lo_creat $conn "INV_READ|INV_WRITE"]
+</ProgramListing>
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOOPEN-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_open</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_open
+</REFNAME>
+<REFPURPOSE>open a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOOPEN-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>opening</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOOPEN-2"><PRIMARY>pg_lo_open</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_open <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOOPEN-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid large object oid.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the access mode for the large object</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOOPEN-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+A file descriptor for use in later pg_lo* routines.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOOPEN-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_open</FUNCTION> open an Inversion Large Object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOOPEN-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+Mode can be either "r", "w", or "rw".
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOCLOSE-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_close</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_close
+</REFNAME>
+<REFPURPOSE>close a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOCLOSE-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>closing</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOCLOSE-2"><PRIMARY>pg_lo_close</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_close <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOCLOSE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+A file descriptor for use in later pg_lo* routines.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOCLOSE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>None</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOCLOSE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_close</FUNCTION> closes an Inversion Large Object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOCLOSE-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOREAD-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_read</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_read
+</REFNAME>
+<REFPURPOSE>read a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOREAD-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>reading</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOREAD-2"><PRIMARY>pg_lo_read</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_read <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOREAD-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+File descriptor for the large object from pg_lo_open.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid buffer variable to contain the large object segment.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the maximum allowable size of the large object segment.</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOREAD-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>None</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOREAD-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_read</FUNCTION> reads 
+at most <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> bytes from a large object into a variable
+ named <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE>.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOREAD-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+<REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE> must be a valid variable name.
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOWRITE-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_write</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_write
+</REFNAME>
+<REFPURPOSE>write a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOWRITE-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>writing</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOWRITE-2"><PRIMARY>pg_lo_write</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_write <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOWRITE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+File descriptor for the large object from pg_lo_open.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid string variable to write to the large object.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the maximum size of the string to write.</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOWRITE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>None</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOWRITE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_write</FUNCTION> writes 
+at most <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> bytes to a large object from a variable
+ <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE>.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOWRITE-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+<REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE> must be 
+the actual string to write, not a variable name.
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOLSEEK-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_lseek</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_lseek
+</REFNAME>
+<REFPURPOSE>seek to a position on a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOLSEEK-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>positioning</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOLSEEK-2"><PRIMARY>pg_lo_lseek</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_lseek <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOLSEEK-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+File descriptor for the large object from pg_lo_open.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a zero-based offset in bytes.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA> whence can be "SEEK_CUR", "SEEK_END", or "SEEK_SET" </PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOLSEEK-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>None</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOLSEEK-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_lseek</FUNCTION> positions 
+to <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> bytes from the beginning of the large object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOLSEEK-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+<REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE> 
+can be "SEEK_CUR", "SEEK_END", or "SEEK_SET".
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOTELL-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_tell</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_tell
+</REFNAME>
+<REFPURPOSE>return the current seek position of a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOTELL-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>positioning</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOTELL-2"><PRIMARY>pg_lo_tell</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_tell <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOTELL-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+File descriptor for the large object from pg_lo_open.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOTELL-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>A zero-based offset in bytes suitable for input to <Function>pg_lo_lseek</Function>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOTELL-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_tell</FUNCTION> returns the current
+to <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> in bytes from the beginning of the large object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOTELL-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOUNLINK-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_unlink</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_unlink
+</REFNAME>
+<REFPURPOSE>delete a large object
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOUNLINK-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>delete</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOUNLINK-2"><PRIMARY>pg_lo_unlink</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_unlink <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOUNLINK-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Identifier for a large object.
+XXX Is this the same as objOid in other calls?? - thomas 1998-01-11
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOUNLINK-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>
+None
+</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOUNLINK-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_unlink</FUNCTION> deletes the specified large object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOUNLINK-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOIMPORT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_import</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_import
+</REFNAME>
+<REFPURPOSE>import a large object from a Unix file
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOIMPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>import</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOIMPORT-2"><PRIMARY>pg_lo_import</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_import <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOIMPORT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Unix file name.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOIMPORT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>
+None
+XXX Does this return a lobjId? Is that the same as the objOid in other calls? thomas - 1998-01-11
+</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOIMPORT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_import</FUNCTION> reads the specified file and places the contents into a large object.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOIMPORT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+  <Function>pg_lo_import</Function> must be called within a BEGIN/END transaction block.
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+<!-- ********************************************************** -->
+
+<REFENTRY ID="PGTCL-PGLOEXPORT-1">
+<REFMETA>
+<REFENTRYTITLE>pg_lo_export</REFENTRYTITLE>
+<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>pg_lo_export
+</REFNAME>
+<REFPURPOSE>export a large object to a Unix file
+</REFPURPOSE>
+<INDEXTERM ID="IX-PGTCL-PGLOEXPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>export</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-PGTCL-PGLOEXPORT-2"><PRIMARY>pg_lo_export</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+pg_lo_export <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE>
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-PGTCL-PGLOEXPORT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies a valid database connection.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Large object identifier.
+XXX Is this the same as the objOid in other calls?? thomas - 1998-01-11
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+  <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Unix file name.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-PGTCL-PGLOEXPORT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<PARA>
+None
+XXX Does this return a lobjId? Is that the same as the objOid in other calls? thomas - 1998-01-11
+</PARA>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-PGTCL-PGLOEXPORT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>pg_lo_export</FUNCTION> writes the specified large object into a Unix file.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-PGTCL-PGLOEXPORT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+  <Function>pg_lo_export</Function> must be called within a BEGIN/END transaction block.
+</PARA>
+</REFSECT1>
+</REFENTRY>
+
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..a01c4726607a8a3c7e4f9e76dd464824ea3c7f31
--- /dev/null
+++ b/doc/src/sgml/libpq.sgml
@@ -0,0 +1,1099 @@
+<Chapter>
+<Title><FileName>libpq</FileName></Title>
+
+<Para>
+     <FileName>libpq</FileName> is the application programming interface to <ProductName>Postgres</ProductName>.  
+     <FileName>libpq</FileName> is a set of library routines which  allows
+     client programs to pass queries to the <ProductName>Postgres</ProductName> backend
+     server and to receive the results of these queries.
+     This version  of  the  documentation  describes  the  <Acronym>C</Acronym>
+     interface  library.   Three short programs are included
+     at the end of this section to show how  to  write  programs that use <FileName>libpq</FileName>.
+     There are several examples of <FileName>libpq</FileName> applications in the
+     following directories:
+
+<ProgramListing>
+../src/test/regress
+         ../src/test/examples
+         ../src/bin/psql
+</ProgramListing>
+
+<Para>
+     Frontend programs which  use  <FileName>libpq</FileName>  must  include  the
+     header  file  <FileName>libpq-fe.h</FileName>  and  must link with the <FileName>libpq</FileName>
+     library.
+</Para>
+
+<Sect1>
+<Title>Control and Initialization</Title>
+
+<Para>
+     The following environment variables can be used to  set
+     up  default  environment  values  to  avoid hard-coding
+     database names into an application program:
+
+<ItemizedList>
+<ListItem>
+<Para>
+<Acronym>PGHOST</Acronym> sets the default server name.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Acronym>PGOPTIONS</Acronym> sets additional runtime  options  for  the <ProductName>Postgres</ProductName> backend.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Acronym>PGPORT</Acronym>  sets the default port for communicating with the <ProductName>Postgres</ProductName> backend.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Acronym>PGTTY</Acronym> sets the file or tty on which  debugging  messages from the backend server are displayed.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Acronym>PGDATABASE</Acronym>  sets the default <ProductName>Postgres</ProductName> database name.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Acronym>PGREALM</Acronym> sets the Kerberos realm to  use  with  <ProductName>Postgres</ProductName>,
+  if  it is different from the local realm.  If
+<Acronym>PGREALM</Acronym> is set, <ProductName>Postgres</ProductName> applications  will  attempt
+        authentication  with  servers for this realm and use
+        separate ticket files to avoid conflicts with  local
+        ticket  files.   This  environment  variable is only
+        used if Kerberos authentication is enabled.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Database Connection Functions</Title>
+
+<Para>
+     The following routines deal with making a connection to
+     a backend from a <Acronym>C</Acronym> program.
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>PQsetdb</Function> 
+          Makes a new connection to a backend.
+<ProgramListing>
+PGconn *PQsetdb(char *pghost,
+                char *pgport,
+                char *pgoptions,
+                char *pgtty,
+                char *dbName);
+</ProgramListing>
+          If  any  argument  is NULL, then the corresponding
+          environment variable is checked. If the  environment  variable  is  also  not  set, then hardwired
+          defaults are used.
+          PQsetdb always returns  a  valid  PGconn  pointer.
+          The  PQstatus (see below) command should be called
+          to ensure that  a  connection  was  properly  made
+          before queries are sent via the connection.  <FileName>libpq</FileName>
+          programmers should  be  careful  to  maintain  the
+          PGconn  abstraction.   Use  the accessor functions
+          below to get at the  contents  of  PGconn.   Avoid
+          directly  referencing  the  fields  of  the PGconn
+          structure as they are subject  to  change  in  the
+          future.
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQdb</Function>  
+         Returns the database name of the connection.
+<ProgramListing>
+char *PQdb(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQhost</Function>
+         Returns the host name of the connection.
+<ProgramListing>
+char *PQhost(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQoptions</Function>
+       Returns the pgoptions used in  the  connection.
+<ProgramListing>
+char *PQoptions(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQport</Function>
+         Returns the pgport of the connection.
+<ProgramListing>
+char *PQport(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQtty</Function>
+         Returns the pgtty of the connection.
+<ProgramListing>
+char *PQtty(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQstatus</Function>
+         Returns the status of the connection. 
+         The status can be CONNECTION_OK or CONNECTION_BAD.
+<ProgramListing>
+ConnStatusType *PQstatus(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQerrorMessage</Function>
+         Returns the error  message  associated with the connection
+<ProgramListing>
+char *PQerrorMessage(PGconn* conn);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQfinish</Function>
+          Close  the  connection to the backend.  Also frees
+          memory used by the PGconn structure.   The  PGconn
+          pointer should not be used after PQfinish has been
+          called.
+<ProgramListing>
+void PQfinish(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQreset</Function>
+          Reset the communication  port  with  the  backend.
+          This function will close the IPC socket connection
+          to the backend and attempt to  reestablish  a  new
+          connection to the same backend.
+<ProgramListing>
+void PQreset(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQtrace</Function>
+          Enables  tracing  of  messages  passed between the
+          frontend and the backend.  The messages are echoed
+          to the debug_port file stream.
+<ProgramListing>
+void PQtrace(PGconn *conn,
+             FILE* debug_port);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQuntrace</Function>
+          Disables  tracing  of  messages passed between the
+          frontend and the backend.
+<ProgramListing>
+void PQuntrace(PGconn *conn);
+</ProgramListing>
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Query Execution Functions</Title>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>PQexec</Function>
+          Submit a query to <ProductName>Postgres</ProductName>.   Returns  a  PGresult
+          pointer if the query was successful or a NULL otherwise.  If a NULL is returned, PQerrorMessage can
+          be used to get more information about the error.
+<ProgramListing>
+PGresult *PQexec(PGconn *conn,
+                 char *query);
+</ProgramListing>
+          The  <Function>PGresult</Function>  structure  encapsulates  the  query
+          result returned by the backend.  <Function>libpq</Function> programmers
+          should   be   careful  to  maintain  the  PGresult
+          abstraction. Use the accessor functions  described
+          below to retrieve the results of the query.  Avoid
+          directly referencing the fields  of  the  PGresult
+          structure  as  they  are  subject to change in the
+          future.
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQresultStatus</Function>
+          Returns the result status of the query.  PQresultStatus can return one of the following values:
+<ProgramListing>
+PGRES_EMPTY_QUERY,
+PGRES_COMMAND_OK,  /* the query was a command */
+PGRES_TUPLES_OK,  /* the query successfully returned tuples */
+PGRES_COPY_OUT,
+PGRES_COPY_IN,
+PGRES_BAD_RESPONSE, /* an unexpected response was received */
+PGRES_NONFATAL_ERROR,
+PGRES_FATAL_ERROR
+</ProgramListing>
+          If  the result status is PGRES_TUPLES_OK, then the
+          following routines can be  used  to  retrieve  the
+          tuples returned by the query.
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQntuples</Function> returns the number of tuples (instances)
+          in the query result.
+<ProgramListing>
+int PQntuples(PGresult *res);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQnfields</Function>
+          Returns   the   number    of    fields
+          (attributes) in the query result.
+<ProgramListing>
+int PQnfields(PGresult *res);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQfname</Function>
+            Returns the field (attribute) name associated with the given field  index.   Field  indices
+          start at 0.
+<ProgramListing>
+char *PQfname(PGresult *res,
+              int field_index);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQfnumber</Function>
+            Returns  the  field  (attribute)  index
+          associated with the given field name.
+<ProgramListing>
+int PQfnumber(PGresult *res,
+              char* field_name);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQftype</Function>
+            Returns the field type associated with the
+          given  field  index.  The  integer  returned is an
+          internal coding of the type.  Field indices  start
+          at 0.
+<ProgramListing>
+Oid PQftype(PGresult *res,
+            int field_num);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQfsize</Function>
+            Returns  the  size  in bytes of the field
+          associated with the given field index. If the size
+          returned  is  -1,  the  field is a variable length
+          field.  Field indices start at 0.
+<ProgramListing>
+int2 PQfsize(PGresult *res,
+                           int field_index);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQgetvalue</Function>
+            Returns the  field  (attribute)  value.
+          For most queries, the value returned by PQgetvalue
+          is a null-terminated ASCII  string  representation
+          of the attribute value.  If the query was a result
+          of a <Acronym>BINARY</Acronym> cursor, then  the  value  returned  by
+          PQgetvalue  is  the  binary  representation of the
+          type in the internal format of the backend server.
+          It  is the programmer's responsibility to cast and
+          convert the data to the correct C type.  The value
+          returned  by  PQgetvalue points to storage that is
+          part of the PGresult structure.  One must  explicitly 
+          copy the value into other storage if it is to
+          be used past the lifetime of the  PGresult  structure itself.
+<ProgramListing>
+char* PQgetvalue(PGresult *res,
+                 int tup_num,
+                 int field_num);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQgetlength</Function>
+            Returns   the   length  of  a  field
+          (attribute) in bytes.  If the field  is  a  struct
+          varlena, the length returned here does not include
+          the size field of the varlena, i.e., it is 4 bytes
+          less.
+<ProgramListing>
+int PQgetlength(PGresult *res,
+                              int tup_num,
+                              int field_num);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQcmdStatus</Function>
+          Returns  the  command  status  associated with the
+          last query command.
+<ProgramListing>
+char *PQcmdStatus(PGresult *res);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQoidStatus</Function>
+          Returns a string with the object id of  the  tuple
+          inserted  if  the last query is an INSERT command.
+          Otherwise, returns an empty string.
+<ProgramListing>
+char* PQoidStatus(PGresult *res);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQprintTuples</Function>
+          Prints out all the  tuples  and,  optionally,  the
+          attribute  names  to  the specified output stream.
+          The programs psql and monitor  both  use  PQprintTuples for output.
+<ProgramListing>
+void PQprintTuples(
+                     PGresult* res,
+                     FILE* fout,      /* output stream */
+                     int printAttName,/* print attribute names or not*/
+                     int terseOutput, /* delimiter bars or not?*/
+                     int width        /* width of column, variable width if 0*/
+                     );
+</ProgramListing>
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Function>PQclear</Function>
+          Frees  the  storage  associated with the PGresult.
+          Every query result should be properly  freed  when
+          it  is  no  longer  used.  Failure to do this will
+          result in memory leaks in  the  frontend  application.
+<ProgramListing>
+void PQclear(PQresult *res);
+</ProgramListing>
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Fast Path</Title>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<ProductName>Postgres</ProductName>  provides  a fast path interface to send function
+ calls to the backend.  This  is  a  trapdoor  into
+     system  internals and can be a potential security hole.
+     Most users will not need this feature.
+<ProgramListing>
+PGresult* PQfn(PGconn* conn,
+               int fnid,
+               int *result_buf,
+               int *result_len,
+               int result_is_int,
+               PQArgBlock *args,
+               int nargs);
+</ProgramListing>
+     The fnid argument is the object identifier of the function to be executed.  result_buf is the buffer in which
+     to load the return value.  The caller must  have  allocated  sufficient space to store the return value.  The
+     result length will be returned in the  storage  pointed
+     to  by  result_len.   If the result is to be an integer
+     value, than result_is_int should be set to 1; otherwise
+     it  should  be  set  to  0.  args and nargs specify the
+     arguments to the function.
+<ProgramListing>
+typedef struct {
+             int len;
+             int isint;
+             union {
+                 int *ptr;
+              int integer;
+             } u;
+         } PQArgBlock;
+</ProgramListing>
+     PQfn always returns a valid PGresult*.  The  resultStatus  should be checked before the result is used.   The
+     caller is responsible for  freeing  the  PGresult  with
+     PQclear when it is not longer needed.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Asynchronous Notification</Title>
+
+<Para>
+     <ProductName>Postgres</ProductName>  supports  asynchronous  notification  via the
+     LISTEN and NOTIFY commands.  A  backend  registers  its
+     interest  in a particular relation with the LISTEN command.  All backends listening on a particular  relation
+     will  be  notified asynchronously when a NOTIFY of that
+     relation name  is  executed  by  another  backend.   No
+     additional  information  is passed from the notifier to
+     the listener.  Thus, typically, any  actual  data  that
+     needs  to  be  communicated  is transferred through the
+     relation.
+     <FileName>libpq</FileName> applications are notified  whenever  a  connected
+     backend  has  received  an  asynchronous  notification.
+     However, the communication  from  the  backend  to  the
+     frontend   is  not  asynchronous.   Notification  comes
+     piggy-backed on other query results.  Thus, an application  must submit queries, even empty ones, in order to
+     receive notice of backend notification.  In effect, the
+     <FileName>libpq</FileName> application must poll the backend to see if there
+     is any pending  notification  information.   After  the
+     execution of a query, a frontend may call PQNotifies to
+     see if any notification  data  is  available  from  the
+     backend.
+</Para>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>PQNotifies</Function>
+          returns  the notification from a list of unhandled
+          notifications from the backend.  Returns  NULL  if
+          there  are no pending notifications from the backend.  PQNotifies behaves like  the  popping  of  a
+          stack.  Once a notification is returned from PQnotifies, it  is  considered  handled  and  will  be
+          removed from the list of notifications.
+<ProgramListing>
+PGnotify* PQNotifies(PGconn *conn);
+</ProgramListing>
+     The  second  sample program gives an example of the use
+     of asynchronous notification.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Functions Associated with the COPY Command</Title>
+
+<Para>
+     The copy command in <ProductName>Postgres</ProductName> has options to  read  from
+     or  write  to  the  network  connection  used by <FileName>libpq</FileName>.
+     Therefore, functions are necessary to access this  network  connection directly so applications may take full
+     advantage of this capability.
+</Para>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>PQgetline</Function>
+          Reads  a  newline-terminated  line  of  characters
+          (transmitted  by the backend server) into a buffer
+          string of size length.  Like fgets(3),  this  routine copies up to length-1 characters into string.
+          It is like gets(3), however, in that  it  converts
+          the terminating newline into a null character.
+          PQgetline returns EOF at EOF, 0 if the entire line
+          has been read, and 1 if the buffer is full but the
+          terminating newline has not yet been read.
+          Notice that the application must check to see if a
+          new line consists of  the  single  character  ".",
+          which  indicates  that the backend server has finished sending the results  of  the  copy  command.
+          Therefore,  if  the  application  ever  expects to
+          receive lines that are more than length-1  characters  long,  the application must be sure to check
+          the return value of PQgetline very carefully.
+          The code in
+<FileName>
+../src/bin/psql/psql.c
+</FileName>
+          contains routines that correctly handle  the  copy
+          protocol.
+<ProgramListing>
+int PQgetline(PGconn *conn,
+              char *string,
+              int length)
+</ProgramListing>
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+<Function>PQputline</Function>
+          Sends  a  null-terminated  string  to  the backend
+          server.
+          The application must explicitly  send  the  single
+          character  "."  to indicate to the backend that it
+          has finished sending its data.
+<ProgramListing>
+void PQputline(PGconn *conn,
+               char *string);
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQendcopy</Function>
+          Syncs with the backend.  This function waits until
+          the  backend  has  finished  the  copy.  It should
+          either be issued when the  last  string  has  been
+          sent  to  the  backend using PQputline or when the
+          last string has been  received  from  the  backend
+          using PGgetline.  It must be issued or the backend
+          may get "out of sync"  with  the  frontend.   Upon
+          return from this function, the backend is ready to
+          receive the next query.
+          The return value is 0  on  successful  completion,
+          nonzero otherwise.
+<ProgramListing>
+int PQendcopy(PGconn *conn);
+</ProgramListing>
+<ProgramListing>
+PQexec(conn, "create table foo (a int4, b char16, d float8)");
+PQexec(conn, "copy foo from stdin");
+PQputline(conn, "3&lt;TAB&gt;hello world&lt;TAB&gt;4.5\n");
+PQputline(conn,"4&lt;TAB&gt;goodbye world&lt;TAB&gt;7.11\n");
+...
+PQputline(conn,".\n");
+PQendcopy(conn);
+</ProgramListing>
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title><FileName>libpq</FileName> Tracing Functions</Title>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>PQtrace</Function>
+          Enable  tracing of the frontend/backend communication to a debugging file stream.
+<ProgramListing>
+void PQtrace(PGconn *conn
+             FILE *debug_port)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>PQuntrace</Function>
+          Disable tracing started by PQtrace
+<ProgramListing>
+void PQuntrace(PGconn *conn)
+</ProgramListing>
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>User Authentication Functions</Title>
+
+<Para>
+     If the user has generated the  appropriate  authentication  credentials
+  (e.g.,  obtaining <Acronym>Kerberos</Acronym> tickets),
+     the frontend/backend authentication process is  handled
+     by  <Function>PQexec</Function>  without any further intervention.
+  The following routines may be called by <FileName>libpq</FileName> programs to tailor the behavior of the authentication process.
+</Para>
+
+<Para>
+<ItemizedList>
+<ListItem>
+<Para>
+<Function>fe_getauthname</Function>
+          Returns a pointer to static space containing whatever name the user has authenticated.  Use of this
+          routine  in  place  of calls to getenv(3) or getpwuid(3) by applications is highly recommended,  as
+          it  is  entirely  possible  that the authenticated
+          user name is not the same as  value  of  the  <Acronym>USER</Acronym>
+          environment   variable  or  the  user's  entry  in
+          <FileName>/etc/passwd</FileName>.
+<ProgramListing>
+char *fe_getauthname(char* errorMessage)
+</ProgramListing>
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+<Function>fe_setauthsvc</Function>
+          Specifies that  <FileName>libpq</FileName>  should  use  authentication
+          service  name rather than its compiled-in default.
+          This value is typically taken from a  command-line
+          switch.
+<ProgramListing>
+void fe_setauthsvc(char *name,
+                   char* errorMessage)
+</ProgramListing>
+          Any   error   messages   from  the  authentication
+          attempts are returned in  the  errorMessage  argument.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>BUGS</Title>
+
+<Para>
+     The  query  buffer is 8192 bytes long, and queries over
+     that length will be silently truncated.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Sample Programs</Title>
+
+<Sect2>
+<Title>Sample Program 1</Title>
+
+<Para>
+<ProgramListing>
+         /*
+          * testlibpq.c
+          *   Test the C version of LIBPQ, the <ProductName>Postgres</ProductName> frontend library.
+          *
+          *
+          */
+         #include &lt;stdio.h&gt;
+         #include "libpq-fe.h"
+
+         void
+         exit_nicely(PGconn* conn)
+         {
+           PQfinish(conn);
+           exit(1);
+         }
+
+         main()
+         {
+           char *pghost, *pgport, *pgoptions, *pgtty;
+           char* dbName;
+           int nFields;
+           int i,j;
+
+         /*  FILE *debug; */
+
+           PGconn* conn;
+           PGresult* res;
+
+           /* begin, by setting the parameters for a backend connection
+              if the parameters are null, then the system will try to use
+              reasonable defaults by looking up environment variables
+              or, failing that, using hardwired constants */
+           pghost = NULL;  /* host name of the backend server */
+           pgport = NULL;  /* port of the backend server */
+           pgoptions = NULL; /* special options to start up the backend server */
+           pgtty = NULL;     /* debugging tty for the backend server */
+           dbName = "template1";
+
+           /* make a connection to the database */
+           conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+
+           /* check to see that the backend connection was successfully made */
+           if (PQstatus(conn) == CONNECTION_BAD) {
+             fprintf(stderr,"Connection to database '&percnt;s' failed.0, dbName);
+             fprintf(stderr,"&percnt;s",PQerrorMessage(conn));
+             exit_nicely(conn);
+           }
+
+         /*  debug = fopen("/tmp/trace.out","w");  */
+         /*   PQtrace(conn, debug);  */
+
+           /* start a transaction block */
+
+           res = PQexec(conn,"BEGIN");
+           if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+             fprintf(stderr,"BEGIN command failed0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+           /* should PQclear PGresult whenever it is no longer needed to avoid
+              memory leaks */
+           PQclear(res);
+
+           /* fetch instances from the pg_database, the system catalog of databases*/
+           res = PQexec(conn,"DECLARE myportal CURSOR FOR select * from pg_database");
+           if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+             fprintf(stderr,"DECLARE CURSOR command failed0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+           PQclear(res);
+
+           res = PQexec(conn,"FETCH ALL in myportal");
+           if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+             fprintf(stderr,"FETCH ALL command didn't return tuples properly0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+
+           /* first, print out the attribute names */
+           nFields = PQnfields(res);
+           for (i=0; i &lt; nFields; i++) {
+             printf("&percnt;-15s",PQfname(res,i));
+           }
+           printf("0);
+
+           /* next, print out the instances */
+           for (i=0; i &lt; PQntuples(res); i++) {
+             for (j=0  ; j &lt; nFields; j++) {
+               printf("&percnt;-15s", PQgetvalue(res,i,j));
+             }
+             printf("0);
+           }
+
+           PQclear(res);
+
+           /* close the portal */
+           res = PQexec(conn, "CLOSE myportal");
+           PQclear(res);
+
+           /* end the transaction */
+           res = PQexec(conn, "END");
+           PQclear(res);
+
+           /* close the connection to the database and cleanup */
+           PQfinish(conn);
+
+         /*   fclose(debug); */
+         }
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Sample Program 2</Title>
+
+<Para>
+<ProgramListing>
+         /*
+          * testlibpq2.c
+          *   Test of the asynchronous notification interface
+          *
+            populate a database with the following:
+
+         CREATE TABLE TBL1 (i int4);
+
+         CREATE TABLE TBL2 (i int4);
+
+         CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
+
+          * Then start up this program
+          * After the program has begun, do
+
+         INSERT INTO TBL1 values (10);
+
+          *
+          *
+          */
+         #include &lt;stdio.h&gt;
+         #include "libpq-fe.h"
+
+         void exit_nicely(PGconn* conn)
+         {
+           PQfinish(conn);
+           exit(1);
+         }
+
+         main()
+         {
+           char *pghost, *pgport, *pgoptions, *pgtty;
+           char* dbName;
+           int nFields;
+           int i,j;
+
+           PGconn* conn;
+           PGresult* res;
+           PGnotify* notify;
+
+           /* begin, by setting the parameters for a backend connection
+              if the parameters are null, then the system will try to use
+              reasonable defaults by looking up environment variables
+              or, failing that, using hardwired constants */
+           pghost = NULL;  /* host name of the backend server */
+           pgport = NULL;  /* port of the backend server */
+           pgoptions = NULL; /* special options to start up the backend server */
+           pgtty = NULL;     /* debugging tty for the backend server */
+           dbName = getenv("USER"); /* change this to the name of your test database*/
+
+           /* make a connection to the database */
+           conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+
+           /* check to see that the backend connection was successfully made */
+           if (PQstatus(conn) == CONNECTION_BAD) {
+             fprintf(stderr,"Connection to database '&percnt;s' failed.0, dbName);
+             fprintf(stderr,"&percnt;s",PQerrorMessage(conn));
+             exit_nicely(conn);
+           }
+
+           res = PQexec(conn, "LISTEN TBL2");
+           if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+             fprintf(stderr,"LISTEN command failed0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+           /* should PQclear PGresult whenever it is no longer needed to avoid
+              memory leaks */
+           PQclear(res);
+
+           while (1) {
+               /* async notification only come back as a result of a query*/
+               /* we can send empty queries */
+               res = PQexec(conn, " ");
+         /*      printf("res-&gt;status = &percnt;s0, pgresStatus[PQresultStatus(res)]); */
+               /* check for asynchronous returns */
+               notify = PQnotifies(conn);
+               if (notify) {
+                fprintf(stderr,
+                     "ASYNC NOTIFY of '&percnt;s' from backend pid '&percnt;d' received0,
+                     notify-&gt;relname, notify-&gt;be_pid);
+                free(notify);
+                break;
+               }
+               PQclear(res);
+           }
+
+           /* close the connection to the database and cleanup */
+           PQfinish(conn);
+
+         }
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Sample Program 3</Title>
+
+<Para>
+<ProgramListing>
+         /*
+          * testlibpq3.c
+          *   Test the C version of LIBPQ, the <ProductName>Postgres</ProductName> frontend library.
+          *   tests the binary cursor interface
+          *
+          *
+          *
+          populate a database by doing the following:
+
+         CREATE TABLE test1 (i int4, d float4, p polygon);
+
+         INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
+
+         INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
+
+          the expected output is:
+
+         tuple 0: got
+          i = (4 bytes) 1,
+          d = (4 bytes) 3.567000,
+          p = (4 bytes) 2 points         boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000)
+         tuple 1: got
+          i = (4 bytes) 2,
+          d = (4 bytes) 89.050003,
+          p = (4 bytes) 2 points         boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
+
+          *
+          */
+         #include &lt;stdio.h&gt;
+         #include "libpq-fe.h"
+         #include "utils/geo-decls.h" /* for the POLYGON type */
+
+         void exit_nicely(PGconn* conn)
+         {
+           PQfinish(conn);
+           exit(1);
+         }
+
+         main()
+         {
+           char *pghost, *pgport, *pgoptions, *pgtty;
+           char* dbName;
+           int nFields;
+           int i,j;
+           int i_fnum, d_fnum, p_fnum;
+
+           PGconn* conn;
+           PGresult* res;
+
+           /* begin, by setting the parameters for a backend connection
+              if the parameters are null, then the system will try to use
+              reasonable defaults by looking up environment variables
+              or, failing that, using hardwired constants */
+           pghost = NULL;  /* host name of the backend server */
+           pgport = NULL;  /* port of the backend server */
+           pgoptions = NULL; /* special options to start up the backend server */
+           pgtty = NULL;     /* debugging tty for the backend server */
+
+           dbName = getenv("USER");  /* change this to the name of your test database*/
+
+           /* make a connection to the database */
+           conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+
+           /* check to see that the backend connection was successfully made */
+           if (PQstatus(conn) == CONNECTION_BAD) {
+             fprintf(stderr,"Connection to database '&percnt;s' failed.0, dbName);
+             fprintf(stderr,"&percnt;s",PQerrorMessage(conn));
+             exit_nicely(conn);
+           }
+
+           /* start a transaction block */
+           res = PQexec(conn,"BEGIN");
+           if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+             fprintf(stderr,"BEGIN command failed0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+           /* should PQclear PGresult whenever it is no longer needed to avoid
+              memory leaks */
+           PQclear(res);
+
+           /* fetch instances from the pg_database, the system catalog of databases*/
+           res = PQexec(conn,"DECLARE mycursor BINARY CURSOR FOR select * from test1");
+           if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+             fprintf(stderr,"DECLARE CURSOR command failed0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+           PQclear(res);
+
+           res = PQexec(conn,"FETCH ALL in mycursor");
+           if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+             fprintf(stderr,"FETCH ALL command didn't return tuples properly0);
+             PQclear(res);
+             exit_nicely(conn);
+           }
+
+           i_fnum = PQfnumber(res,"i");
+           d_fnum = PQfnumber(res,"d");
+           p_fnum = PQfnumber(res,"p");
+
+           for (i=0;i&lt;3;i++) {
+               printf("type[&percnt;d] = &percnt;d, size[&percnt;d] = &percnt;d0,
+                   i, PQftype(res,i),
+                   i, PQfsize(res,i));
+           }
+           for (i=0; i &lt; PQntuples(res); i++) {
+             int *ival;
+             float *dval;
+             int plen;
+             POLYGON* pval;
+             /*/
+             ival =  (int*)PQgetvalue(res,i,i_fnum);
+             dval =  (float*)PQgetvalue(res,i,d_fnum);
+             plen = PQgetlength(res,i,p_fnum);
+
+             /* plen doesn't include the length field so need to increment by VARHDSZ*/
+             pval = (POLYGON*) malloc(plen + VARHDRSZ);
+             pval-&gt;size = plen;
+             memmove((char*)&amp;pval-&gt;npts, PQgetvalue(res,i,p_fnum), plen);
+             printf("tuple &percnt;d: got0, i);
+             printf(" i = (&percnt;d bytes) &percnt;d,0,
+                 PQgetlength(res,i,i_fnum), *ival);
+             printf(" d = (&percnt;d bytes) &percnt;f,0,
+                 PQgetlength(res,i,d_fnum), *dval);
+             printf(" p = (&percnt;d bytes) &percnt;d points boundbox = (hi=&percnt;f/&percnt;f, lo = &percnt;f,&percnt;f)0,
+                 PQgetlength(res,i,d_fnum),
+                 pval-&gt;npts,
+                 pval-&gt;boundbox.xh,
+                 pval-&gt;boundbox.yh,
+                 pval-&gt;boundbox.xl,
+                 pval-&gt;boundbox.yl);
+           }
+
+           PQclear(res);
+
+           /* close the portal */
+           res = PQexec(conn, "CLOSE mycursor");
+           PQclear(res);
+
+           /* end the transaction */
+           res = PQexec(conn, "END");
+           PQclear(res);
+
+           /* close the connection to the database and cleanup */
+           PQfinish(conn);
+
+         }
+</ProgramListing>
+<Para>
+
+</Sect2>
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..8462de950728982b8286b7fede908764cd665272
--- /dev/null
+++ b/doc/src/sgml/lobj.sgml
@@ -0,0 +1,485 @@
+<Chapter>
+<Title>Large Objects</Title>
+
+<Para>
+     In <ProductName>Postgres</ProductName>, data values are stored in tuples and 
+     individual tuples cannot span data pages. Since the size of
+     a data page is 8192 bytes, the upper limit on the  size
+     of a data value is relatively low. To support the storage 
+     of larger atomic values, <ProductName>Postgres</ProductName> provides a  large
+     object   interface.    This  interface  provides  file
+     oriented access to user data that has been declared  to
+     be a large type.
+     This  section describes the implementation and the 
+     programmatic and query  language  interfaces  to  <ProductName>Postgres</ProductName>
+     large object data.
+</Para>
+
+<Sect1>
+<Title>Historical Note</Title>
+
+<Para>
+     Originally, <ProductName>Postgres 4.2</ProductName> supported three standard 
+     implementations of large objects: as files external 
+     to <ProductName>Postgres</ProductName>,  as  <Acronym>UNIX</Acronym>  files managed by <ProductName>Postgres</ProductName>, and as data
+     stored within the <ProductName>Postgres</ProductName> database. It causes  
+     considerable confusion among users. As a result, we only 
+     support large objects as data stored within  the  <ProductName>Postgres</ProductName>
+     database  in  <ProductName>PostgreSQL</ProductName>.  Even  though is is slower to
+     access, it provides stricter data  integrity.
+     For historical reasons, this storage scheme is referred to as 
+     Inversion large objects. (We will use  Inversion  and  large
+     objects  interchangeably to mean the same thing in this
+     section.)
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Inversion Large Objects</Title>
+
+<Para>
+     The Inversion large object implementation breaks  large
+     objects  up  into  "chunks"  and  stores  the chunks in
+     tuples in the database.  A B-tree index guarantees fast
+     searches for the correct chunk number when doing random
+     access reads and writes.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Large Object Interfaces</Title>
+
+<Para>
+     The  facilities  <ProductName>Postgres</ProductName>  provides  to  access   large
+     objects,  both  in  the backend as part of user-defined
+     functions or the front end as part  of  an  application
+     using  the   interface, are described below. (For users
+     familiar with <ProductName>Postgres 4.2</ProductName>, <ProductName>PostgreSQL</ProductName> has a new set of
+     functions  providing  a  more  coherent  interface. The
+     interface is the same for  dynamically-loaded  C  
+     functions as well as for XXX LOST TEXT? WHAT SHOULD GO HERE??.
+
+     The  <ProductName>Postgres</ProductName>  large  object interface is modeled after
+     the <Acronym>UNIX</Acronym>  file  system  interface,  with  analogues  of
+     <Function>open(2)</Function>,  <Function>read(2)</Function>, <Function>write(2)</Function>,
+ <Function>lseek(2)</Function>, etc.  User 
+     functions call these routines to retrieve only the data  of
+     interest  from a large object.  For example, if a large
+     object type called mugshot  existed  that  stored  
+     photographs  of  faces, then a function called beard could
+     be declared on mugshot data.  Beard could look  at  the
+     lower third of a photograph, and determine the color of
+     the beard that appeared  there,  if  any.   The  entire
+     large  object value need not be buffered, or even 
+     examined, by the beard function.
+     Large objects may be accessed from dynamically-loaded <Acronym>C</Acronym>
+     functions  or  database  client  programs that link the
+     library.  <ProductName>Postgres</ProductName> provides a set of routines that 
+     support opening, reading, writing, closing, and seeking on
+     large objects.
+</Para>
+
+<Sect2>
+<Title>Creating a Large Object</Title>
+
+<Para>
+     The routine
+<ProgramListing>
+Oid lo_creat(PGconn *conn, int mode)
+</ProgramListing>
+     creates a new large  object.  The  mode  is  a  bitmask
+     describing  several  different  attributes  of  the new
+     object.  The symbolic constants listed here are defined
+     in
+<FileName>
+PGROOT/src/backend/libpq/libpq-fs.h
+</FileName>
+     The access type (read, write, or both) is controlled by
+     OR ing together the bits <Acronym>INV_READ</Acronym>  and  <Acronym>INV_WRITE</Acronym>.   If
+     the large object should be archived -- that is, if 
+     historical versions of it should be moved periodically  to
+     a  special archive relation -- then the <Acronym>INV_ARCHIVE</Acronym> bit
+     should be set.  The low-order sixteen bits of mask  are
+     the  storage  manager  number on which the large object
+     should reside.  For sites other  than  Berkeley,  these
+     bits should always be zero.
+     The commands below create an (Inversion) large object:
+<ProgramListing>
+inv_oid = lo_creat(INV_READ|INV_WRITE|INV_ARCHIVE);
+</ProgramListing>
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Importing a Large Object</Title>
+
+<Para>
+To import a <Acronym>UNIX</Acronym> file as
+     a large object, call
+<ProgramListing>
+Oid lo_import(PGconn *conn, text *filename)
+</ProgramListing>
+     The filename argument specifies the  <Acronym>UNIX</Acronym>  pathname  of
+     the file to be imported as a large object.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Exporting a Large Object</Title>
+
+<Para>
+To export a large object
+     into <Acronym>UNIX</Acronym> file, call
+<ProgramListing>
+int lo_export(PGconn *conn, Oid lobjId, text *filename)
+</ProgramListing>
+     The lobjId argument specifies  the  Oid  of  the  large
+     object  to  export  and the filename argument specifies
+     the <Acronym>UNIX</Acronym> pathname of the file.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Opening an Existing Large Object</Title>
+
+<Para>
+     To open an existing large object, call
+<ProgramListing>
+int lo_open(PGconn *conn, Oid lobjId, int mode, ...)
+</ProgramListing>
+     The lobjId argument specifies  the  Oid  of  the  large
+     object  to  open.   The  mode  bits control whether the
+     object is opened  for  reading  INV_READ),  writing  or
+     both.
+     A  large  object cannot be opened before it is created.
+     lo_open returns a large object descriptor for later use
+     in  lo_read, lo_write, lo_lseek, lo_tell, and lo_close.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Writing Data to a Large Object</Title>
+
+<Para>
+     The routine
+<ProgramListing>
+int lo_write(PGconn *conn, int fd, char *buf, int len)
+</ProgramListing>
+     writes len bytes from buf to large object fd.   The  fd
+     argument must have been returned by a previous lo_open.
+     The number of bytes actually written is  returned.   In
+     the event of an error, the return value is negative.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Seeking on a Large Object</Title>
+
+<Para>
+     To change the current read or write location on a large
+     object, call
+<ProgramListing>
+int lo_lseek(PGconn *conn, int fd, int offset, int whence)
+</ProgramListing>
+     This routine moves the current location pointer for the
+     large object described by fd to the new location specified 
+     by offset.  The valid values  for  .i  whence  are
+     SEEK_SET SEEK_CUR and SEEK_END.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Closing a Large Object Descriptor</Title>
+
+<Para>
+     A large object may be closed by calling
+<ProgramListing>
+int lo_close(PGconn *conn, int fd)
+</ProgramListing>
+     where  fd  is  a  large  object  descriptor returned by
+     lo_open.  On success, <Acronym>lo_close</Acronym> returns zero.  On error,
+     the return value is negative.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Built in registered functions</Title>
+
+<Para>
+     There  are two built-in registered functions, <Acronym>lo_import</Acronym>
+     and <Acronym>lo_export</Acronym> which  are  convenient  for  use  in  <Acronym>SQL</Acronym>
+     queries.
+     Here is an example of their use
+<ProgramListing>
+CREATE TABLE image (
+    name            text,
+    raster          oid
+);
+
+INSERT INTO image (name, raster)
+    VALUES ('beautiful image', lo_import('/etc/motd'));
+
+SELECT lo_export(image.raster, "/tmp/motd") from image
+    WHERE name = 'beautiful image';
+</ProgramListing>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Accessing Large Objects from LIBPQ</Title>
+
+<Para>
+     Below is a sample program which shows how the large object  
+     interface
+     in  LIBPQ  can  be used.  Parts of the program are 
+     commented out but are left in the source for  the  readers
+     benefit.  This program can be found in
+<FileName>
+../src/test/examples
+</FileName>
+     Frontend applications which use the large object interface  
+     in  LIBPQ  should   include   the   header   file
+     libpq/libpq-fs.h and link with the libpq library.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Sample Program</Title>
+
+<Para>
+<ProgramListing>
+/*--------------------------------------------------------------
+          *
+          * testlo.c--
+          *    test using large objects with libpq
+          *
+          * Copyright (c) 1994, Regents of the University of California
+          *
+          *
+          * IDENTIFICATION
+          *    /usr/local/devel/pglite/cvs/src/doc/manual.me,v 1.16 1995/09/01 23:55:00 jolly Exp
+          *
+          *--------------------------------------------------------------
+          */
+         #include &lt;stdio.h&gt;
+         #include "libpq-fe.h"
+         #include "libpq/libpq-fs.h"
+
+         #define BUFSIZE          1024
+
+         /*
+          * importFile *    import file "in_filename" into database as large object "lobjOid"
+          *
+          */
+         Oid importFile(PGconn *conn, char *filename)
+         {
+             Oid lobjId;
+             int lobj_fd;
+             char buf[BUFSIZE];
+             int nbytes, tmp;
+             int fd;
+
+             /*
+              * open the file to be read in
+              */
+             fd = open(filename, O_RDONLY, 0666);
+             if (fd &lt; 0)  {   /* error */
+              fprintf(stderr, "can't open unix file
+             }
+
+             /*
+              * create the large object
+              */
+             lobjId = lo_creat(conn, INV_READ|INV_WRITE);
+             if (lobjId == 0) {
+              fprintf(stderr, "can't create large object");
+             }
+
+             lobj_fd = lo_open(conn, lobjId, INV_WRITE);
+             /*
+              * read in from the Unix file and write to the inversion file
+              */
+             while ((nbytes = read(fd, buf, BUFSIZE)) &gt; 0) {
+              tmp = lo_write(conn, lobj_fd, buf, nbytes);
+              if (tmp &lt; nbytes) {
+                  fprintf(stderr, "error while reading
+              }
+             }
+
+             (void) close(fd);
+             (void) lo_close(conn, lobj_fd);
+
+             return lobjId;
+         }
+
+         void pickout(PGconn *conn, Oid lobjId, int start, int len)
+         {
+             int lobj_fd;
+             char* buf;
+             int nbytes;
+             int nread;
+
+             lobj_fd = lo_open(conn, lobjId, INV_READ);
+             if (lobj_fd &lt; 0) {
+              fprintf(stderr,"can't open large object %d",
+                   lobjId);
+             }
+
+             lo_lseek(conn, lobj_fd, start, SEEK_SET);
+             buf = malloc(len+1);
+
+             nread = 0;
+             while (len - nread &gt; 0) {
+              nbytes = lo_read(conn, lobj_fd, buf, len - nread);
+              buf[nbytes] = ' ';
+              fprintf(stderr,"&gt;&gt;&gt; %s", buf);
+              nread += nbytes;
+             }
+             fprintf(stderr,"0);
+             lo_close(conn, lobj_fd);
+         }
+
+         void overwrite(PGconn *conn, Oid lobjId, int start, int len)
+         {
+             int lobj_fd;
+             char* buf;
+             int nbytes;
+             int nwritten;
+             int i;
+
+             lobj_fd = lo_open(conn, lobjId, INV_READ);
+             if (lobj_fd &lt; 0) {
+              fprintf(stderr,"can't open large object %d",
+                   lobjId);
+             }
+
+             lo_lseek(conn, lobj_fd, start, SEEK_SET);
+             buf = malloc(len+1);
+
+             for (i=0;i&lt;len;i++)
+              buf[i] = 'X';
+             buf[i] = ' ';
+
+             nwritten = 0;
+             while (len - nwritten &gt; 0) {
+              nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
+              nwritten += nbytes;
+             }
+             fprintf(stderr,"0);
+             lo_close(conn, lobj_fd);
+         }
+
+         /*
+          * exportFile *    export large object "lobjOid" to file "out_filename"
+          *
+          */
+         void exportFile(PGconn *conn, Oid lobjId, char *filename)
+         {
+             int lobj_fd;
+             char buf[BUFSIZE];
+             int nbytes, tmp;
+             int fd;
+
+             /*
+              * create an inversion "object"
+              */
+             lobj_fd = lo_open(conn, lobjId, INV_READ);
+             if (lobj_fd &lt; 0) {
+              fprintf(stderr,"can't open large object %d",
+                   lobjId);
+             }
+
+             /*
+              * open the file to be written to
+              */
+             fd = open(filename, O_CREAT|O_WRONLY, 0666);
+             if (fd &lt; 0)  {   /* error */
+              fprintf(stderr, "can't open unix file
+                   filename);
+             }
+
+             /*
+              * read in from the Unix file and write to the inversion file
+              */
+             while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) &gt; 0) {
+              tmp = write(fd, buf, nbytes);
+                 if (tmp &lt; nbytes) {
+                  fprintf(stderr,"error while writing
+                       filename);
+              }
+             }
+
+             (void) lo_close(conn, lobj_fd);
+             (void) close(fd);
+
+             return;
+         }
+
+         void
+         exit_nicely(PGconn* conn)
+         {
+           PQfinish(conn);
+           exit(1);
+         }
+
+         int
+         main(int argc, char **argv)
+         {
+             char *in_filename, *out_filename;
+             char *database;
+             Oid lobjOid;
+             PGconn *conn;
+             PGresult *res;
+
+             if (argc != 4) {
+              fprintf(stderr, "Usage: %s database_name in_filename out_filename0,
+                   argv[0]);
+              exit(1);
+             }
+
+             database = argv[1];
+             in_filename = argv[2];
+             out_filename = argv[3];
+
+             /*
+              * set up the connection
+              */
+             conn = PQsetdb(NULL, NULL, NULL, NULL, database);
+
+             /* check to see that the backend connection was successfully made */
+             if (PQstatus(conn) == CONNECTION_BAD) {
+              fprintf(stderr,"Connection to database '%s' failed.0, database);
+              fprintf(stderr,"%s",PQerrorMessage(conn));
+              exit_nicely(conn);
+             }
+
+             res = PQexec(conn, "begin");
+             PQclear(res);
+
+             printf("importing file
+         /*  lobjOid = importFile(conn, in_filename); */
+             lobjOid = lo_import(conn, in_filename);
+         /*
+             printf("as large object %d.0, lobjOid);
+
+             printf("picking out bytes 1000-2000 of the large object0);
+             pickout(conn, lobjOid, 1000, 1000);
+
+             printf("overwriting bytes 1000-2000 of the large object with X's0);
+             overwrite(conn, lobjOid, 1000, 1000);
+         */
+
+             printf("exporting large object to file
+         /*    exportFile(conn, lobjOid, out_filename); */
+             lo_export(conn, lobjOid,out_filename);
+
+             res = PQexec(conn, "end");
+             PQclear(res);
+             PQfinish(conn);
+             exit(0);
+         }
+</ProgramListing>
+</Para>
+
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/manage.sgml b/doc/src/sgml/manage.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..332dc2459da98e9eb62795ec7fff5b6f846470e0
--- /dev/null
+++ b/doc/src/sgml/manage.sgml
@@ -0,0 +1,294 @@
+<Chapter>
+<Title>Managing a Database</Title>
+
+<Para>
+<Note>
+<Para>
+This section is currently a thinly disguised copy of the Tutorial. Needs to be augmented.
+- thomas 1998-01-12
+</Para>
+</Note>
+</Para>
+
+<Para>
+Although the <FirstTerm>site administrator</FirstTerm> is responsible for overall management of the
+<ProductName>Postgres</ProductName> installation, some databases within the
+installation may be managed by another person, designated the <FirstTerm>database administrator</FirstTerm>.
+This assignment of responsibilities occurs when a database is created. A user may be assigned
+explicit privileges to create databases and/or to create new users. A user assigned both privileges
+can perform most administrative task within <ProductName>Postgres</ProductName>, but will
+not by default have the same operating system privileges as the site administrator.
+</Para>
+
+<Para>
+The Database Administrator's Guide covers these topics in more detail.
+</Para>
+
+<Sect1>
+<Title>Database Creation</Title>
+
+<Para>
+Databases are created by the <Command>create database</Command> issued from
+within <ProductName>Postgres</ProductName>. <Application>createdb</Application> is a command-line
+utility provided to give the same functionality from outside <ProductName>Postgres</ProductName>.
+</Para>
+
+<Para>
+The <ProductName>Postgres</ProductName> backend must be running for either method
+to succeed, and the user issuing the command must be the <ProductName>Postgres</ProductName>
+<FirstTerm>superuser</FirstTerm> or have been assigned database creation privileges by the
+superuser.
+</Para>
+
+<Para>
+To create a new database named <Quote>mydb</Quote> from the command line, type
+<ProgramListing>
+% createdb mydb
+</ProgramListing>
+
+and to do the same from within <Application>psql</Application> type
+<ProgramListing>
+* CREATE DATABASE mydb;
+</ProgramListing>
+</Para>
+
+<Para>
+If you do not have the privileges required to create a database, you will see
+the following:
+<ProgramListing>
+% createdb mydb
+WARN:user "your username" is not allowed to create/destroy databases
+createdb: database creation failed on mydb.
+</ProgramListing>
+</Para>
+
+<Para>
+<ProductName>Postgres</ProductName>  allows  you to create any number of databases
+at a  given  site  and  you  automatically  become  the
+database  administrator  of  the database you just created.  
+Database names must  have  an  alphabetic  first
+character and are limited to 32 characters in length.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Alternate Database Locations</Title>
+
+<Para>
+It is possible to create a database in a location other than the default
+location for the installation. Remember that all database access actually
+occurs through the database backend, so that any location specified must
+be accessible by the backend.
+
+<Para>
+ Either an absolute path name or an environment variable
+may be specified as a location.
+Any environment variable specifying an alternate location must have
+been defined before the backend was started.
+Consult with the site administrator
+regarding preconfigured alternate database locations.
+
+<Note>
+<Para>
+ The environment variable style of specification
+is to be preferred since it allows the site administrator more flexibility in
+managing disk storage.
+</Para>
+</Note>
+
+<Para>
+For security and integrity reasons,
+any path or environment variable specified has some
+additional path fields appended.
+
+<Para>
+Alternate database locations must be prepared by running <Application>initlocation</Application>.
+
+<Para>
+To create a data storage area in <FileName>/alt/postgres/data</FileName>, ensure
+that <FileName>/alt/postgres</FileName> already exists.
+From the command line, type
+<ProgramListing>
+% initlocation /alt/postgres/data
+Creating Postgres database system directory /alt/postgres/data
+
+Creating Postgres database system directory /alt/postgres/data/base
+
+</ProgramListing>
+
+<Para>
+To do the same using an environment variable PGDATA2, type
+<ProgramListing>
+% initlocation $PGDATA2
+Creating Postgres database system directory /alt/postgres/data
+
+Creating Postgres database system directory /alt/postgres/data/base
+
+</ProgramListing>
+
+<Para>
+To create a database in the alternate storage area <FileName>/alt/postgres/data</FileName>
+from the command line,
+type
+<ProgramListing>
+% createdb -D /alt/postgres/data mydb
+</ProgramListing>
+
+or
+
+<ProgramListing>
+% createdb -D PGDATA2 mydb
+</ProgramListing>
+
+and to do the same from within <Application>psql</Application> type
+<ProgramListing>
+* CREATE DATABASE mydb WITH LOCATION = 'PGDATA2';
+</ProgramListing>
+</Para>
+
+<Para>
+If you do not have the privileges required to create a database, you will see
+the following:
+<ProgramListing>
+% createdb mydb
+WARN:user "your username" is not allowed to create/destroy databases
+createdb: database creation failed on mydb.
+</ProgramListing>
+</Para>
+
+<Para>
+If the specified location does not exist or the database backend does not have
+permission to access it or to write to directories under it, you will see
+the following:
+<ProgramListing>
+% createdb -D /alt/postgres/data mydb
+ERROR:  Unable to create database directory /alt/postgres/data/base/mydb
+createdb: database creation failed on mydb.
+</ProgramListing>
+
+</Sect1>
+
+<Sect1>
+<Title>Accessing a Database</Title>
+
+<Para>
+     Once you have constructed a database, you can access it
+     by:
+
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+running the <ProductName>Postgres</ProductName>  terminal  monitor  programs  (e.g.
+        <Application>psql</Application>) which allows you to interactively
+        enter, edit, and execute <Acronym>SQL</Acronym> commands.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      writing a  C  program  using  the  LIBPQ  subroutine
+        library.   This  allows  you  to submit <Acronym>SQL</Acronym> commands
+        from C and get answers and status messages  back  to
+        your  program.   This interface is discussed further
+        in section ??.
+</Para>
+</ListItem>
+</ItemizedList>
+
+You might want to start up <Application>psql</Application>, to try out the examples in this manual.
+ It can be activated for the <Database>mydb</Database>
+     database by typing the command:
+<ProgramListing>
+% psql mydb
+</ProgramListing>
+
+     You will be greeted with the following message:
+<ProgramListing>
+Welcome to the POSTGRESQL interactive sql monitor:
+  Please read the file COPYRIGHT for copyright terms of POSTGRESQL
+
+   type \? for help on slash commands
+   type \q to quit
+   type \g or terminate with semicolon to execute query
+ You are currently connected to the database: template1
+
+mydb=>
+</ProgramListing>
+</Para>
+
+<Para>
+This prompt indicates that the terminal monitor is listening
+  to you and that you can type <Acronym>SQL</Acronym> queries into a
+     workspace maintained by the terminal monitor.
+     The <Application>psql</Application> program responds to escape  codes  that  begin
+     with  the  backslash  character, <Quote>\</Quote>  For example, you
+     can get help on the syntax of various
+ <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing:
+<ProgramListing>
+mydb=> \h
+</ProgramListing>
+
+     Once  you  have finished entering your queries into the
+     workspace, you can pass the contents of  the  workspace
+     to the <ProductName>Postgres</ProductName> server by typing:
+<ProgramListing>
+mydb=> \g
+</ProgramListing>
+
+     This  tells  the  server  to process the query.  If you
+     terminate your query with a semicolon, the  <Quote>\g</Quote> is  not
+     necessary.   <Application>psql</Application> will automatically process semicolon terminated queries.
+     To read queries from a file,  say  myFile,  instead  of
+     entering them interactively, type:
+<ProgramListing>
+mydb=> \i fileName
+</ProgramListing>
+
+     To get out of <Application>psql</Application> and return to UNIX, type
+<ProgramListing>
+mydb=> \q
+</ProgramListing>
+
+     and  <Application>psql</Application>  will  quit  and  return  you to your command
+     shell. (For more escape codes, type <Command>\h</Command> at  the  monitor
+     prompt.)
+     White  space  (i.e.,  spaces, tabs and newlines) may be
+     used freely in <Acronym>SQL</Acronym> queries.  Single-line comments  are  denoted  by
+     <Quote>--</Quote>.   Everything  after the dashes up to the end of the
+     line is ignored. Multiple-line comments, and comments within a line,
+     are denoted by <Quote>/* ... */</Quote>
+</Para>
+
+<Sect2>
+<Title>Database Privileges</Title>
+
+<Para>
+</Sect2>
+
+<Sect2>
+<Title>Table Privileges</Title>
+
+<Para>
+TBD
+</Para>
+
+</Sect2>
+
+</Sect1>
+     
+<Sect1>
+<Title>Destroying a Database</Title>
+
+<Para>
+     If you are the database administrator for the  database
+     <Database>mydb</Database>,  you can destroy it using the following UNIX command:
+<ProgramListing>
+% destroydb mydb
+</ProgramListing>
+     This action physically removes all of  the  UNIX  files
+     associated  with  the database and cannot be undone, so
+     this should only be done with a  great  deal  of  forethought.
+</Para>
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/odbc.sgml b/doc/src/sgml/odbc.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..cb75579b6b6b1bfe88f40c459b7513db05400a50
--- /dev/null
+++ b/doc/src/sgml/odbc.sgml
@@ -0,0 +1,98 @@
+<Chapter>
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Tim</FirstName>
+<Surname>Goeke</Surname>
+</Author>
+</AuthorGroup>
+<Date>Transcribed 1998-02-12</Date>
+</DocInfo>
+
+<Title>ODBC Interface</Title>
+
+<Para>
+<Note>
+<Para>
+Contributed by <ULink url="mailto:tgoeke@xpressway.com">Tim Goeke</ULink>
+</Para>
+</Note>
+
+<Para>
+ODBC is an abstract API which allows you to write standard "ODBC" code,
+using the ODBC API.
+
+<Sect1>
+<Title>Background</Title>
+
+<Para>
+The ODBC API matches up on the backend to an ODBC compatible data source.
+This could be anything from a text file to an Oracle RDBMS.
+
+<Para>
+The backend access come from ODBC drivers, or vendor specifc drivers that
+allow data access.   PostODBC is such a driver, along with others that are
+available, such as the OpenLink ODBC drivers.
+
+<Para>
+Once you write an ODBC application, you SHOULD be able to connect to ANY
+back end database, regardless of the vendor, as long as the database schema
+is the same.
+
+<Para>
+For example. you could have MS SQL Server and PostgreSQL servers which have
+exactly the same data.  Using ODBC, your Windows app would make exactly the
+same calls and the back end data source would look the same (to the windows
+app).
+
+<Para>
+In the real world, differences in drivers and the level of ODBC support
+lessens the potential of ODBC:
+
+<SimpleList>
+<Member>
+Access, Delphi, and Visual Basic all support ODBC directly.
+
+<Member>
+Under C++, such as Visual C++, you can use the C++ ODBC API.
+
+<Member>
+In Visual C++, you can use the CRecordSet class, which wraps the ODBC API
+set within and MFC 4.2 class.  This is the easiest route if you are doing
+Windows C++ development under Windows NT.
+</SimpleList>
+
+<Para>
+If I write an app for PostgreSQL can I write it using ODBC calls
+to the PostgreSQL server, or is that only when another database program 
+like MS SQL Server or Access needs to access the data?
+
+<Para>
+Again, the ODBC API set is the way to go.   You can find out more at
+Microsoft's web site or in your Visual C++ docs (if that's what you are
+using.)
+
+<Para>
+Visual Basic and the other RAD tools have Recordset objects that use ODBC
+directly to access data.  Using the data-aware controls, you can quickly
+link to the ODBC back end database (<Emphasis>very</Emphasis> quickly).
+
+<Para>
+Playing around with MS Access will help you sort this out.  Try using
+File->Get External Data
+
+<Para>
+<Tip>
+<Para>
+You'll have to set up a DSN first.
+</Para>
+</Tip>
+
+<Para>
+<Tip>
+<Para>
+The PostgreSQL datetime type will break MS Access.
+</Para>
+</Tip>
+
+</Chapter>
diff --git a/doc/src/sgml/pgaccess.sgml b/doc/src/sgml/pgaccess.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..9404e71b4e1cae52d083b399c509b7500c4674ac
--- /dev/null
+++ b/doc/src/sgml/pgaccess.sgml
@@ -0,0 +1,8 @@
+<Chapter>
+<Title><Command>pgaccess</Command></Title>
+
+<Para>
+This section needs to be written. Volunteers?
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/ports.sgml b/doc/src/sgml/ports.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..0ee18b543fe2f8dac5c674b9265202f094db984c
--- /dev/null
+++ b/doc/src/sgml/ports.sgml
@@ -0,0 +1,264 @@
+<Chapter>
+<Title>Ports</Title>
+
+<Sect1>
+<Title>Currently Supported Platforms</Title>
+
+<Para>
+     <ProductName>Postgres</ProductName>  is  available  free  of charge. This manual
+     describes version 6.3 of <ProductName>Postgres</ProductName>.  The authors  have
+     compiled  and  tested <ProductName>Postgres</ProductName> on the following 
+     platforms:
+
+<TABLE TOCENTRY="1">
+<TITLE>Supported Platforms</TITLE>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY><Acronym>OS</Acronym></ENTRY>
+    <ENTRY>Processor</ENTRY>
+    <ENTRY>Version</ENTRY>
+    <ENTRY>Reported</ENTRY>
+    <ENTRY>Remarks</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>AIX 4.1.x-4.2</ENTRY>
+    <ENTRY>RS6000</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>4.1.4.0,4.2 (<ULink url="mailto:darrenk@insightdist.com">Darren King</ULink>),
+4.1.5 (<ULink url="mailto:Andreas.Zeugswetter@telecom.at">Andreas Zeugswetter</ULink>);
+3.2.5 confirmed on v6.2.1 (<ULink url="mailto:danaf@ans.net">Frank Dana</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>BSDi</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:maillist@candle.pha.pa.us">Bruce Momjian</ULink></ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>FreeBSD 2.2.x-3.x</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>,
+<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NetBSD 1.3</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:brook@trillium.NMSU.Edu">Brook Milligan</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NetBSD 1.3</ENTRY>
+    <ENTRY>Sparc</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:tih@hamartun.priv.no">Tom I Helbekkmo</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NetBSD 1.3</ENTRY>
+    <ENTRY>VAX</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:tih@hamartun.priv.no">Tom I Helbekkmo</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>DGUX 5.4R4.11</ENTRY>
+    <ENTRY>m88k</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:geek+@cmu.edu">Brian E Gallew</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>HPUX 10.20</ENTRY>
+    <ENTRY>PA-RISC</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>9.0.x confirmed on v6.2.1 (<ULink url="mailto:stanb@awod.com">Stan Brown</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>IRIX 6.x</ENTRY>
+    <ENTRY>MIPS</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>5.x is different (<ULink url="mailto:martin@biochemistry.ucl.ac.uk">Andrew Martin</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Digital 4.0</ENTRY>
+    <ENTRY>Alpha</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>in progress; v6.2.1 confirmed working (<ULink url="mailto:pjlobo@euitt.upm.es">Pedro J. Lobo</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>linux 2.0.x</ENTRY>
+    <ENTRY>Alpha</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>partial success (<ULink url="mailto:rkirkpat@nag.cs.colorado.edu">Ryan Kirkpatrick</ULink>,
+<ULink url="mailto:jsturm@zenacomp.com"> Jeff Sturm </ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>linux 2.0.x</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:lockhart@alumni.caltech.edu">Thomas Lockhart</ULink>,
+<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>linux 2.0.x</ENTRY>
+    <ENTRY>Sparc</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:szybist@boxhill.com">Tom Szybist</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>mklinux</ENTRY>
+    <ENTRY>PPC</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>SCO</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>partial success (<ULink url="mailto:Bill.Allie@mug.org">Billy G. Allie</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Solaris</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Solaris 2.5.1-2.6</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>(<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>,
+<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>SunOS 4.1.4</ENTRY>
+    <ENTRY>Sparc</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>patches submitted (<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>SVR4</ENTRY>
+    <ENTRY>MIPS</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>similar to v6.2.1; "mostly working" (<ULink url="mailto:ridderbusch.pad@sni.de">Frank Ridderbusch</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>SVR4 4.4</ENTRY>
+    <ENTRY>m88k</ENTRY>
+    <ENTRY>v6.2.1</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>confirmed with patching (<ULink url="mailto:dlw@seavme.xroads.com">Doug Winterburn</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Unixware</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>aka UNIVEL (<ULink url="mailto:Bill.Allie@mug.org">Billy G. Allie</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NextStep</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.x</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>client-only support; v1.0.9 worked with patches (<ULink url="mailto:dave@turbocat.de">David Wetzel</ULink>)</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+
+<Sect1>
+<Title>Unsupported Platforms</Title>
+
+<Para>
+A few platforms which have been attempted and which have been
+reported to not work with the standard distribution.
+Others listed here do not provide sufficient library support for an attempt.
+
+<TABLE TOCENTRY="1">
+<TITLE>Possibly Incompatible Platforms</TITLE>
+<TITLEABBREV>Incompatibles</TITLEABBREV>
+<TGROUP COLS="4">
+<THEAD>
+  <ROW>
+    <ENTRY><Acronym>OS</Acronym></ENTRY>
+    <ENTRY>Processor</ENTRY>
+    <ENTRY>Version</ENTRY>
+    <ENTRY>Reported</ENTRY>
+    <ENTRY>Remarks</ENTRY>
+  </ROW>
+</THEAD>
+<TBODY>
+  <ROW>
+    <ENTRY>MacOS</ENTRY>
+    <ENTRY>all</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>not library compatible; use ODBC/JDBC</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NetBSD</ENTRY>
+    <ENTRY>arm32</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>not yet working (<ULink url="mailto:dmill@globalnet.co.uk">Dave Millen</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>NetBSD</ENTRY>
+    <ENTRY>m68k</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>Amiga, HP300, Mac; not yet working (<ULink url="mailto:hotz@jpl.nasa.gov">Henry Hotz</ULink>)</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Ultrix</ENTRY>
+    <ENTRY>MIPS,VAX?</ENTRY>
+    <ENTRY>v6.x</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>no recent reports; obsolete?</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Windows NT</ENTRY>
+    <ENTRY>all</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>not library compatible; client side maybe; use ODBC/JDBC</ENTRY>
+  </ROW>
+  <ROW>
+    <ENTRY>Windows</ENTRY>
+    <ENTRY>x86</ENTRY>
+    <ENTRY>v6.3</ENTRY>
+    <ENTRY>1998-03-01</ENTRY>
+    <ENTRY>not library compatible; client side maybe; use ODBC/JDBC</ENTRY>
+  </ROW>
+</TBODY>
+</TGROUP>
+</TABLE>
+
+<Para>
+Note that Windows ports of the frontend are apparently possible
+using third-party Posix porting tools and libraries.
+</Para>
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..897de1be1bdc058a02a91b09347d8de346a4604a
--- /dev/null
+++ b/doc/src/sgml/postgres.sgml
@@ -0,0 +1,244 @@
+<!-- postgres.sgml
+-
+- Postgres integrated documentation.
+- Other subset docs should be copied and shrunk from here.
+- thomas 1998-02-23
+-
+- -->
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!entity intro    SYSTEM "intro.sgml">
+<!entity arch     SYSTEM "arch.sgml">
+<!entity start    SYSTEM "start.sgml">
+<!entity query    SYSTEM "query.sgml">
+
+<!entity advanced SYSTEM "advanced.sgml">
+<!entity environ  SYSTEM "environ.sgml">
+<!entity manage   SYSTEM "manage.sgml">
+<!entity datatype SYSTEM "datatype.sgml">
+<!entity array    SYSTEM "array.sgml">
+<!entity inherit  SYSTEM "inherit.sgml">
+<!entity query-ug SYSTEM "query-ug.sgml">
+<!entity storage  SYSTEM "storage.sgml">
+<!entity psql     SYSTEM "psql.sgml">
+<!entity pgaccess SYSTEM "pgaccess.sgml">
+
+<!entity start-ag SYSTEM "start-ag.sgml">
+<!entity install  SYSTEM "install.sgml">
+<!entity recovery SYSTEM "recovery.sgml">
+<!entity regress  SYSTEM "regress.sgml">
+<!entity ports    SYSTEM "ports.sgml">
+<!entity release  SYSTEM "release.sgml">
+
+<!entity intro-pg SYSTEM "intro-pg.sgml">
+<!entity arch-pg  SYSTEM "arch-pg.sgml">
+<!entity extend   SYSTEM "extend.sgml">
+<!entity rules    SYSTEM "rules.sgml">
+<!entity xfunc    SYSTEM "xfunc.sgml">
+<!entity xtypes   SYSTEM "xtypes.sgml">
+<!entity xoper    SYSTEM "xoper.sgml">
+<!entity xaggr    SYSTEM "xaggr.sgml">
+<!entity xindex   SYSTEM "xindex.sgml">
+<!entity gist     SYSTEM "gist.sgml">
+<!entity dfunc    SYSTEM "dfunc.sgml">
+<!entity lobj     SYSTEM "lobj.sgml">
+<!entity trigger  SYSTEM "trigger.sgml">
+<!entity spi      SYSTEM "spi.sgml">
+<!entity func-ref SYSTEM "func-ref.sgml">
+<!entity libpq    SYSTEM "libpq.sgml">
+<!entity libpgtcl SYSTEM "libpgtcl.sgml">
+<!entity ecpg     SYSTEM "ecpg.sgml">
+<!entity odbc     SYSTEM "odbc.sgml">
+<!entity jdbc     SYSTEM "jdbc.sgml">
+
+<!entity arch-dev SYSTEM "arch-dev.sgml">
+<!entity geqo     SYSTEM "geqo.sgml">
+<!entity protocol SYSTEM "protocol.sgml">
+<!entity compiler SYSTEM "compiler.sgml">
+<!entity docguide SYSTEM "docguide.sgml">
+<!entity biblio   SYSTEM "biblio.sgml">
+<!entity contacts SYSTEM "contacts.sgml">
+]>
+<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc -->
+<Book>
+
+<!-- Title information -->
+
+<Title>PostgreSQL</Title>
+<BookInfo>
+    <ReleaseInfo>Covering v6.3 for general release</ReleaseInfo>
+    <BookBiblio>
+    <AuthorGroup>
+      <CorpAuthor>The PostgreSQL Development Team</CorpAuthor>
+    </AuthorGroup>
+<!-- editor in authorgroup is not supported
+    <AuthorGroup>
+-->
+      <Editor>
+        <FirstName>Thomas</FirstName>
+        <SurName>Lockhart</SurName>
+        <Affiliation>
+          <OrgName>Caltech/JPL</OrgName>
+        </Affiliation>
+      </Editor>
+<!--
+    </AuthorGroup>
+-->
+ 
+<!--
+    <AuthorInitials>TGL</AuthorInitials>
+-->
+
+    <Date>(last updated 1998-02-23)</Date>
+    </BookBiblio>
+
+<LegalNotice>
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group.
+</Para>
+</LegalNotice>
+
+</BookInfo>
+
+<!--
+<TOC> </TOC>
+<LOT> </LOT>
+-->
+
+<!--
+<Dedication>
+<Para>
+Your name here...
+</Para>
+</Dedication>
+-->
+
+<Preface>
+<Title>Summary</Title>
+
+<Para>
+<ProductName>Postgres</ProductName>, 
+ developed originally in the UC Berkeley Computer Science Department,
+ pioneered many of the object-relational concepts
+ now becoming available in some commercial databases.
+It provides SQL92/SQL3 language support,
+ transaction integrity, and type extensibility.
+ <ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant
+ of this original Berkeley code.
+</Para>
+</Preface>
+
+<Part>
+<Title>Tutorial</Title>
+<PartIntro>
+<Para>
+Introduction for new users.
+</Para>
+</PartIntro>
+&intro;
+&arch;
+&start;
+&query;
+&advanced;
+</Part>
+
+<Part>
+<Title>User's Guide</Title>
+<PartIntro>
+<Para>
+Information for users.
+</Para>
+</PartIntro>
+&environ;
+&manage;
+&datatype;
+&array;
+&inherit;
+&query-ug;
+&storage;
+&psql;
+&pgaccess;
+</Part>
+
+<Part>
+<Title>Administrator's Guide</Title>
+<PartIntro>
+<Para>
+Installation and maintenance information.
+</Para>
+</PartIntro>
+&ports;
+&install;
+&start-ag;
+&recovery;
+&regress;
+&release;
+</Part>
+
+<Part>
+<Title>Programmer's Guide</Title>
+<PartIntro>
+<Para>
+Information for extending <ProductName>Postgres</ProductName>.
+</Para>
+</PartIntro>
+&intro-pg;
+&arch-pg;
+&extend;
+&xfunc;
+&xtypes;
+&xoper;
+&xaggr;
+&xindex;
+&gist;
+&dfunc;
+&trigger;
+&spi;
+&libpq;
+</Part>
+
+<Part>
+<Title>Reference</Title>
+<PartIntro>
+<Para>
+User and programmer interfaces.
+</Para>
+</PartIntro>
+&func-ref;
+&lobj;
+&ecpg;
+&libpq;
+&libpgtcl;
+&odbc;
+&jdbc;
+</Part>
+
+<Part>
+<Title>Developer's Guide</Title>
+<PartIntro>
+<Para>
+The Developer's Guide includes discussion of design decisions and suggestions for
+future development.
+</Para>
+</PartIntro>
+&arch-dev;
+&geqo;
+&protocol;
+&compiler;
+</Part>
+
+<Part>
+<Title>Appendices</Title>
+<PartIntro>
+<Para>
+Additional related information.
+</Para>
+</PartIntro>
+&docguide;
+&contacts;
+&biblio;
+</Part>
+
+<INDEX> </INDEX>
+
+</Book>
+
diff --git a/doc/src/sgml/programmer.sgml b/doc/src/sgml/programmer.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..3c73484e077b787a22f1a32bf275a307824c0cb2
--- /dev/null
+++ b/doc/src/sgml/programmer.sgml
@@ -0,0 +1,173 @@
+<!-- programmer.sgml
+-
+- Postgres programmer's guide.
+- Derived from postgres.sgml.
+- thomas 1998-02-24
+-
+- -->
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!entity intro    SYSTEM "intro.sgml">
+<!entity arch     SYSTEM "arch.sgml">
+<!entity start    SYSTEM "start.sgml">
+<!entity query    SYSTEM "query.sgml">
+
+<!entity advanced SYSTEM "advanced.sgml">
+<!entity environ  SYSTEM "environ.sgml">
+<!entity manage   SYSTEM "manage.sgml">
+<!entity datatype SYSTEM "datatype.sgml">
+<!entity array    SYSTEM "array.sgml">
+<!entity inherit  SYSTEM "inherit.sgml">
+<!entity query-ug SYSTEM "query-ug.sgml">
+<!entity storage  SYSTEM "storage.sgml">
+<!entity psql     SYSTEM "psql.sgml">
+<!entity pgaccess SYSTEM "pgaccess.sgml">
+
+<!entity start-ag SYSTEM "start-ag.sgml">
+<!entity install  SYSTEM "install.sgml">
+<!entity recovery SYSTEM "recovery.sgml">
+<!entity regress  SYSTEM "regress.sgml">
+<!entity ports    SYSTEM "ports.sgml">
+<!entity release  SYSTEM "release.sgml">
+
+<!entity intro-pg SYSTEM "intro-pg.sgml">
+<!entity arch-pg  SYSTEM "arch-pg.sgml">
+<!entity extend   SYSTEM "extend.sgml">
+<!entity rules    SYSTEM "rules.sgml">
+<!entity xfunc    SYSTEM "xfunc.sgml">
+<!entity xtypes   SYSTEM "xtypes.sgml">
+<!entity xoper    SYSTEM "xoper.sgml">
+<!entity xaggr    SYSTEM "xaggr.sgml">
+<!entity xindex   SYSTEM "xindex.sgml">
+<!entity gist     SYSTEM "gist.sgml">
+<!entity dfunc    SYSTEM "dfunc.sgml">
+<!entity lobj     SYSTEM "lobj.sgml">
+<!entity trigger  SYSTEM "trigger.sgml">
+<!entity spi      SYSTEM "spi.sgml">
+<!entity func-ref SYSTEM "func-ref.sgml">
+<!entity libpq    SYSTEM "libpq.sgml">
+<!entity libpgtcl SYSTEM "libpgtcl.sgml">
+<!entity ecpg     SYSTEM "ecpg.sgml">
+<!entity odbc     SYSTEM "odbc.sgml">
+<!entity jdbc     SYSTEM "jdbc.sgml">
+
+<!entity arch-dev SYSTEM "arch-dev.sgml">
+<!entity geqo     SYSTEM "geqo.sgml">
+<!entity protocol SYSTEM "protocol.sgml">
+<!entity compiler SYSTEM "compiler.sgml">
+<!entity docguide SYSTEM "docguide.sgml">
+<!entity biblio   SYSTEM "biblio.sgml">
+<!entity contacts SYSTEM "contacts.sgml">
+]>
+<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc -->
+<Book>
+
+<!-- Title information -->
+
+<Title>PostgreSQL Programmer's Guide</Title>
+<BookInfo>
+    <ReleaseInfo>Covering v6.3 for general release</ReleaseInfo>
+    <BookBiblio>
+    <AuthorGroup>
+      <CorpAuthor>The PostgreSQL Development Team</CorpAuthor>
+    </AuthorGroup>
+<!-- editor in authorgroup is not supported
+    <AuthorGroup>
+-->
+      <Editor>
+        <FirstName>Thomas</FirstName>
+        <SurName>Lockhart</SurName>
+        <Affiliation>
+          <OrgName>Caltech/JPL</OrgName>
+        </Affiliation>
+      </Editor>
+<!--
+    </AuthorGroup>
+-->
+ 
+<!--
+    <AuthorInitials>TGL</AuthorInitials>
+-->
+
+    <Date>(last updated 1998-02-24)</Date>
+    </BookBiblio>
+
+<LegalNotice>
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group.
+</Para>
+</LegalNotice>
+
+</BookInfo>
+
+<!--
+<TOC> </TOC>
+<LOT> </LOT>
+-->
+
+<!--
+<Dedication>
+<Para>
+Your name here...
+</Para>
+</Dedication>
+-->
+
+<Preface>
+<Title>Summary</Title>
+
+<Para>
+<ProductName>Postgres</ProductName>, 
+ developed originally in the UC Berkeley Computer Science Department,
+ pioneered many of the object-relational concepts
+ now becoming available in some commercial databases.
+It provides SQL92/SQL3 language support,
+ transaction integrity, and type extensibility.
+ <ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant
+ of this original Berkeley code.
+</Para>
+</Preface>
+
+&intro-pg;
+&arch-pg;
+&extend;
+&xfunc;
+&xtypes;
+&xoper;
+&xaggr;
+&xindex;
+&gist;
+&dfunc;
+&trigger;
+&spi;
+
+<!-- reference -->
+
+&func-ref;
+&lobj;
+&ecpg;
+&libpq;
+&libpgtcl;
+&odbc;
+&jdbc;
+
+<!-- development -->
+
+&arch-dev;
+&geqo;
+&protocol;
+&compiler;
+
+<!-- appendices -->
+
+&docguide;
+<!--
+&contacts;
+-->
+&biblio;
+
+<!--
+<INDEX> </INDEX>
+-->
+
+</Book>
+
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..af5acc1e0f7533f55e7117ad3e20c606b3fe4f3a
--- /dev/null
+++ b/doc/src/sgml/protocol.sgml
@@ -0,0 +1,1509 @@
+<Chapter>
+<DocInfo>
+<Author>
+<FirstName>Phil</FirstName>
+<Surname>Thompson</Surname>
+</Author>
+<Date>1998-02-02</Date>
+</DocInfo>
+<Title>Frontend/Backend Protocol</Title>
+
+<Para>
+<Note>
+<Para>
+Written by <ULink url="mailto:phil@river-bank.demon.co.uk">Phil Thompson</ULink>
+</Para>
+</Note>
+
+<Para>
+<ProductName>Postgres</ProductName> uses a message-based protocol for communication between frontends
+and backends.  The protocol is implemented over <Acronym>TCP/IP</Acronym> and also on Unix sockets.
+<ProductName>Postgres</ProductName> v6.3 introduced version numbers into the protocol.
+This was done in such
+a way as to still allow connections from earlier versions of frontends, but
+this document does not cover the protocol used by those earlier versions.
+
+<Para>
+This document describes the initial version-numbered protocol, designated v1.0.
+Higher level features built on this protocol (for example, how <FileName>libpq</FileName> passes
+certain environment variables after the connection is established)
+are covered elsewhere.
+
+<Sect1>
+<Title>Overview</Title>
+
+<Para>
+The three major components are the frontend (running on the client) and the
+postmaster and backend (running on the server).  The postmaster and backend
+have different roles but may be implemented by the same executable.
+
+<Para>
+A frontend sends a startup packet to the postmaster.  This includes the names
+of the user and the database the user wants to connect to.  The postmaster then
+uses this, and the information in the pg_hba.conf(5) file to determine what
+further authentication information it requires the frontend to send (if any)
+and responds to the frontend accordingly.
+
+<Para>
+The frontend then sends any required authentication information.  Once the
+postmaster validates this it responds to the frontend that it is authenticated
+and hands over to a backend.
+
+<Para>
+Subsequent communications are query and result packets exchanged between the
+frontend and the backend.  The postmaster takes no further part in the
+communication.
+
+<Para>
+When the frontend wishes to disconnect it sends an appropriate packet and
+closes the connection without waiting for a response for the backend.
+
+<Para>
+Packets are sent as a data stream.  The first byte determines what should be
+expected in the rest of the packet.  The exception is packets send from a
+frontend to the postmaster, which comprise a packet length then the packet
+itself.  The difference is historical.
+
+<Sect1>
+<Title>Protocol</Title>
+
+<Para>
+This section describes the message flow.  There are four different types of
+flows depending on the state of the connection:
+ authentication, query, function call, and termination.
+
+<Sect2>
+<Title>Authentication</Title>
+
+<Para>
+The frontend sends a StartupPacket.  The postmaster uses this and the contents
+of the pg_hba.conf(5) file to determine what authentication method the frontend
+must use.  The postmaster then responds with one of the following messages:
+
+<Para>
+<VariableList>
+<VarListEntry>
+<Term>
+	ErrorResponse
+</Term>
+<ListItem>
+<Para>
+		The postmaster then immediately closes the connection.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	AuthenticationOk
+</Term>
+<ListItem>
+<Para>
+		The postmaster then hands over to the backend.  The postmaster
+		takes no further part in the communication.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	AuthenticationKerberosV4
+</Term>
+<ListItem>
+<Para>
+		The frontend must then take part in a Kerberos V4
+		authentication dialog (not described here) with the postmaster.
+		If this is successful, the postmaster responds with an
+		AuthenticationOk, otherwise it responds with an ErrorResponse.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	AuthenticationKerberosV5
+</Term>
+<ListItem>
+<Para>
+		The frontend must then take part in a Kerberos V5
+		authentication dialog (not described here) with the postmaster.
+		If this is successful, the postmaster responds with an
+		AuthenticationOk, otherwise it responds with an ErrorResponse.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	AuthenticationUnencryptedPassword
+</Term>
+<ListItem>
+<Para>
+		The frontend must then send an UnencryptedPasswordPacket.
+		If this is the correct password, the postmaster responds with
+		an AuthenticationOk, otherwise it responds with an
+		ErrorResponse.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	AuthenticationEncryptedPassword
+</Term>
+<ListItem>
+<Para>
+		The frontend must then send an EncryptedPasswordPacket.
+		If this is the correct password, the postmaster responds with
+		an AuthenticationOk, otherwise it responds with an
+		ErrorResponse.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+If the frontend does not support the authentication method requested by the
+postmaster, then it should immediately close the connection.
+
+<Sect2>
+<Title>Query</Title>
+
+<Para>
+The frontend sends a Query message to the backend.  The response sent by the
+backend depends on the contents of the query.  The possible responses are as
+follows.
+
+<Para>
+<VariableList>
+<VarListEntry>
+<Term>
+	CompletedResponse
+</Term>
+<ListItem>
+<Para>
+		The query completed normally.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	CopyInResponse
+</Term>
+<ListItem>
+<Para>
+		The backend is ready to copy data from the frontend to a
+		relation.  The frontend should then send a CopyDataRows
+		message.  The backend will then respond with a
+		CompletedResponse message with a tag of "COPY".
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	CopyOutResponse
+</Term>
+<ListItem>
+<Para>
+		The backend is ready to copy data from a relation to the
+		frontend.  It then sends a CopyDataRows message, and then a
+		CompletedResponse message with a tag of "COPY".
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	CursorResponse
+</Term>
+<ListItem>
+<Para>
+		The query was either an insert(l), delete(l), update(l),
+		fetch(l) or a select(l) command.
+                If the transaction has been
+                aborted then the backend sends a CompletedResponse message with
+                a tag of "*ABORT STATE*".  Otherwise the following responses
+                are sent.
+</Para>
+<Para>
+		For an insert(l) command, the backend then sends a
+		CompletedResponse message with a tag of "INSERT <Replaceable>oid</Replaceable> <Replaceable>rows</Replaceable>"
+		where <Replaceable>rows</Replaceable> is the number of rows inserted, and <Replaceable>oid</Replaceable> is the
+		object ID of the inserted row if <Replaceable>rows</Replaceable> is 1, otherwise <Replaceable>oid</Replaceable>
+		is 0.
+</Para>
+<Para>
+		For a delete(l) command, the backend then sends a
+		CompletedResponse message with a tag of "DELETE <Replaceable>rows</Replaceable>" where
+		<Replaceable>rows</Replaceable> is the number of rows deleted.
+</Para>
+<Para>
+		For an update(l) command, the backend then sends a
+		CompletedResponse message with a tag of "UPDATE <Replaceable>rows</Replaceable>" where
+		<Replaceable>rows</Replaceable> is the number of rows deleted.
+</Para>
+<Para>
+		For a fetch(l) or select(l) command, the backend sends a
+		RowDescription message.  This is then followed by an AsciiRow
+		or BinaryRow message (depending on if a binary cursor was
+		specified) for each row being returned to the frontend.
+		Finally, the backend sends a CompletedResponse message with a
+		tag of "SELECT".
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	EmptyQueryResponse
+</Term>
+<ListItem>
+<Para>
+		The query was empty.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	ErrorResponse
+</Term>
+<ListItem>
+<Para>
+		An error has occurred.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	NoticeResponse
+</Term>
+<ListItem>
+<Para>
+		A warning message has been issued in relation to the query.
+		Notices are in addition to other responses, ie. the backend
+		will send another response message immediately afterwards.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	NotificationResponse
+</Term>
+<ListItem>
+<Para>
+		A notify(l) command has been executed for a relation for
+		which a previous listen(l) command was executed.  Notifications
+		are in addition to other responses, ie. the backend will send
+		another response message immediately afterwards.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+A frontend must be prepared to accept ErrorResponse and NoticeResponse
+messages whenever it is expecting any other type of message.
+
+<Sect2>
+<Title>Function Call</Title>
+
+<Para>
+The frontend sends a FunctionCall message to the backend.  The response sent by
+the backend depends on the result of the function call.  The possible responses
+are as follows.
+
+<Para>
+<VariableList>
+<VarListEntry>
+<Term>
+	ErrorResponse
+</Term>
+<ListItem>
+<Para>
+		An error has occurred.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	FunctionResultResponse
+</Term>
+<ListItem>
+<Para>
+		The function call was executed and returned a result.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	FunctionVoidResponse
+</Term>
+<ListItem>
+<Para>
+		The function call was executed and returned no result.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	NoticeResponse
+</Term>
+<ListItem>
+<Para>
+		A warning message has been issued in relation to the function
+		call.  Notices are in addition to other responses, ie. the
+		backend will send another response message immediately
+		afterwards.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+A frontend must be prepared to accept ErrorResponse and NoticeResponse
+messages whenever it is expecting any other type of message.
+
+<Sect2>
+<Title>Termination</Title>
+
+<Para>
+The frontend sends a Terminate message and immediately closes the connection.
+On receipt of the message, the backend immediately closes the connection and
+terminates.
+
+
+<Sect1>
+<Title>Message Data Types</Title>
+
+<Para>
+This section describes the base data types used in messages.
+
+<Para>
+<VariableList>
+<VarListEntry>
+<Term>
+	Int<Replaceable>n</Replaceable>(<Replaceable>i</Replaceable>)
+</Term>
+<ListItem>
+<Para>
+		An <Replaceable>n</Replaceable> bit integer in network byte order.
+                If <Replaceable>i</Replaceable> is specified it
+		is the literal value.  Eg. Int16, Int32(42).
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString<Replaceable>n</Replaceable>(<Replaceable>s</Replaceable>)
+</Term>
+<ListItem>
+<Para>
+		A character array of exactly <Replaceable>n</Replaceable> bytes interpreted as a '\0'
+		terminated string.  The '\0' is omitted if there is
+		insufficient room.  If <Replaceable>s</Replaceable> is specified it is the literal value.
+		Eg. LimString32, LimString64("user").
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String(<Replaceable>s</Replaceable>)
+</Term>
+<ListItem>
+<Para>
+		A conventional C '\0' terminated string with no length
+		limitation.  A frontend should always read the full string
+		even though it may have to discard characters if it's buffers
+		aren't big enough.
+<Note>
+<Para>
+Is 8193 bytes the largest allowed size?
+</Para>
+</Note>
+		If <Replaceable>s</Replaceable> is specified it is the literal value.
+		Eg. String, String("user").
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte<Replaceable>n</Replaceable>(<Replaceable>c</Replaceable>)
+</Term>
+<ListItem>
+<Para>
+		Exactly <Replaceable>n</Replaceable> bytes.  If <Replaceable>c</Replaceable> is specified it is the literal
+		value.  Eg. Byte, Byte1('\n').
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Sect1>
+<Title>Message Formats</Title>
+
+<Para>
+This section describes the detailed format of each message.  Each can be sent
+by either a frontend (F), a postmaster/backend (B), or both (F & B).
+
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+AsciiRow (B)
+</Term>
+<ListItem>
+<Para>
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('D')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message, in the context in which it is sent (see
+		CopyInResponse), as an <Acronym>ASCII</Acronym> row.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+
+                A bit map with one bit for each field in the row.  The 1st
+                field corresponds to bit 7 of the 1st byte, the 2nd field
+                corresponds to bit 6 of the 1st byte, the 8th field corresponds
+                to bit 0 of the 1st byte, the 9th field corresponds to bit 8 of
+                the 2nd byte, and so on.  The bit is set if the value of the
+                corresponding field is not NULL.
+</Para>
+<Para>
+	Then, for each field, there is the following:
+<VariableList>
+<VarListEntry>
+<Term>
+		Int32
+</Term>
+<ListItem>
+<Para>
+			Specifies the size of the value of the field, including
+			this size.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+		Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+			Specifies the value of the field itself in <Acronym>ASCII</Acronym>
+			characters.  <Replaceable>n</Replaceable> is the above size minus 4.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+AuthenticationOk (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('R')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an authentication request.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32(0)
+</Term>
+<ListItem>
+<Para>
+		Specifies that the authentication was successful.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+AuthenticationKerberosV4 (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('R')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an authentication request.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32(1)
+</Term>
+<ListItem>
+<Para>
+		Specifies that Kerberos V4 authentication is required.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+AuthenticationKerberosV5 (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('R')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an authentication request.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32(2)
+</Term>
+<ListItem>
+<Para>
+		Specifies that Kerberos V5 authentication is required.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+AuthenticationUnencryptedPassword (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('R')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an authentication request.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32(3)
+</Term>
+<ListItem>
+<Para>
+		Specifies that an unencrypted password is required.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+AuthenticationEncryptedPassword (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('R')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an authentication request.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32(4)
+</Term>
+<ListItem>
+<Para>
+		Specifies that an encrypted password is required.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte2
+</Term>
+<ListItem>
+<Para>
+		The salt to use when encrypting the password.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+BinaryRow (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('B')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message, in the context in which it is sent (see
+		CopyOutResponse), as a binary row.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+                A bit map with one bit for each field in the row.  The 1st
+                field corresponds to bit 7 of the 1st byte, the 2nd field
+                corresponds to bit 6 of the 1st byte, the 8th field corresponds
+                to bit 0 of the 1st byte, the 9th field corresponds to bit 8 of
+                the 2nd byte, and so on.  The bit is set if the value of the
+                corresponding field is not NULL.
+</Para>
+<Para>
+	Then, for each field, there is the following:
+<VariableList>
+<VarListEntry>
+<Term>
+		Int32
+</Term>
+<ListItem>
+<Para>
+			Specifies the size of the value of the field, excluding
+			this size.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+		Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+			Specifies the value of the field itself in binary
+			format.  <Replaceable>n</Replaceable> is the above size.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+CompletedResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('C')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a completed response.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The command tag.  This is usually (but not always) a single
+		word that identifies which SQL command was completed.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+CopyDataRows (B & F)
+</Term>
+<ListItem>
+<Para>
+	This is a stream of rows where each row is terminated by a Char1('\n').
+	This is then followed by the sequence Char1('\\'), Char1('.'),
+	Char1('\n').
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+CopyInResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('D')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message, in the context in which it is sent (see
+		AsciiRow), as a copy in started response.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+CopyOutResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('B')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message, in the context in which it is sent (see
+		BinaryRow), as a copy out started response.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+CursorResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('P')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a cursor response.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The name of the cursor.  This will be "blank" if the cursor is
+		implicit.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+EmptyQueryResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('I')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an empty query response.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String("")
+</Term>
+<ListItem>
+<Para>
+		Unused.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+EncryptedPasswordPacket (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		The size of the packet in bytes.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The encrypted (using crypt()) password.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+ErrorResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('E')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as an error.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The error message itself.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+FunctionCall (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('F')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a function call.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String("")
+</Term>
+<ListItem>
+<Para>
+		Unused.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		Specifies the object ID of the function to call.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		Specifies the number of arguments being supplied to the
+		function.
+</Para>
+<Para>
+	Then, for each argument, there is the following:
+<VariableList>
+<VarListEntry>
+<Term>
+		Int32
+</Term>
+<ListItem>
+<Para>
+			Specifies the size of the value of the argument,
+			excluding this size.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+		Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+			Specifies the value of the field itself in binary
+			format.  <Replaceable>n</Replaceable> is the above size.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+<Para>
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+FunctionResultResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('V')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a function call result.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte1('G')
+</Term>
+<ListItem>
+<Para>
+		Specifies that an actual result was returned.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		Specifies the size of the value of the result, excluding this
+		size.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte<Replaceable>n</Replaceable>
+</Term>
+<ListItem>
+<Para>
+		Specifies the value of the result itself in binary format.
+		<Replaceable>n</Replaceable> is the above size.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte1('0')
+</Term>
+<ListItem>
+<Para>
+		Unused.  (Strictly speaking, FunctionResultResponse and
+		FunctionVoidResponse are the same thing but with some optional
+		parts to the message.)
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+FunctionVoidResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('V')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a function call result.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Byte1('0')
+</Term>
+<ListItem>
+<Para>
+		Specifies that no actual result was returned.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+NoticeResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('N')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a notice.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The notice message itself.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+NotificationResponse (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('A')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a notification response.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		The process ID of the backend process.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The name of the relation that the notify has been raised on.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+Query (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('Q')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as query.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The query itself.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+RowDescription (B)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('T')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a row description.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int16
+</Term>
+<ListItem>
+<Para>
+		Specifies the number of fields in a row (and may be zero).
+</Para>
+<Para>
+	Then, for each field, there is the following:
+<VariableList>
+<VarListEntry>
+<Term>
+		String
+</Term>
+<ListItem>
+<Para>
+			Specifies the field name.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+		Int32
+</Term>
+<ListItem>
+<Para>
+			Specifies the object ID of the field type.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+		Int16
+</Term>
+<ListItem>
+<Para>
+			Specifies the type size.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+StartupPacket (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Int32(296)
+</Term>
+<ListItem>
+<Para>
+		The size of the packet in bytes.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		The protocol version number.  The most significant 16 bits are
+		the major version number.  The least 16 significant bits are
+		the minor version number.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString64
+</Term>
+<ListItem>
+<Para>
+		The database name, defaults to the user name if omitted.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString32
+</Term>
+<ListItem>
+<Para>
+		The user name.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString64
+</Term>
+<ListItem>
+<Para>
+		Any additional command line arguments to be passed to the
+		backend by the postmaster.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString64
+</Term>
+<ListItem>
+<Para>
+		Unused.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	LimString64
+</Term>
+<ListItem>
+<Para>
+		The optional tty the backend should use for debugging messages.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+Terminate (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Byte1('X')
+</Term>
+<ListItem>
+<Para>
+		Identifies the message as a termination.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+UnencryptedPasswordPacket (F)
+</Term>
+<ListItem>
+<Para>
+
+<VariableList>
+<VarListEntry>
+<Term>
+	Int32
+</Term>
+<ListItem>
+<Para>
+		The size of the packet in bytes.
+</Para>
+</ListItem>
+</VarListEntry>
+<VarListEntry>
+<Term>
+	String
+</Term>
+<ListItem>
+<Para>
+		The unencrypted password.
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+
+</Para>
+</ListItem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/psql.sgml b/doc/src/sgml/psql.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..3019396de7aa3f0647a8e30a02cec1510a7fd4b0
--- /dev/null
+++ b/doc/src/sgml/psql.sgml
@@ -0,0 +1,8 @@
+<Chapter>
+<Title><Command>psql</Command></Title>
+
+<Para>
+This section needs to be written. Volunteers?
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/query-ug.sgml b/doc/src/sgml/query-ug.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..a5fc3463a1536687edf0aa427eeca94319d03a03
--- /dev/null
+++ b/doc/src/sgml/query-ug.sgml
@@ -0,0 +1,332 @@
+<Chapter>
+<TITLE>The Query Language</TITLE>
+
+<Para>
+<Note>
+<Para>
+This chapter must go into depth on each area of the query language. Currently a copy of the tutorial.
+- thomas 1998-01-12
+</Para>
+</Note>
+</Para>
+
+<Para>
+     The  <ProductName>Postgres</ProductName>  query language is a variant of
+ <Acronym>SQL3</Acronym>. It
+     has many extensions such as an extensible type  system,
+     inheritance,  functions and production rules. Those are
+     features carried over from the original <ProductName>Postgres</ProductName>  query
+     language,  <ProductName>PostQuel</ProductName>.  This section provides an overview
+     of how to use <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym>  to  perform  simple  operations.
+     This manual is only intended to give you an idea of our
+     flavor of <Acronym>SQL</Acronym> and is in no way a complete  tutorial  on
+     <Acronym>SQL</Acronym>.  Numerous  books  have  been  written  on <Acronym>SQL</Acronym>. For
+     instance, consult <Ulink url="refs.html#MELT93">[MELT93]</ULink> or 
+     <Ulink url="refs.html#DATE93">[DATE93]</ULink>. You should also
+     be  aware  that  some features are not part of the <Acronym>ANSI</Acronym>
+     standard.
+</Para>
+
+<Sect1>
+<Title>Concepts</Title>
+
+<Para>
+     The fundamental notion in <ProductName>Postgres</ProductName> is that of a  class,
+     which  is a named collection of object instances.  Each
+     instance has the same collection of  named  attributes,
+     and each attribute is of a specific type.  Furthermore,
+     each instance has a permanent <FirstTerm>object  identifier</FirstTerm> (<Acronym>OID</Acronym>)
+     that  is  unique  throughout the installation.  Because
+     <Acronym>SQL</Acronym> syntax refers to tables,  we  will use  the  terms
+     <FirstTerm>table</FirstTerm> and <FirstTerm>class</FirstTerm> interchangeably.
+  Likewise, an <Acronym>SQL</Acronym> <FirstTerm>row</FirstTerm> is an
+     <FirstTerm>instance</FirstTerm> and <Acronym>SQL</Acronym> <FirstTerm>columns</FirstTerm>
+ are <FirstTerm>attributes</FirstTerm>.
+     As  previously  discussed,  classes  are  grouped  into
+     databases,  and  a collection of databases managed by a
+     single <FileName>postmaster</FileName> process constitutes  an  installation
+     or site.
+</Para>
+
+<Sect1>
+<Title>Creating a New Class</Title>
+
+<Para>
+     You  can  create  a  new  class by specifying the class
+     name, along with all attribute names and their types:
+
+<ProgramListing>
+CREATE TABLE weather (
+    city            varchar(80),
+    temp_lo         int,           -- low temperature
+    temp_hi         int,           -- high temperature
+    prcp            real,          -- precipitation
+    date            date
+);
+</ProgramListing>
+
+<Para>
+     Note that keywords are case-insensitive and identifiers
+     are usually case-insensitive.
+<Acronym>Postgres</Acronym> allows <Acronym>SQL92</Acronym> <FirstTerm>delimited identifiers</FirstTerm>
+(identifiers surrounded by double-quotes) to include mixed-case and spaces, tabs, etc.
+
+<Para>
+  <ProductName>Postgres</ProductName>  <Acronym>SQL</Acronym> supports the usual
+     <Acronym>SQL</Acronym> types <Type>int</Type>,
+ <Type>float</Type>,  <Type>real</Type>,  <Type>smallint</Type>,  <Type>char(N)</Type>,  
+     <Type>varchar(N)</Type>,  <Type>date</Type>, <Type>time</Type>,
+and <Type>timestamp</Type>, as well as other types of general utility and
+a rich set of geometric types.  As we will 
+     see later, <ProductName>Postgres</ProductName> can be customized  with  an  
+     arbitrary  number  of
+     user-defined  data types.  Consequently, type names are
+     not syntactical keywords, except where required to support special cases in the <Acronym>SQL92</Acronym> standard.
+     So far, the <ProductName>Postgres</ProductName> create command looks exactly  like
+     the  command  used  to  create a table in a traditional
+     relational system.  However, we will presently see that
+     classes  have  properties  that  are  extensions of the
+     relational model.
+</Para>
+
+<Sect1>
+<Title>Populating a Class with Instances</Title>
+
+<Para>
+     The <Command>insert</Command> statement is used to populate a  class  with
+     instances:
+
+<ProgramListing>
+INSERT INTO weather
+    VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')
+</ProgramListing>
+
+<Para>
+     You can also use the <Command>copy</Command> command to perform load large
+     amounts of data from flat (<Acronym>ASCII</Acronym>) files.
+</Para>
+
+<Sect1>
+<Title>Querying a Class</Title>
+
+<Para>
+     The weather class can be queried with normal relational
+     selection  and projection queries.  A <Acronym>SQL</Acronym> <Command>select</Command> 
+     statement is used to do this.  The statement is divided into
+     a target list (the part that lists the attributes to be
+     returned) and a qualification (the part that  specifies
+     any  restrictions).   For  example, to retrieve all the
+     rows of weather, type:
+<ProgramListing>
+SELECT * FROM WEATHER;
+</ProgramListing>
+
+     and the output should be:
+<ProgramListing>
++--------------+---------+---------+------+------------+
+|city          | temp_lo | temp_hi | prcp | date       |
++--------------+---------+---------+------+------------+
+|San Francisco | 46      | 50      | 0.25 | 11-27-1994 |
++--------------+---------+---------+------+------------+
+|San Francisco | 43      | 57      | 0    | 11-29-1994 |
++--------------+---------+---------+------+------------+
+|Hayward       | 37      | 54      |      | 11-29-1994 |
++--------------+---------+---------+------+------------+
+</ProgramListing>
+     You may specify any arbitrary expressions in the  target list. For example, you can do:
+<ProgramListing>
+SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
+</ProgramListing>
+
+<Para>
+     Arbitrary  Boolean  operators
+ (<Command>and</Command>,  <Command>or</Command> and <Command>not</Command>) are
+     allowed in the qualification of any query.   For  example,
+
+<ProgramListing>
+SELECT * FROM weather
+    WHERE city = 'San Francisco'
+    AND prcp > 0.0;
+
++--------------+---------+---------+------+------------+
+|city          | temp_lo | temp_hi | prcp | date       |
++--------------+---------+---------+------+------------+
+|San Francisco | 46      | 50      | 0.25 | 11-27-1994 |
++--------------+---------+---------+------+------------+
+</ProgramListing>
+</Para>
+
+<Para>
+     As  a final note, you can specify that the results of a
+     select can be returned in a <FirstTerm>sorted order</FirstTerm>
+ or with <FirstTerm>duplicate instances</FirstTerm> removed.
+
+<ProgramListing>
+SELECT DISTINCT city
+    FROM weather
+    ORDER BY city;
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Redirecting SELECT Queries</Title>
+
+<Para>
+     Any select query can be redirected to a new class
+<ProgramListing>
+SELECT * INTO TABLE temp FROM weather;
+</ProgramListing>
+
+<Para>
+     This forms an implicit <Command>create</Command> command, creating a new
+     class temp with the attribute names and types specified
+     in  the target list of the <Command>select into</Command> command.  We can
+     then, of course, perform any operations on the  resulting 
+     class that we can perform on other classes.
+</Para>
+
+<Sect1>
+<Title>Joins Between Classes</Title>
+
+<Para>
+     Thus far, our queries have only accessed one class at a
+     time.  Queries can access multiple classes at once,  or
+     access  the  same  class  in  such  a way that multiple
+     instances of the class are being processed at the  same
+     time.   A query that accesses multiple instances of the
+     same or different classes at one time is called a  join
+     query.
+     As an example, say we wish to find all the records that
+     are in the  temperature  range  of  other  records.  In
+     effect,  we  need  to  compare  the temp_lo and temp_hi
+     attributes of each EMP  instance  to  the  temp_lo  and
+     temp_hi  attributes of all other EMP instances.
+<Note>
+<Para>
+This  is only a conceptual model.  The actual join may
+   be performed in a more efficient manner, but this is invisible to the user.
+</Para>
+</Note>
+
+ We can do this with the following query:
+
+<ProgramListing>
+SELECT W1.city, W1.temp_lo, W1.temp_hi,
+    W2.city, W2.temp_lo, W2.temp_hi
+    FROM weather W1, weather W2
+    WHERE W1.temp_lo < W2.temp_lo
+    AND W1.temp_hi > W2.temp_hi;
+
++--------------+---------+---------+---------------+---------+---------+
+|city          | temp_lo | temp_hi | city          | temp_lo | temp_hi |
++--------------+---------+---------+---------------+---------+---------+
+|San Francisco | 43      | 57      | San Francisco | 46      | 50      |
++--------------+---------+---------+---------------+---------+---------+
+|San Francisco | 37      | 54      | San Francisco | 46      | 50      |
++--------------+---------+---------+---------------+---------+---------+
+</ProgramListing>     
+
+<Note>
+<Para>
+The semantics of such a join are 
+   that the qualification
+   is a truth expression defined for the Cartesian  product  of
+   the  classes indicated in the query.  For those instances in
+   the Cartesian product for which the qualification  is  true,
+   <ProductName>Postgres</ProductName>  computes  and  returns the values specified in the
+   target list.  <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> does not assign  any  meaning  to
+   duplicate values in such expressions.  This means that <ProductName>Postgres</ProductName> 
+   sometimes recomputes the same target list several times;
+   this frequently happens when Boolean expressions are connected 
+   with an "or".  To remove such duplicates, you must  use
+   the <Command>select distinct</Command> statement.
+</Para>
+</Note>
+
+<Para>
+     In this case, both W1 and  W2  are  surrogates for  an
+     instance  of the class weather, and both range over all
+     instances of the class.  (In the  terminology  of  most
+     database  systems,  W1 and W2 are known as <FirstTerm>range variables</FirstTerm>.)  
+     A query can contain an  arbitrary  number  of
+     class names and surrogates.
+</Para>
+
+<Sect1>
+<Title>Updates</Title>
+
+<Para>
+     You can update existing instances using the update command. 
+     Suppose you discover the temperature readings are
+     all  off  by 2 degrees as of Nov 28, you may update the
+     data as follow:
+
+<ProgramListing>
+UPDATE weather
+    SET temp_hi = temp_hi - 2,  temp_lo = temp_lo - 2
+    WHERE date > '11/28/1994';
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Deletions</Title>
+
+<Para>
+     Deletions are performed using the <Command>delete</Command> command:
+<ProgramListing>
+DELETE FROM weather WHERE city = 'Hayward';
+</ProgramListing>
+
+     All weather recording belongs to Hayward is removed.
+     One should be wary of queries of the form
+<ProgramListing>
+DELETE FROM classname;
+</ProgramListing>
+
+     Without a qualification, <Command>delete</Command> will simply
+     remove  all  instances  of  the given class, leaving it
+     empty.  The system will not request confirmation before
+     doing this.
+</Para>
+
+<Sect1>
+<Title>Using Aggregate Functions</Title>
+
+<Para>
+     Like  most  other  query  languages,  <ProductName>PostgreSQL</ProductName> supports
+     aggregate functions.
+The current  implementation  of  <ProductName>Postgres</ProductName> aggregate functions have some limitations.
+     Specifically, while there  are  aggregates  to  compute
+     such  functions as the <Function>count</Function>, <Function>sum</Function>,
+ <Function>avg</Function> (average), <Function>max</Function> (maximum) and
+     <Function>min</Function> (minimum) over a set of instances,  aggregates  can  only
+     appear  in  the  target  list of a query and not directly in the
+     qualification (the <FirstTerm>where</FirstTerm> clause). As an example,
+
+<ProgramListing>
+SELECT max(temp_lo) FROM weather;
+</ProgramListing>
+
+is allowed, while
+
+<ProgramListing>
+SELECT city FROM weather WHERE temp_lo = max(temp_lo);
+</ProgramListing>
+
+is not. However, as is often the case the query can be restated to accomplish
+the intended result; here by using a <FirstTerm>subselect</FirstTerm>:
+<ProgramListing>
+SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
+</ProgramListing>
+</Para>
+
+<Para>
+     Aggregates may also have <FirstTerm>group by</FirstTerm> clauses:
+<ProgramListing>
+SELECT city, max(temp_lo)
+    FROM weather
+    GROUP BY city;
+</ProgramListing>
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..df119fd365ad7ab1dfcb0abf35e8d0b5f5225c83
--- /dev/null
+++ b/doc/src/sgml/query.sgml
@@ -0,0 +1,362 @@
+<Chapter ID="QUERY">
+<TITLE>The Query Language</TITLE>
+
+<Para>
+     The  <ProductName>Postgres</ProductName>  query language is a variant of
+the <Acronym>SQL3</Acronym> draft next-generation standard. It
+     has many extensions such as an extensible type  system,
+     inheritance,  functions and production rules. These are
+     features carried over from the original <ProductName>Postgres</ProductName>  query
+     language,  <ProductName>PostQuel</ProductName>.  This section provides an overview
+     of how to use <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym>  to  perform  simple  operations.
+     This manual is only intended to give you an idea of our
+     flavor of <Acronym>SQL</Acronym> and is in no way a complete  tutorial  on
+     <Acronym>SQL</Acronym>.  Numerous  books  have  been  written  on <Acronym>SQL</Acronym>, including
+<!--
+<XRef LinkEnd="MELT93"> and <XRef LinkEnd="DATE97">.
+-->
+[MELT93] and [DATE97].
+     You should be  aware  that  some language features 
+are not part of the <Acronym>ANSI</Acronym> standard.
+</Para>
+
+<Sect1>
+<Title>Interactive Monitor</Title>
+
+<Para>
+     In the examples that follow, we assume  that  you  have
+     created  the mydb database as described in the previous
+     subsection and have started <Application>psql</Application>.
+     Examples  in  this  manual  can  also   be   found   in
+     <FileName>/usr/local/pgsql/src/tutorial/</FileName>.    Refer   to   the
+     <FileName>README</FileName> file in that directory for how to use them.   To
+     start the tutorial, do the following:
+
+<ProgramListing>
+% cd /usr/local/pgsql/src/tutorial
+% psql -s mydb
+Welcome to the POSTGRESQL interactive sql monitor:
+  Please read the file COPYRIGHT for copyright terms of POSTGRESQL
+
+   type \? for help on slash commands
+   type \q to quit
+   type \g or terminate with semicolon to execute query
+ You are currently connected to the database: postgres
+
+mydb=> \i basics.sql
+</ProgramListing>
+</Para>
+
+<Para>
+     The  <Literal>\i</Literal>  command  read  in  queries  from the specified
+     files. The <Literal>-s</Literal> option puts you in single step mode which
+     pauses  before  sending a query to the backend. Queries
+     in this section are in the file <FileName>basics.sql</FileName>.
+</Para>
+
+<Para>
+<Application>psql</Application>
+has a variety of <Literal>\d</Literal> commands for showing system information.
+Consult these commands for more details;
+for a listing, type <Literal>\?</Literal> at the <Application>psql</Application> prompt.
+</Para>
+
+<Sect1>
+<Title>Concepts</Title>
+
+<Para>
+     The fundamental notion in <ProductName>Postgres</ProductName> is that of a  class,
+     which  is a named collection of object instances.  Each
+     instance has the same collection of  named  attributes,
+     and each attribute is of a specific type.  Furthermore,
+     each instance has a permanent <FirstTerm>object  identifier</FirstTerm> (<Acronym>OID</Acronym>)
+     that  is  unique  throughout the installation.  Because
+     <Acronym>SQL</Acronym> syntax refers to tables,  we  will use  the  terms
+     <FirstTerm>table</FirstTerm> and <FirstTerm>class</FirstTerm> interchangeably.
+  Likewise, an <Acronym>SQL</Acronym> <FirstTerm>row</FirstTerm> is an
+     <FirstTerm>instance</FirstTerm> and <Acronym>SQL</Acronym> <FirstTerm>columns</FirstTerm>
+ are <FirstTerm>attributes</FirstTerm>.
+     As  previously  discussed,  classes  are  grouped  into
+     databases,  and  a collection of databases managed by a
+     single <Application>postmaster</Application> process constitutes  an  installation
+     or site.
+</Para>
+
+<Sect1>
+<Title>Creating a New Class</Title>
+
+<Para>
+     You  can  create  a  new  class by specifying the class
+     name, along with all attribute names and their types:
+
+<ProgramListing>
+CREATE TABLE weather (
+    city            varchar(80),
+    temp_lo         int,           -- low temperature
+    temp_hi         int,           -- high temperature
+    prcp            real,          -- precipitation
+    date            date
+);
+</ProgramListing>
+
+<Para>
+     Note that both keywords and identifiers are case-insensitive; identifiers can become
+case-sensitive by surrounding them with double-quotes as allowed by <Acronym>SQL92</Acronym>.
+     <ProductName>Postgres</ProductName>  <Acronym>SQL</Acronym> supports the usual
+     <Acronym>SQL</Acronym> types <Type>int</Type>,
+ <Type>float</Type>,  <Type>real</Type>,  <Type>smallint</Type>,  <Type>char(N)</Type>,  
+     <Type>varchar(N)</Type>,  <Type>date</Type>, <Type>time</Type>,
+and <Type>timestamp</Type>, as well as other types of general utility and
+a rich set of geometric types.  As we will 
+     see later, <ProductName>Postgres</ProductName> can be customized  with  an  
+     arbitrary  number  of
+     user-defined  data types.  Consequently, type names are
+     not syntactical keywords, except where required to support special cases in the <Acronym>SQL92</Acronym> standard.
+     So far, the <ProductName>Postgres</ProductName> create command looks exactly  like
+     the  command  used  to  create a table in a traditional
+     relational system.  However, we will presently see that
+     classes  have  properties  that  are  extensions of the
+     relational model.
+</Para>
+
+<Sect1>
+<Title>Populating a Class with Instances</Title>
+
+<Para>
+     The <Command>insert</Command> statement is used to populate a  class  with
+     instances:
+
+<ProgramListing>
+INSERT INTO weather
+    VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')
+</ProgramListing>
+
+<Para>
+     You can also use the <Command>copy</Command> command to perform load large
+     amounts of data from flat (<Acronym>ASCII</Acronym>) files.
+</Para>
+
+<Sect1>
+<Title>Querying a Class</Title>
+
+<Para>
+     The weather class can be queried with normal relational
+     selection  and projection queries.  A <Acronym>SQL</Acronym> <Command>select</Command> 
+     statement is used to do this.  The statement is divided into
+     a target list (the part that lists the attributes to be
+     returned) and a qualification (the part that  specifies
+     any  restrictions).   For  example, to retrieve all the
+     rows of weather, type:
+<ProgramListing>
+SELECT * FROM WEATHER;
+</ProgramListing>
+
+     and the output should be:
+<ProgramListing>
++--------------+---------+---------+------+------------+
+|city          | temp_lo | temp_hi | prcp | date       |
++--------------+---------+---------+------+------------+
+|San Francisco | 46      | 50      | 0.25 | 11-27-1994 |
++--------------+---------+---------+------+------------+
+|San Francisco | 43      | 57      | 0    | 11-29-1994 |
++--------------+---------+---------+------+------------+
+|Hayward       | 37      | 54      |      | 11-29-1994 |
++--------------+---------+---------+------+------------+
+</ProgramListing>
+     You may specify any arbitrary expressions in the  target list. For example, you can do:
+<ProgramListing>
+SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
+</ProgramListing>
+
+<Para>
+     Arbitrary  Boolean  operators
+ (<Command>and</Command>,  <Command>or</Command> and <Command>not</Command>) are
+     allowed in the qualification of any query.   For  example,
+
+<ProgramListing>
+SELECT * FROM weather
+    WHERE city = 'San Francisco'
+    AND prcp > 0.0;
+
++--------------+---------+---------+------+------------+
+|city          | temp_lo | temp_hi | prcp | date       |
++--------------+---------+---------+------+------------+
+|San Francisco | 46      | 50      | 0.25 | 11-27-1994 |
++--------------+---------+---------+------+------------+
+</ProgramListing>
+</Para>
+
+<Para>
+     As  a final note, you can specify that the results of a
+     select can be returned in a <FirstTerm>sorted order</FirstTerm>
+ or with <FirstTerm>duplicate instances</FirstTerm> removed.
+
+<ProgramListing>
+SELECT DISTINCT city
+    FROM weather
+    ORDER BY city;
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Redirecting SELECT Queries</Title>
+
+<Para>
+     Any select query can be redirected to a new class
+<ProgramListing>
+SELECT * INTO TABLE temp FROM weather;
+</ProgramListing>
+
+<Para>
+     This forms an implicit <Command>create</Command> command, creating a new
+     class temp with the attribute names and types specified
+     in  the target list of the <Command>select into</Command> command.  We can
+     then, of course, perform any operations on the  resulting 
+     class that we can perform on other classes.
+</Para>
+
+<Sect1>
+<Title>Joins Between Classes</Title>
+
+<Para>
+     Thus far, our queries have only accessed one class at a
+     time.  Queries can access multiple classes at once,  or
+     access  the  same  class  in  such  a way that multiple
+     instances of the class are being processed at the  same
+     time.   A query that accesses multiple instances of the
+     same or different classes at one time is called a  join
+     query.
+     As an example, say we wish to find all the records that
+     are in the  temperature  range  of  other  records.  In
+     effect,  we  need  to  compare  the temp_lo and temp_hi
+     attributes of each EMP  instance  to  the  temp_lo  and
+     temp_hi  attributes of all other EMP instances.
+<Note>
+<Para>
+This  is only a conceptual model.  The actual join may
+   be performed in a more efficient manner, but this is invisible to the user.
+</Para>
+</Note>
+
+ We can do this with the following query:
+
+<ProgramListing>
+SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
+    W2.city, W2.temp_lo AS low, W2.temp_hi AS high
+    FROM weather W1, weather W2
+    WHERE W1.temp_lo < W2.temp_lo
+    AND W1.temp_hi > W2.temp_hi;
+
++--------------+-----+------+---------------+-----+------+
+|city          | low | high | city          | low | high |
++--------------+-----+------+---------------+-----+------+
+|San Francisco | 43  | 57   | San Francisco | 46  | 50   |
++--------------+-----+------+---------------+-----+------+
+|San Francisco | 37  | 54   | San Francisco | 46  | 50   |
++--------------+-----+------+---------------+-----+------+
+</ProgramListing>     
+
+<Note>
+<Para>
+The semantics of such a join are 
+   that the qualification
+   is a truth expression defined for the Cartesian  product  of
+   the  classes indicated in the query.  For those instances in
+   the Cartesian product for which the qualification  is  true,
+   <ProductName>Postgres</ProductName>  computes  and  returns the values specified in the
+   target list.  <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> does not assign  any  meaning  to
+   duplicate values in such expressions.  This means that <ProductName>Postgres</ProductName> 
+   sometimes recomputes the same target list several times;
+   this frequently happens when Boolean expressions are connected 
+   with an "or".  To remove such duplicates, you must  use
+   the <Command>select distinct</Command> statement.
+</Para>
+</Note>
+
+<Para>
+     In this case, both W1 and  W2  are  surrogates for  an
+     instance  of the class weather, and both range over all
+     instances of the class.  (In the  terminology  of  most
+     database  systems,  W1 and W2 are known as <FirstTerm>range variables</FirstTerm>.)  
+     A query can contain an  arbitrary  number  of
+     class names and surrogates.
+</Para>
+
+<Sect1>
+<Title>Updates</Title>
+
+<Para>
+     You can update existing instances using the update command. 
+     Suppose you discover the temperature readings are
+     all  off  by 2 degrees as of Nov 28, you may update the
+     data as follow:
+
+<ProgramListing>
+UPDATE weather
+    SET temp_hi = temp_hi - 2,  temp_lo = temp_lo - 2
+    WHERE date > '11/28/1994';
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Deletions</Title>
+
+<Para>
+     Deletions are performed using the <Command>delete</Command> command:
+<ProgramListing>
+DELETE FROM weather WHERE city = 'Hayward';
+</ProgramListing>
+
+     All weather recording belongs to Hayward is removed.
+     One should be wary of queries of the form
+<ProgramListing>
+DELETE FROM classname;
+</ProgramListing>
+
+     Without a qualification, <Command>delete</Command> will simply
+     remove  all  instances  of  the given class, leaving it
+     empty.  The system will not request confirmation before
+     doing this.
+</Para>
+
+<Sect1>
+<Title>Using Aggregate Functions</Title>
+
+<Para>
+     Like  most  other  query  languages,  <ProductName>PostgreSQL</ProductName> supports
+     aggregate functions.
+The current  implementation  of  <ProductName>Postgres</ProductName> aggregate functions have some limitations.
+     Specifically, while there  are  aggregates  to  compute
+     such  functions as the <Function>count</Function>, <Function>sum</Function>,
+ <Function>avg</Function> (average), <Function>max</Function> (maximum) and
+     <Function>min</Function> (minimum) over a set of instances,  aggregates  can  only
+     appear  in  the  target  list of a query and not directly in the
+     qualification (the where clause). As an example,
+
+<ProgramListing>
+SELECT max(temp_lo) FROM weather;
+</ProgramListing>
+
+is allowed, while
+
+<ProgramListing>
+SELECT city FROM weather WHERE temp_lo = max(temp_lo);
+</ProgramListing>
+
+is not. However, as is often the case the query can be restated to accomplish 
+the intended result; here by using a <FirstTerm>subselect</FirstTerm>:
+<ProgramListing>
+SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
+</ProgramListing>
+</Para>
+
+<Para>
+     Aggregates may also have <FirstTerm>group by</FirstTerm> clauses:
+<ProgramListing>
+SELECT city, max(temp_lo)
+    FROM weather
+    GROUP BY city;
+</ProgramListing>
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/recovery.sgml b/doc/src/sgml/recovery.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..2eec4e885e420df7cb637fc6528de0401c36fe02
--- /dev/null
+++ b/doc/src/sgml/recovery.sgml
@@ -0,0 +1,8 @@
+<Chapter>
+<Title>Database Recovery</Title>
+
+<Para>
+This section needs to be written. Volunteers?
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..f5a8d8a3d5f95becf0b1f562a85f0ae0a8f079e0
--- /dev/null
+++ b/doc/src/sgml/regress.sgml
@@ -0,0 +1,448 @@
+<Chapter>
+<Title>Regression Test</Title>
+
+<Abstract>
+<Para>
+Regression test instructions and analysis.
+</Para>
+</Abstract>
+
+<Para>
+  The PostgreSQL regression tests are a comprehensive set of tests for the
+  SQL implementation embedded in PostgreSQL developed by Jolly Chen and
+  Andrew Yu. It tests standard SQL operations as well as the extended
+  capabilities of PostgreSQL.
+</Para>
+
+<Para>
+  These tests have recently been revised by Marc Fournier and Thomas Lockhart
+and are now packaged as
+  functional units which should make them easier to run and easier to interpret.
+From <ProductName>PostgreSQL</ProductName> v6.1 onward
+ the regression tests are current for every official release. 
+</Para>
+
+<Para>
+  Some properly installed and fully functional PostgreSQL installations
+  can fail some of these regression tests due to artifacts of floating point
+  representation and time zone support. The current tests are evaluated
+  using a simple "diff" algorithm, and are sensitive to small system
+  differences. For apparently failed tests, examining the differences
+  may reveal that the differences are not significant.
+</Para>
+
+<Para>
+The regression testing notes below assume the following (except where noted):
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+Commands are Unix-compatible. See note below.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+Defaults are used except where noted.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+User postgres is the <ProductName>Postgres</ProductName> superuser.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The source path is /usr/src/pgsql (other paths are possible).
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+The runtime path is /usr/local/pgsql (other paths are possible).
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+<Sect1>
+<Title>Regression Environment</Title>
+
+<Para>
+  The regression test is invoked by the <Command>make</Command> command which compiles
+  a <Acronym>C</Acronym> program into a shared library
+  in the current directory.  Localized shell scripts are also created in
+  the current directory. The output file templates are massaged into the
+  <FileName>./expected/*.out</FileName> files.  The localization replaces macros in the source
+  files with absolute pathnames and user names.
+</Para>
+
+<Para>
+  Normally, the regression test should be run as the pg_superuser since
+  the 'src/test/regress' directory and sub-directories are owned by the
+  pg_superuser. If you run the regression test as another user the
+  'src/test/regress' directory tree should be writeable to that user.
+</Para>
+
+<Para>
+  The postmaster should be invoked with the system time zone set for
+  Berkeley, California. This is done automatically by the regression
+test script. However, it does require machine support for the PST8PDT
+time zone.
+</Para>
+
+<Para>
+To verify that your machine does have this support, type
+the following:
+<ProgramListing>
+    setenv TZ PST8PDT
+    date
+</ProgramListing>
+</Para>
+
+<Para>
+  The "date" command above should have returned the current system time
+  in the PST8PDT time zone. If the PST8PDT database is not available, then
+  your system may have returned the time in GMT. If the PST8PDT time zone
+  is not available, you can set the time zone rules explicitly:
+<ProgramListing>
+    setenv PGTZ PST8PDT7,M04.01.0,M10.05.03
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Directory Layout</Title>
+
+<Para>
+<Note>
+<Para>
+This should become a table in the previous section.
+</Para>
+</Note>
+</Para>
+
+<Para>
+<ProgramListing>
+  input/ .... .source files that are converted using 'make all' into
+              some of the .sql files in the 'sql' subdirectory
+
+  output/ ... .source files that are converted using 'make all' into
+              .out files in the 'expected' subdirectory
+
+  sql/ ...... .sql files used to perform the regression tests
+
+  expected/ . .out files that represent what we *expect* the results to
+              look like
+
+  results/ .. .out files that represent what the results *actually* look
+              like. Also used as temporary storage for table copy testing.
+</ProgramListing>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Regression Test Procedure</Title>
+
+<Para>
+Commands were tested on RedHat Linux version 4.2 using the bash shell.
+Except where noted, they will probably work on most systems. Commands
+like <FileName>ps</FileName> and <FileName>tar</FileName> vary wildly on what options you should use on each
+platform. <Emphasis>Use common sense</Emphasis> before typing in these commands.
+</Para>
+
+<Para>
+<Procedure>
+<Title><ProductName>Postgres</ProductName> Regression Configuration</Title>
+
+<Para>
+For a fresh install or upgrading from previous releases of
+<ProductName>Postgres</ProductName>:
+</Para>
+
+<Step Performance="required">
+<Para>
+Build the regression test. Type
+<ProgramListing>
+    cd /usr/src/pgsql/src/test/regress
+    gmake all
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="optional">
+<Para>
+  If you have prevously invoked the regression test, clean up the
+  working directory with:
+
+<ProgramListing>
+    cd /usr/src/pgsql/src/test/regress
+    make clean
+</ProgramListing>
+
+<Step Performance="required">
+<Para>
+     The file /usr/src/pgsql/src/test/regress/README has detailed
+     instructions for running and interpreting the regression tests.
+     A short version follows here:
+</Para>
+
+<Para>
+If the postmaster is not already running, start the postmaster on an
+available window by typing
+<ProgramListing>
+    postmaster
+</ProgramListing>
+
+or start the postmaster daemon running in the background by typing
+<ProgramListing>
+    cd
+    nohup postmaster > regress.log 2>&1 &
+</ProgramListing>
+</Para>
+
+<Para>
+     Run postmaster from your <ProductName>Postgres</ProductName> super user account (typically
+     account postgres).
+
+<Note>
+<Para>
+Do not run <FileName>postmaster</FileName> from the root account.
+</Para>
+</Note>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+ Run the regression tests.  Type
+
+<ProgramListing>
+    cd /usr/src/pgsql/src/test/regress
+    gmake runtest
+</ProgramListing>
+</Para>
+
+<Para>
+
+     You do not need to type "gmake clean" if this is the first time you
+     are running the tests.
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+
+     You should get on the screen (and also written to file ./regress.out)
+     a series of statements stating which tests passed and which tests
+     failed.  Please note that it can be normal for some of the tests to
+     "fail".  For the failed tests, use diff to compare the files in
+     directories ./results and ./expected.  If float8 failed, type
+     something like:
+<ProgramListing>
+    cd /usr/src/pgsql/src/test/regress
+    diff -w expected/float8.out results
+</ProgramListing>
+</Para>
+</Step>
+
+<Step Performance="required">
+<Para>
+     After running the tests, type
+<ProgramListing>
+    destroydb regression
+    cd /usr/src/pgsql/src/test/regress
+    gmake clean
+</ProgramListing>
+</Para>
+</Step>
+
+</Procedure>
+
+</Sect1>
+
+<Sect1>
+<Title>Regression Analysis</Title>
+
+<Para>
+    <Quote>Failed</Quote> tests may have failed due to slightly different error messages,
+     math libraries, or output formatting.
+     "Failures" of this type do not indicate a problem with
+     <ProductName>Postgres</ProductName>.
+</Para>
+
+<Para>
+     For a i686/Linux-ELF platform, no tests failed since this is the
+     v6.2.1 regression testing reference platform.
+</Para>
+
+<Para>
+     For the SPARC/Linux-ELF platform, using the 970525 beta version of
+     <ProductName>Postgres</ProductName> v6.2 the following tests "failed":
+     float8 and geometry "failed" due to minor precision differences in
+     floating point numbers.  select_views produces massively different output,
+     but the differences are due to minor floating point differences.
+</Para>
+
+<Para>
+     Conclusion?  If you do see failures, try to understand the nature of
+     the differences and then decide if those differences will affect your
+     intended use of <ProductName>Postgres</ProductName>.  However, keep in mind that this is likely
+     to be the most solid release of <ProductName>Postgres</ProductName> to date, incorporating many
+     bug fixes from v6.1, and that previous versions of <ProductName>Postgres</ProductName> have been
+     in use successfully for some time now.
+</Para>
+
+<Sect2>
+<Title>Comparing expected/actual output</Title>
+
+<Para>
+  The results are in files in the ./results directory. These results
+  can be compared with results in the ./expected directory using 'diff'.
+  The files might not compare exactly. The following paragraphs attempt
+  to explain the differences.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Error message differences</Title>
+
+<Para>
+  Some of the regression tests involve intentional invalid input values.
+  Error messages can come from either the Postgres code or from the host
+  platform system routines. In the latter case, the messages may vary
+  between platforms, but should reflect similar information. These
+  differences in messages will result in a "failed" regression test which
+  can be validated by inspection.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>OID differences</Title>
+
+<Para>
+  There are several places where PostgreSQL OID (object identifiers) appear
+  in 'regress.out'. OID's are unique 32-bit integers which are generated
+  by the PostgreSQL backend whenever a table row is inserted or updated.
+  If you run the regression test on a non-virgin database or run it multiple
+  times, the OID's reported will have different values. 
+
+  The following SQL statements in 'misc.out' have shown this behavior:
+
+  QUERY: SELECT user_relns() AS user_relns ORDER BY user_relns;
+
+    The 'a,523676' row is composed from an OID.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Date and time differences</Title>
+
+<Para>
+  On many supported platforms, you can force PostgreSQL to believe that it
+  is running in the same time zone as Berkeley, California. See details in
+  the section on how to run the regression tests.
+
+  If you do not explicitly set your time zone environment to PST8PDT, then
+  most of the date and time results will reflect your local time zone and
+  will fail the regression testing.
+
+  There appears to be some systems which do not accept the recommended syntax
+  for explicitly setting the local time zone rules. Some systems using the
+  public domain time zone package exhibit minor problems with pre-1970 PDT
+  times, representing them in PST instead.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Floating point differences</Title>
+
+<Para>
+  Some of the tests involve computing 64-bit (<Type>float8</Type>) number from table
+  columns. Differences in results involving mathematical functions of
+  <Type>float8</Type> columns have been observed. These differences occur where
+  different operating systems are used on the same platform ie:
+  BSDI and SOLARIS on Intel/86, and where the same operating system is
+  used used on different platforms, ie: SOLARIS on SPARC and Intel/86.
+
+  Human eyeball comparison is needed to determine the real significance
+  of these differences which are usually 10 places to the right of
+  the decimal point.
+
+  Some systems signal errors from pow() and exp() differently from
+  the mechanism expected by the current Postgres code.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Polygon differences</Title>
+
+<Para>
+  Several of the tests involve operations on geographic date about the
+  Oakland/Berkley CA street map. The map data is expressed as polygons
+  whose vertices are represented as pairs of <Type>float8</Type> numbers (decimal
+  latitude and longitude). Initially, some tables are created and
+  loaded with geographic data, then some views are created which join
+  two tables using the polygon intersection operator (##), then a select
+  is done on the view. 
+
+  When comparing the results from different platforms, differences occur
+  in the 2nd or 3rd place to the right of the decimal point. The SQL
+  statements where these problems occur are the folowing:
+
+<ProgramListing>
+    QUERY: SELECT * from street;
+    QUERY: SELECT * from iexit;
+</ProgramListing>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Random differences</Title>
+
+<Para>
+  There is at least one test case in random.out which is intended to produce
+  random results. This causes random to fail the regression testing.
+  Typing
+<ProgramListing>
+    diff results/random.out expected/random.out
+</ProgramListing>
+
+ should produce only
+  one or a few lines of differences for this reason, but other floating
+  point differences on dissimilar architectures might cause many more
+  differences. See the release notes below.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>The <Quote>expected</Quote> files</Title>
+
+<Para>
+  The <FileName>./expected/*.out</FileName> files were adapted from the original monolithic
+  <FileName>expected.input</FileName> file provided by Jolly Chen et al. Newer versions of these
+  files generated on various development machines have been substituted after
+  careful (?) inspection. Many of the development machines are running a
+  Unix OS variant (FreeBSD, Linux, etc) on Ix86 hardware.
+
+  The original <FileName>expected.input</FileName> file was created on a SPARC Solaris 2.4
+  system using the <FileName>postgres5-1.02a5.tar.gz</FileName> source tree. It was compared
+  with a file created on an I386 Solaris 2.4 system and the differences
+  were only in the floating point polygons in the 3rd digit to the right
+  of the decimal point. (see below)
+
+  The original <FileName>sample.regress.out</FileName> file was from the postgres-1.01 release
+  constructed by Jolly Chen and is included here for reference. It may
+  have been created on a DEC ALPHA machine as the <FileName>Makefile.global</FileName>
+  in the postgres-1.01 release has PORTNAME=alpha.
+</Para>
+
+</Sect2>
+
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..93048018a056c909d4e48df309876403f04a2659
--- /dev/null
+++ b/doc/src/sgml/release.sgml
@@ -0,0 +1,144 @@
+<Chapter>
+<Title>Release Notes</Title>
+
+<Para>
+<Note>
+<Para>
+Should include the migration notes from <FileName>migration/</FileName>.
+</Para>
+</Note>
+</Para>
+
+<Para>
+The release notes have not yet been integrated into the new documentation.
+Check for plain text files in the top of the distribution directory tree
+and in the <FileName>migration/</FileName> directory for current information.
+
+<Sect1>
+<Title>Release 6.3</Title>
+
+<Para>
+TBD
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Release 6.2.1</Title>
+
+<Para>
+<Note>
+<Para>
+v6.2.1 was a bug-fix and usability release on v6.2. Needs only a few notes.
+</Para>
+</Note>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Release 6.2</Title>
+
+<Para>
+<Note>
+<Para>
+This should include information based on Bruce's release summary.
+</Para>
+</Note>
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Release 6.1</Title>
+
+<Para>
+<Note>
+<Para>
+This should include information based on Bruce's release summary.
+</Para>
+</Note>
+</Para>
+
+<Para>
+  The regression tests have been adapted and extensively modified for the
+  v6.1 release of PostgreSQL.
+</Para>
+
+<Para>
+  Three new data types (datetime, timespan, and circle) have been added to
+  the native set of PostgreSQL types. Points, boxes, paths, and polygons
+  have had their output formats made consistant across the data types.
+  The polygon output in misc.out has only been spot-checked for correctness
+  relative to the original regression output.
+</Para>
+
+<Para>
+  PostgreSQL v6.1 introduces a new, alternate optimizer which uses <FirstTerm>genetic</FirstTerm>
+  algorithms. These algorithms introduce a random behavior in the ordering
+  of query results when the query contains multiple qualifiers or multiple
+  tables (giving the optimizer a choice on order of evaluation). Several
+  regression tests have been modified to explicitly order the results, and
+  hence are insensitive to optimizer choices. A few regression tests are
+  for data types which are inherently unordered (e.g. points and time
+  intervals) and tests involving those types are explicitly bracketed with
+  <Command>set geqo to 'off'</Command> and <Command>reset geqo</Command>.
+</Para>
+
+<Para>
+  The interpretation of array specifiers (the curly braces around atomic
+  values) appears to have changed sometime after the original regression
+  tests were generated. The current <FileName>./expected/*.out</FileName> files reflect this
+  new interpretation, which may not be correct!
+</Para>
+
+<Para>
+  The float8 regression test fails on at least some platforms. This is due
+  to differences in implementations of pow() and exp() and the signaling
+  mechanisms used for overflow and underflow conditions.
+</Para>
+
+<Para>
+  The "random" results in the random test should cause the "random" test
+  to be "failed", since the regression tests are evaluated using a simple
+  diff. However, "random" does not seem to produce random results on my 
+  test machine (Linux/gcc/i686).
+</Para>
+
+<Sect1>
+<Title>Timing Results</Title>
+
+<Para>
+These timing results are from running the regression test with the command
+
+<ProgramListing>
+% time make runtest
+</ProgramListing>
+
+<Para>
+  Timing under Linux 2.0.27 seems to have a roughly 5% variation from run
+  to run, presumably due to the timing vagaries of multitasking systems.
+
+<Sect2>
+<Title>v6.3</Title>
+
+<Para>
+<ProgramListing>
+  Time   System
+  02:30  Dual Pentium Pro 180, 96MB, UW-SCSI, Linux 2.0.30, gcc 2.7.2.1 -O2 -m486
+  04:12  Dual Pentium Pro 180, 96MB, EIDE, Linux 2.0.30, gcc 2.7.2.1 -O2 -m486
+</ProgramListing>
+
+<Sect2>
+<Title>v6.1</Title>
+
+<Para>
+<ProgramListing>
+  Time   System
+  06:12  Pentium Pro 180, 32MB, Linux 2.0.30, gcc 2.7.2 -O2 -m486
+  12:06  P-100, 48MB, Linux 2.0.29, gcc
+  39:58  Sparc IPC 32MB, Solaris 2.5, gcc 2.7.2.1 -O -g
+</ProgramListing>
+
+</Chapter>
+
diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..2dabb3ca35a7d5b89a61ced5a6819357a5a2faac
--- /dev/null
+++ b/doc/src/sgml/rules.sgml
@@ -0,0 +1,28 @@
+<Chapter>
+<Title>The <ProductName>Postgres</ProductName> Rule System</Title>
+
+<Para>
+     Production  rule  systems  are conceptually simple, but
+     there are many subtle points involved in actually using
+     them.  Consequently, we will not attempt to explain the
+     actual syntax and operation of the <ProductName>Postgres</ProductName> rule system
+     here.  Instead, you should read 
+<XRef LinkEnd="STON90b" EndTerm="[STON90b]"> to understand
+     some of these points and the theoretical foundations of
+     the  <ProductName>Postgres</ProductName>  rule  system before trying to use rules.
+     The discussion in this section is intended  to  provide
+     an  overview  of the <ProductName>Postgres</ProductName> rule system and point the
+     user at helpful references and examples.
+
+     The "query rewrite" rule  system  modifies  queries  to
+     take rules into consideration, and then passes the modified 
+     query to the query optimizer for  execution.   It
+     is  very powerful, and can be used for many things such
+     as query language procedures, views, and versions.  The
+     power  of  this  rule system is discussed in 
+<XRef LinkEnd="ONG90" EndTerm="[ONG90]">
+ as well as
+<XRef LinkEnd="STON90b" EndTerm="[STON90b]">.
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..c403f816f876c36e83ac2baa91591aff2275db58
--- /dev/null
+++ b/doc/src/sgml/spi.sgml
@@ -0,0 +1,2831 @@
+<Chapter>
+<DocInfo>
+<AuthorGroup>
+<Author>
+<FirstName>Vadim</FirstName>
+<Surname>Mikheev</Surname>
+</Author>
+</AuthorGroup>
+<Date>Transcribed 1998-01-16</Date>
+</DocInfo>
+
+<Title>Server Programming Interface</Title>
+
+<Para>
+   The <FirstTerm>Server Programming Interface</FirstTerm> (<Acronym>SPI</Acronym>) is an attempt to give users the
+ability to run <Acronym>SQL</Acronym> queries inside user-defined <Acronym>C</Acronym> functions.
+Given the lack
+of a proper <FirstTerm>Procedural Language</FirstTerm> (<Acronym>PL</Acronym>) in the current version of 
+<ProductName>Postgres</ProductName>,
+<Acronym>SPI</Acronym> is the only way to write server-stored procedures and triggers.  In the future
+<Acronym>SPI</Acronym> will be used as the "workhorse" for a <Acronym>PL</Acronym>.
+</Para>
+
+<Para>
+   In fact, <Acronym>SPI</Acronym> is just a set of native interface functions to simplify
+access to the Parser, Planner, Optimizer and Executor. <Acronym>SPI</Acronym> also does some
+memory management.
+</Para>
+
+<Para>
+   To avoid misunderstanding we'll use <FirstTerm>function</FirstTerm> to mean <Acronym>SPI</Acronym> interface
+functions and <FirstTerm>procedure</FirstTerm> for user-defined C-functions using <Acronym>SPI</Acronym>.
+</Para>
+
+<Para>
+   <Acronym>SPI</Acronym> procedures are always called by some (upper) Executor and the <Acronym>SPI</Acronym>
+manager uses the Executor to run your queries. Other procedures may be
+called by the Executor running queries from your procedure.
+</Para>
+
+<Para>
+   Note, that if during execution of a query from a procedure the transaction
+is aborted then control will not be returned to your procedure. Rather, all work
+will be rolled back and the server will wait for the next command from the
+client.  This will be changed in future versions.
+</Para>
+
+<Para>
+   Other restrictions are the inability to execute BEGIN, END and ABORT
+(transaction control statements) and cursor operations.  This will also be
+changed in the future.
+</Para>
+
+<Para>
+   If successful, <Acronym>SPI</Acronym> functions return a non-negative result (either via
+a returned integer value or in SPI_result global variable, as described below).
+On error, a negative or NULL result will be returned.
+</Para>
+
+<Sect1>
+<Title>Interface Functions</Title>
+
+<REFENTRY ID="SPI-SPICONNECT-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_connect</REFENTRYTITLE>
+<REFMISCINFO>SPI - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_connect
+</REFNAME>
+<REFPURPOSE>
+   Connects your procedure to the SPI manager.
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPICONNECT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPICONNECT-2"><PRIMARY>SPI_connect</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+int SPI_connect(void)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPICONNECT-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPICONNECT-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>int
+</TERM>
+<LISTITEM>
+<PARA>
+Return status
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM><ReturnValue>SPI_OK_CONNECT</ReturnValue>
+</TERM>
+<LISTITEM>
+<PARA>
+   if connected
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM><ReturnValue>SPI_ERROR_CONNECT</ReturnValue>
+</TERM>
+<LISTITEM>
+<PARA>
+   if not connected
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPICONNECT-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_connect</FUNCTION> opens a connection to the <ProductName>Postgres</ProductName> backend.
+   You should call this function if you will need to execute queries. Some
+   utility SPI functions may be called from un-connected procedures.
+</PARA>
+<PARA>
+   You may get <ReturnValue>SPI_ERROR_CONNECT</ReturnValue> error if <Function>SPI_connect</Function> is
+   called from an already connected procedure - e.g. if you directly call one
+   procedure from another connected one.  Actually, while the child procedure
+   will be able to use SPI, your parent procedure will not be able to continue
+   to use SPI after the child returns (if <Function>SPI_finish</Function> is called by the child).
+   It's bad practice.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPICONNECT-2">
+<TITLE>Usage
+</TITLE>
+<PARA>XXX thomas 1997-12-24
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPICONNECT-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_connect</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+  Initializes the SPI internal
+   structures for query execution and memory management.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPICONNECT-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIFINISH-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_finish</REFENTRYTITLE>
+<REFMISCINFO>SPI - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_finish
+</REFNAME>
+<REFPURPOSE>
+   Disconnects your procedure from the SPI manager.
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIFINISH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>disconnecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIFINISH-2"><PRIMARY>SPI_finish</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_finish(void)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIFINISH-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIFINISH-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>int
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+<ReturnValue>SPI_OK_FINISH</ReturnValue>
+   if properly disconnected
+</Member>
+<Member>
+<ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue>
+   if called from an un-connected procedure
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIFINISH-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_finish</FUNCTION> closes an existing connection to the <ProductName>Postgres</ProductName> backend.
+   You should call this function after completing operations through the SPI manager.
+
+<PARA>
+   You may get the error return <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if <Function>SPI_finish</Function> is
+   called without having a current valid connection.
+ There is no fundamental problem
+   with this; it means that nothing was done by the SPI manager.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIFINISH-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+   <Function>SPI_finish</Function> <Emphasis>must</Emphasis> be called as a final step by a connected procedure
+ or you may get
+   unpredictable results! Note that you can safely skip the call to <Function>SPI_finish</Function>
+   if you abort the transaction (via elog(ERROR)).
+
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIFINISH-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_finish</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+   Disconnects your procedure from the SPI manager and frees all memory
+   allocations made by your procedure via <Function>palloc</Function> since
+ the <Function>SPI_connect</Function>. 
+   These allocations can't be used any more! See Memory management.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIFINISH-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIEXEC-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_exec</REFENTRYTITLE>
+<REFMISCINFO>SPI - Connection Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_exec
+</REFNAME>
+<REFPURPOSE>
+   Creates an execution plan (parser+planner+optimizer) and executes a query.
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIEXEC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>executing</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIEXEC-2"><PRIMARY>SPI_exec</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_exec(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIEXEC-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+char *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+String containing query plan
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Maximum number of tuples to return
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIEXEC-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>int
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+   <ReturnValue>SPI_OK_EXEC</ReturnValue> if properly disconnected
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if called from an un-connected procedure
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur).
+</Member>
+</SimpleList>
+
+<Para>
+   If execution of your query was successful then one of the following
+   (non-negative) values will be returned:
+<SimpleList>
+<Member>
+   <ReturnValue>SPI_OK_UTILITY</ReturnValue> if some utility (e.g. CREATE TABLE ...) was executed
+</Member>
+<Member>
+   <ReturnValue>SPI_OK_SELECT</ReturnValue> if SELECT (but not SELECT ... INTO!) was executed
+</Member>
+<Member>
+   <ReturnValue>SPI_OK_SELINTO</ReturnValue> if SELECT ... INTO was executed
+</Member>
+<Member>
+   <ReturnValue>SPI_OK_INSERT</ReturnValue> if INSERT (or INSERT ... SELECT) was executed
+</Member>
+<Member>
+   <ReturnValue>SPI_OK_DELETE</ReturnValue> if DELETE was executed
+</Member>
+<Member>
+   <ReturnValue>SPI_OK_UPDATE</ReturnValue> if UPDATE was executed
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIEXEC-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_exec</FUNCTION> creates an execution plan (parser+planner+optimizer)
+ and executes the query for <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> tuples.
+
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIEXEC-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+  This should only be called from a connected procedure.
+   If <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> is zero then it executes the query for all tuples returned by the
+   query scan. Using <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> > 0 you may restrict the number of tuples for
+   which the query will be executed. For example,
+
+<ProgramListing>
+SPI_exec ("insert into table select * from table", 5);
+</ProgramListing>
+
+will allow at most 5 tuples to be inserted into table.
+
+   If execution of your query was successful then a non-negative value will be returned.
+
+<Note>
+<Para>
+You may pass many queries in one string or query string may be
+   re-written by RULEs. <Function>SPI_exec</Function> returns the result for the last query
+   executed.
+</Para>
+</Note>
+
+<Para>
+   The actual number of tuples for which the (last) query was executed is
+   returned in the global variable SPI_processed (if not <ReturnValue>SPI_OK_UTILITY</ReturnValue>).
+
+   If <ReturnValue>SPI_OK_SELECT</ReturnValue> returned and SPI_processed &gt; 0 then you may use global
+   pointer SPITupleTable *SPI_tuptable to access the selected tuples:
+
+   Also NOTE, that <Function>SPI_finish</Function> frees and makes all SPITupleTables
+   unusable! (See Memory management).
+</Para>
+
+<Para>
+   <Function>SPI_exec</Function> may return one of the following (negative) values:
+<SimpleList>
+<Member>
+   <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur).
+</Member>
+</SimpleList>
+
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIEXEC-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_exec</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+   Disconnects your procedure from the SPI manager and frees all memory
+   allocations made by your procedure via <Function>palloc</Function> since the <Function>SPI_connect</Function>. 
+   These allocations can't be used any more! See Memory management.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIEXEC-4">
+<TITLE>Structures
+</TITLE>
+<PARA>
+   If <ReturnValue>SPI_OK_SELECT</ReturnValue> returned and SPI_processed > 0 then you may use the global
+   pointer SPITupleTable *SPI_tuptable to access the selected tuples.
+
+<Para>
+   Structure SPITupleTable is defined in spi.h:
+<ProgramListing>
+   typedef struct
+   {
+       uint32      alloced;        /* # of alloced vals */
+       uint32      free;           /* # of free vals */
+       TupleDesc   tupdesc;        /* tuple descriptor */
+       HeapTuple  *vals;           /* tuples */
+   } SPITupleTable;
+</ProgramListing>
+
+<Para>
+   HeapTuple *vals is an array of pointers to tuples. TupleDesc tupdesc is
+   a tuple descriptor which you may pass to SPI functions dealing with
+   tuples.
+
+<Para>
+   NOTE! Functions <Function>SPI_exec</Function>, <Function>SPI_execp</Function> and <Function>SPI_prepare</Function> change both
+   SPI_processed and SPI_tuptable (just the pointer, not the contents of the
+   structure)!  So, save them in local procedure variables if you need them.
+
+<Para>
+   Also NOTE, that <Function>SPI_finish</Function> frees and makes all SPITupleTables
+   unusable! (See Memory management).
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIPREPARE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_prepare</REFENTRYTITLE>
+<REFMISCINFO>SPI - Plan Preparation</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_prepare
+</REFNAME>
+<REFPURPOSE>
+   Connects your procedure to the SPI manager.
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIPREPARE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIPREPARE-2"><PRIMARY>SPI_prepare</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_prepare(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIPREPARE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Query string
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+<REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Number of input parameters ($1 ... $nargs - as in SQL-functions)
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+<REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Pointer list of type <Acronym>OID</Acronym>s to input arguments
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIPREPARE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>void *
+</TERM>
+<LISTITEM>
+<PARA>
+Pointer to an execution plan (parser+planner+optimizer)
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIPREPARE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_prepare</FUNCTION> 
+   creates and returns an execution plan (parser+planner+optimizer) but doesn't
+   execute the query. Should only be called from a connected procedure.
+
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIPREPARE-2">
+<TITLE>Usage
+</TITLE>
+<PARA>
+   nargs is number of parameters ($1 ... $nargs - as in SQL-functions),
+   and nargs may be 0 only if there is not any $1 in query.
+
+<Para>
+   Execution of prepared execution plans is sometimes much faster so this
+   feature may be useful if the same query will be executed many times.
+
+<Para>
+The plan returned by <Function>SPI_prepare</Function> may be used only in current
+   invocation of the procedure since <Function>SPI_finish</Function> frees memory allocated for a plan. 
+   See <Function>SPI_saveplan</Function>.
+
+<Para>
+   If successful, a non-null pointer will be returned. Otherwise, you'll get
+   a NULL plan.  In both cases SPI_result will be set like the value returned
+   by SPI_exec, except that it is set to 
+   <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or nargs < 0 or nargs > 0 && argtypes
+   is NULL.
+
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIPREPARE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_prepare</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+TBD
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIPREPARE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPISAVEPLAN-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_saveplan</REFENTRYTITLE>
+<REFMISCINFO>SPI - Plan Storage</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_saveplan
+</REFNAME>
+<REFPURPOSE>
+   Saves a passed plan
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPISAVEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPISAVEPLAN-2"><PRIMARY>SPI_saveplan</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_saveplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPISAVEPLAN-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Passed plan
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPISAVEPLAN-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>void *
+</TERM>
+<LISTITEM>
+<PARA>
+Execution plan location. NULL if unsuccessful.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>SPI_result
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+   <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is un-connected
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPISAVEPLAN-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_saveplan</FUNCTION> 
+   stores a plan prepared by <Function>SPI_prepare</Function> in safe memory
+   protected from freeing by <Function>SPI_finish</Function> or the transaction manager.
+
+<Para>
+   In the current version of <ProductName>Postgres</ProductName> there is no ability to
+ store prepared plans in the system
+   catalog and fetch them from there for execution. This will be implemented
+   in future versions.
+
+   As an alternative, there is the ability to reuse prepared plans in the
+   consequent invocations of your procedure in the current session.
+   Use <Function>SPI_execp</Function> to execute this saved plan.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPISAVEPLAN-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+   <Function>SPI_saveplan</Function> saves a passed plan (prepared by <Function>SPI_prepare</Function>) in memory
+   protected from freeing by <Function>SPI_finish</Function> and by the transaction manager and
+   returns a pointer to the saved plan.  You may save the pointer returned in
+   a local variable.  Always check if this pointer is NULL or not either when
+   preparing a plan or using an already prepared plan in SPI_execp (see below).
+
+<Note>
+<Para>
+   If one of the objects (a relation, function, etc.) referenced by the prepared
+   plan is dropped during your session (by your backend or another process) then the
+   results of <Function>SPI_execp</Function> for this plan will be unpredictable.
+</Para>
+</Note>
+
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPISAVEPLAN-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_saveplan</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+TBD
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPISAVEPLAN-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIEXECP-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_execp</REFENTRYTITLE>
+<REFMISCINFO>SPI - Plan Execution</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_execp
+</REFNAME>
+<REFPURPOSE>
+   Executes a plan prepared or returned by <Function>SPI_saveplan</Function>
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIEXECP-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIEXECP-2"><PRIMARY>SPI_execp</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_execp(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>,
+<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>,
+<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>,
+<REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIEXECP-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Execution plan
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Actual parameter values
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Array describing what parameters get NULLs
+<SimpleList>
+<Member>'n' indicates NULL allowed</Member>
+<Member>' ' indicates NULL not allowed</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Number of tuples for which plan is to be executed
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIEXECP-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>int
+</TERM>
+<LISTITEM>
+<PARA>
+   Returns the same value as <Function>SPI_exec</Function> as well as
+<SimpleList>
+<Member>
+ <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue>
+ if <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
+ is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> &lt; 0
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_PARAM</ReturnValue>
+ if <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>
+ is NULL
+ and <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>
+ was prepared with some parameters.
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>SPI_tuptable
+</TERM>
+<LISTITEM>
+<PARA>
+initialized as in
+   <Function>SPI_exec</Function> if successful
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>SPI_processed
+</TERM>
+<LISTITEM>
+<PARA>
+initialized as in
+   <Function>SPI_exec</Function> if successful
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIEXECP-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_execp</FUNCTION> 
+   stores a plan prepared by <Function>SPI_prepare</Function> in safe memory
+   protected from freeing by <Function>SPI_finish</Function> or the transaction manager.
+
+<Para>
+   In the current version of <ProductName>Postgres</ProductName> there is no ability to
+ store prepared plans in the system
+   catalog and fetch them from there for execution. This will be implemented
+   in future versions.
+
+   As a work arround, there is the ability to reuse prepared plans in the
+   consequent invocations of your procedure in the current session.
+   Use <Function>SPI_execp</Function> to execute this saved plan.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIEXECP-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+   If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>
+is NULL then 
+   <Function>SPI_execp</Function> 
+assumes that all values (if any) are NOT NULL.
+
+<Note>
+<Para>
+   If one of the objects (a relation, function, etc.) referenced by the prepared
+   plan is dropped during your session (by your backend or another process) then the
+   results of <Function>SPI_execp</Function> for this plan will be unpredictable.
+</Para>
+</Note>
+
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIEXECP-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>SPI_execp</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>
+TBD
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIEXECP-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+</Sect1>
+
+<Sect1>
+<Title>Interface Support Functions</Title>
+
+<Para>
+All functions described below may be used by connected and unconnected
+procedures.
+</Para>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPICOPYTUPLE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_copytuple</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Copy</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_copytuple
+</REFNAME>
+<REFPURPOSE>
+Makes copy of tuple in upper Executor context
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-2"><PRIMARY>SPI_copytuple</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_copytuple(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple to be copied
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+HeapTuple
+</TERM>
+<LISTITEM>
+<PARA>
+Copied tuple
+<SimpleList>
+<Member>
+ <ReturnValue>non-NULL</ReturnValue>
+ if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+ is not NULL and the copy was successful
+</Member>
+<Member>
+   <ReturnValue>NULL</ReturnValue>
+ only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+ is NULL
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_copytuple</FUNCTION> 
+   makes a copy of tuple in upper Executor context. See the section on Memory Management.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+TBD
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIMODIFYTUPLE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Modify</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_modifytuple
+</REFNAME>
+<REFPURPOSE>
+Modifies tuple of relation
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>modifying tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-2"><PRIMARY>SPI_modifytuple</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_modifytuple(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE>
+, <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple to be modified
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Number of attribute numbers in attnum
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int * <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Array of numbers of the attributes which are to be changed
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+Datum * <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+New values for the attributes specified
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+char * <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Which attributes are NULL, if any
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+HeapTuple
+</TERM>
+<LISTITEM>
+<PARA>
+New tuple with modifications
+<SimpleList>
+<Member>
+ <ReturnValue>non-NULL</ReturnValue>
+ if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+ is not NULL and the modify was successful
+</Member>
+<Member>
+   <ReturnValue>NULL</ReturnValue>
+ only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+ is NULL
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+SPI_result
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+   <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if rel is NULL or tuple is NULL or natts &le; 0 or
+   attnum is NULL or Values is NULL.
+</Member>
+<Member>
+   <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if there is an invalid 
+   attribute number in attnum (attnum &le; 0 or &gt; number of
+   attributes in tuple)
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_modifytuple</FUNCTION> 
+Modifies a tuple in upper Executor context. See the section on Memory Management.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+If successful, a pointer to the new tuple is returned. The new tuple is
+allocated in upper Executor context (see Memory management). Passed tuple
+is not changed.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIFNUMBER-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_fnumber</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_fnumber
+</REFNAME>
+<REFPURPOSE>
+Finds the attribute number for specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIFNUMBER-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIFNUMBER-2"><PRIMARY>SPI_fnumber</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_fnumber(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIFNUMBER-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+char * <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Field name
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIFNUMBER-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+int
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+<SimpleList>
+<Member>
+Valid one-based index number of attribute
+</Member>
+<Member>
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if the named attribute is not found
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIFNUMBER-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_fnumber</FUNCTION> 
+   returns the attribute number for the attribute with name in fname.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIFNUMBER-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIFNUMBER-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIFNUMBER-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIFNAME-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_fname</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_fname
+</REFNAME>
+<REFPURPOSE>
+Finds the attribute name for the specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIFNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIFNAME-2"><PRIMARY>SPI_fname</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_fname(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIFNAME-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+char * <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIFNAME-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+char *
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute name
+<SimpleList>
+<Member>
+NULL if fnumber is out of range
+</Member>
+<Member>
+SPI_result set to
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> on error
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIFNAME-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_fname</FUNCTION> 
+   returns the attribute name for the specified attribute.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIFNAME-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIFNAME-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+Returns a newly-allocated copy of the attribute name.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIFNAME-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIGETVALUE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_getvalue</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_getvalue
+</REFNAME>
+<REFPURPOSE>
+Returns the string value of the specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIGETVALUE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIGETVALUE-2"><PRIMARY>SPI_getvalue</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_getvalue(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIGETVALUE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple to be examined
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIGETVALUE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+char *
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute value or NULL if
+<SimpleList>
+<Member>
+attribute is NULL
+</Member>
+<Member>
+fnumber is out of range
+(SPI_result set to
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>)
+</Member>
+<Member>
+no output function available
+(SPI_result set to
+<ReturnValue>SPI_ERROR_NOOUTFUNC</ReturnValue>)
+</Member>
+</SimpleList>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIGETVALUE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_getvalue</FUNCTION> 
+   returns an external (string) representation of the value of the specified attribute.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETVALUE-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETVALUE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+Allocates memory as required by the value.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIGETVALUE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIGETBINVAL-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_getbinval</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_getbinval
+</REFNAME>
+<REFPURPOSE>
+Returns the binary value of the specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIGETBINVAL-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIGETBINVAL-2"><PRIMARY>SPI_getbinval</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_getbinval(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIGETBINVAL-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple to be examined
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIGETBINVAL-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+Datum
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute binary value
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+bool * <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+flag for null value in attribute
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+SPI_result
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIGETBINVAL-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_getbinval</FUNCTION> 
+   returns the binary value of the specified attribute.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETBINVAL-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETBINVAL-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+Does not allocate new space for the binary value.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIGETBINVAL-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIGETTYPE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_gettype</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_gettype
+</REFNAME>
+<REFPURPOSE>
+Returns the type name of the specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIGETTYPE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIGETTYPE-2"><PRIMARY>SPI_gettype</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_gettype(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIGETTYPE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIGETTYPE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+char *
+</TERM>
+<LISTITEM>
+<PARA>
+The type name for the specified attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+SPI_result
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIGETTYPE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_gettype</FUNCTION> 
+   returns a copy of the type name for the specified attribute.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETTYPE-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETTYPE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+Does not allocate new space for the binary value.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIGETTYPE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIGETTYPEID-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_gettypeid</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_gettypeid
+</REFNAME>
+<REFPURPOSE>
+Returns the type <Acronym>OID</Acronym> of the specified attribute
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIGETTYPEID-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIGETTYPEID-2"><PRIMARY>SPI_gettypeid</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_gettypeid(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIGETTYPEID-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input tuple description
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIGETTYPEID-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+<Acronym>OID</Acronym>
+</TERM>
+<LISTITEM>
+<PARA>
+The type <Acronym>OID</Acronym> for the specified attribute number
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+SPI_result
+</TERM>
+<LISTITEM>
+<PARA>
+<SimpleList>
+<Member>
+<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>
+</Member>
+</SimpleList>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIGETTYPEID-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_gettypeid</FUNCTION> 
+   returns the type <Acronym>OID</Acronym> for the specified attribute.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETTYPEID-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+Attribute numbers are 1 based.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETTYPEID-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+TBD
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIGETTYPEID-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIGETRELNAME-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_getrelname</REFENTRYTITLE>
+<REFMISCINFO>SPI - Tuple Information</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_getrelname
+</REFNAME>
+<REFPURPOSE>
+Returns the name of the specified relation
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIGETRELNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIGETRELNAME-2"><PRIMARY>SPI_getrelname</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_getrelname(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIGETRELNAME-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Input relation
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIGETRELNAME-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+char *
+</TERM>
+<LISTITEM>
+<PARA>
+The name of the specified relation
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIGETRELNAME-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_getrelname</FUNCTION> 
+   returns the name of the specified relation.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETRELNAME-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+TBD
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIGETRELNAME-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+Copies the relation name into new storage.
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIGETRELNAME-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIPALLOC-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_palloc</REFENTRYTITLE>
+<REFMISCINFO>SPI - Memory Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_palloc
+</REFNAME>
+<REFPURPOSE>
+Allocates memory in upper Executor context
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIPALLOC-2"><PRIMARY>SPI_palloc</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_palloc(<REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIPALLOC-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Octet size of storage to allocate
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIPALLOC-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void *
+</TERM>
+<LISTITEM>
+<PARA>
+New storage space of specified size
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIPALLOC-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_palloc</FUNCTION> 
+   allocates memory in upper Executor context. See section on memory management.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIPALLOC-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+TBD
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIPALLOC-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+TBD
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIPALLOC-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIREPALLOC-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_repalloc</REFENTRYTITLE>
+<REFMISCINFO>SPI - Memory Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_repalloc
+</REFNAME>
+<REFPURPOSE>
+Re-allocates memory in upper Executor context
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIREPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIREPALLOC-2"><PRIMARY>SPI_repalloc</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_repalloc(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIREPALLOC-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Pointer to existing storage
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>
+Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Octet size of storage to allocate
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIREPALLOC-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void *
+</TERM>
+<LISTITEM>
+<PARA>
+New storage space of specified size with contents copied from existing area
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIREPALLOC-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_repalloc</FUNCTION> 
+   re-allocates memory in upper Executor context. See section on memory management.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIREPALLOC-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+TBD
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIREPALLOC-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+TBD
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIREPALLOC-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+<!-- *********************************************** -->
+
+<REFENTRY ID="SPI-SPIPFREE-1">
+<REFMETA>
+<REFENTRYTITLE>SPI_pfree</REFENTRYTITLE>
+<REFMISCINFO>SPI - Memory Management</REFMISCINFO>
+</REFMETA>
+<REFNAMEDIV>
+<REFNAME>SPI_pfree
+</REFNAME>
+<REFPURPOSE>
+Frees memory from upper Executor context
+</REFPURPOSE>
+<INDEXTERM ID="IX-SPI-SPIPFREE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-SPI-SPIPFREE-2"><PRIMARY>SPI_pfree</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>1997-12-24</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+SPI_pfree(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>)
+</SYNOPSIS>
+
+<REFSECT2 ID="R2-SPI-SPIPFREE-1">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>
+Pointer to existing storage
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+
+<REFSECT2 ID="R2-SPI-SPIPFREE-2">
+<REFSECT2INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT2INFO>
+<TITLE>Outputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>
+None
+</TERM>
+<LISTITEM>
+<PARA>
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+</REFSECT2>
+</REFSYNOPSISDIV>
+
+<REFSECT1 ID="R1-SPI-SPIPFREE-1">
+<REFSECT1INFO>
+<DATE>1997-12-24</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA>
+<FUNCTION>SPI_pfree</FUNCTION> 
+   frees memory in upper Executor context. See section on memory management.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-SPI-SPIPFREE-2">
+<TITLE>Usage
+</TITLE>
+<Para>
+TBD
+</PARA>
+</REFSECT1>
+<!--
+<REFSECT1 ID="R1-SPI-SPIPFREE-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA>
+TBD
+</PARA>
+</REFSECT1>
+-->
+<!--
+<REFSECT1 ID="R1-SPI-SPIPFREE-4">
+<TITLE>Structures
+</TITLE>
+<PARA>None
+</PARA>
+</REFSECT1>
+-->
+</REFENTRY>
+
+</Sect1>
+
+<Sect1>
+<Title>Memory Management</Title>
+
+<Para>
+   Server allocates memory in memory contexts in such way that allocations
+made in one context may be freed by context destruction without affecting
+allocations made in other contexts. All allocations (via <Function>palloc</Function>, etc) are
+made in the context which are chosen as current one. You'll get
+unpredictable results if you'll try to free (or reallocate) memory allocated
+not in current context.
+</Para>
+
+<Para>
+   Creation and switching between memory contexts are subject of SPI manager
+memory management.
+</Para>
+
+<Para>
+
+   SPI procedures deal with two memory contexts: upper Executor memory
+context and procedure memory context (if connected). 
+</Para>
+
+<Para>
+
+   Before a procedure is connected to the SPI manager, current memory context
+is upper Executor context so all allocation made by the procedure itself via
+<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility functions before connecting to SPI are
+made in this context.
+</Para>
+
+<Para>
+
+   After <Function>SPI_connect</Function> is called current context is the procedure's one.  All
+allocations made via <Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility functions (except
+for <Function>SPI_copytuple</Function>, <Function>SPI_modifytuple</Function>,
+ <Function>SPI_palloc</Function> and <Function>SPI_repalloc</Function>) are
+made in this context.
+</Para>
+
+<Para>
+
+   When a procedure disconnects from the SPI manager (via <Function>SPI_finish</Function>) the
+current context is restored to the upper Executor context and all allocations
+made in the procedure memory context are freed and can't be used any more!
+</Para>
+
+<Para>
+
+   If you want to return something to the upper Executor then you have to
+allocate memory for this in the upper context!
+</Para>
+
+<Para>
+
+   SPI has no ability to automatically free allocations in the upper Executor
+context!
+</Para>
+
+<Para>
+
+   SPI automatically frees memory allocated during execution of a query when
+this query is done!
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Visibility of Data Changes</Title>
+
+<Para>
+<ProductName>Postgres</ProductName> data changes visibility rule: during a query execution, data
+changes made by the query itself (via SQL-function, SPI-function, triggers)
+are invisible to the query scan.  For example, in query
+
+   INSERT INTO a SELECT * FROM a
+
+   tuples inserted are invisible for SELECT' scan.  In effect, this
+duplicates the database table within itself (subject to unique index
+rules, of course) without recursing.
+</Para>
+
+<Para>
+   Changes made by query Q are visible by queries which are started after
+query Q, no matter whether they are started inside Q (during the execution
+of Q) or after Q is done.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Examples</Title>
+
+<Para>
+   This example of SPI usage demonstrates the visibility rule.
+   There are more complex examples in in src/test/regress/regress.c and
+in contrib/spi.
+</Para>
+
+<Para>
+   This is a very simple example of SPI usage. The procedure execq accepts
+an SQL-query in its first argument and tcount in its second, executes the
+query using SPI_exec and returns the number of tuples for which the query
+executed:
+
+<ProgramListing>
+#include "executor/spi.h"	/* this is what you need to work with SPI */
+
+int execq(text *sql, int cnt);
+
+int
+execq(text *sql, int cnt)
+{
+	int ret;
+	int proc = 0;
+	
+	SPI_connect();
+	
+	ret = SPI_exec(textout(sql), cnt);
+	
+	proc = SPI_processed;
+	/*
+	 * If this is SELECT and some tuple(s) fetched -
+	 * returns tuples to the caller via elog (NOTICE).
+	 */
+	if ( ret == SPI_OK_SELECT && SPI_processed > 0 )
+	{
+		TupleDesc tupdesc = SPI_tuptable->tupdesc;
+		SPITupleTable *tuptable = SPI_tuptable;
+		char buf[8192];
+		int i;
+		
+		for (ret = 0; ret < proc; ret++)
+		{
+			HeapTuple tuple = tuptable->vals[ret];
+			
+			for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)
+				sprintf(buf + strlen (buf), " %s%s",
+					SPI_getvalue(tuple, tupdesc, i),
+					(i == tupdesc->natts) ? " " : " |");
+			elog (NOTICE, "EXECQ: %s", buf);
+		}
+	}
+
+	SPI_finish();
+
+	return (proc);
+}
+</ProgramListing>
+</Para>
+
+<Para>
+   Now, compile and create the function:
+
+<ProgramListing>
+create function execq (text, int4) returns int4 as '...path_to_so' language 'c';
+</ProgramListing>
+
+<ProgramListing>
+vac=> select execq('create table a (x int4)', 0);
+execq
+-----
+    0
+(1 row)
+
+vac=> insert into a values (execq('insert into a values (0)',0));
+INSERT 167631 1
+vac=> select execq('select * from a',0);
+NOTICE:EXECQ:  0 <<< inserted by execq
+
+NOTICE:EXECQ:  1 <<< value returned by execq and inserted by upper INSERT
+
+execq
+-----
+    2
+(1 row)
+
+vac=> select execq('insert into a select x + 2 from a',1);
+execq
+-----
+    1
+(1 row)
+
+vac=> select execq('select * from a', 10);
+NOTICE:EXECQ:  0 
+
+NOTICE:EXECQ:  1 
+
+NOTICE:EXECQ:  2 <<< 0 + 2, only one tuple inserted - as specified
+
+execq
+-----
+    3            <<< 10 is max value only, 3 is real # of tuples
+(1 row)
+
+vac=> delete from a;
+DELETE 3
+vac=> insert into a values (execq('select * from a', 0) + 1);
+INSERT 167712 1
+vac=> select * from a;
+x
+-
+1                <<< no tuples in a (0) + 1
+(1 row)
+
+vac=> insert into a values (execq('select * from a', 0) + 1);
+NOTICE:EXECQ:  0 
+INSERT 167713 1
+vac=> select * from a;
+x
+-
+1
+2                <<< there was single tuple in a + 1
+(2 rows)
+
+--   This demonstrates data changes visibility rule:
+
+vac=> insert into a select execq('select * from a', 0) * x from a;
+NOTICE:EXECQ:  1 
+NOTICE:EXECQ:  2 
+NOTICE:EXECQ:  1 
+NOTICE:EXECQ:  2 
+NOTICE:EXECQ:  2 
+INSERT 0 2
+vac=> select * from a;
+x
+-
+1
+2
+2                <<< 2 tuples * 1 (x in first tuple)
+6                <<< 3 tuples (2 + 1 just inserted) * 2 (x in second tuple)
+(4 rows)             ^^^^^^^^ 
+                     tuples visible to execq() in different invocations
+</ProgramListing>
+</Para>
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/start-ag.sgml b/doc/src/sgml/start-ag.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..6ca52ddaf705ab4906bb2c4434fc5ba7bae33d20
--- /dev/null
+++ b/doc/src/sgml/start-ag.sgml
@@ -0,0 +1,432 @@
+<!--
+-	This file currently contains several small chapters.
+-	Each chapter should be split off into a separate source file...
+-	- thomas 1998-02-24
+-->
+
+<Chapter>
+<Title>Runtime Environment</Title>
+
+<Para>
+<Figure Id="ADMIN-LAYOUT">
+<Title><ProductName>Postgres</ProductName> file layout</Title>
+<Graphic Align="center" FileRef="layout.gif" Format="GIF"></Graphic>
+</Figure>
+
+<XRef LinkEnd="ADMIN-LAYOUT" EndTerm="ADMIN-LAYOUT">
+shows how the <ProductName>Postgres</ProductName>  distribution  is  laid
+     out  when installed in the default way. For simplicity,
+     we will assume that <ProductName>Postgres</ProductName> has been installed in  the
+     directory  <FileName>/usr/local/pgsql</FileName>.   Therefore, wherever
+     you see the directory <FileName>/usr/local/pgsql</FileName> you  should
+     substitute  the name of the directory where <ProductName>Postgres</ProductName> is
+     actually installed.
+     All <ProductName>Postgres</ProductName> commands are installed  in  the  directory
+     <FileName>/usr/local/pgsql/bin</FileName>.   Therefore,  you should add
+     this directory to your shell command path.  If you  use
+     a variant of the Berkeley C shell, such as csh or tcsh,
+     you would add
+<ProgramListing>
+set path = ( /usr/local/pgsql/bin path )
+</ProgramListing>
+     in the .login file in your home directory.  If you  use
+     a  variant  of  the  Bourne  shell, such as sh, ksh, or
+     bash, then you would add
+<ProgramListing>
+PATH=/usr/local/pgsql/bin PATH
+export PATH
+</ProgramListing>
+     to the .profile file in your home directory.
+     From now on, we will assume that  you  have  added  the
+     <ProductName>Postgres</ProductName>  bin  directory to your path.  In addition, we
+     will make frequent reference to "setting a shell  
+     variable"  or  "setting an environment variable" throughout
+     this document.  If you did  not  fully  understand  the
+     last  paragraph  on  modifying  your  search  path, you
+     should consult the UNIX manual pages that describe your
+     shell before going any further.
+</Para>
+
+<Para>
+If your site administrator has not set things up in the
+default  way,  you may have some more work to do.  For example, if the database server machine is a remote machine, you
+will need to set the <Acronym>PGHOST</Acronym> environment variable to the name
+of the database server machine.   The  environment  variable
+<Acronym>PGPORT</Acronym> may also have to be set.  The bottom line is this: if
+you try to start an application  program  and  it  complains
+that it cannot connect to the <Application>postmaster</Application>, you should immediately consult your site administrator to make sure that your
+environment is properly set up.
+</Para>
+
+<Sect1>
+<Title>Locale Support</Title>
+
+<Para>
+<Note>
+<Para>
+Written by Oleg Bartunov.
+See <ULink url="http://www.sai.msu.su/~megera/postgres/">Oleg's web page</ULink>
+ for additional information on locale and Russian language support.
+
+</Para>
+</Note>
+While doing a project for a company in Moscow, Russia, I encountered the problem that postgresql had no
+support of national alphabets. After looking for possible workarounds I decided to develop support of locale myself.
+I'm not a C-programer but already had some experience with locale programming when I work with perl
+(debugging) and glimpse. After several days of digging through
+ the <ProductName>Postgres</ProductName> source tree I made very minor corections to
+src/backend/utils/adt/varlena.c and src/backend/main/main.c and got what I needed! I did support only for
+LC_CTYPE and LC_COLLATE, but later LC_MONETARY was added by others. I got many
+messages from people about this patch so I decided to send it to developers and (to my surprise) it was
+incorporated into postgresql distribution.
+
+<Para>
+ People often complain that locale doesn't work for them. There are several common mistakes: 
+
+<ItemizedList>
+<ListItem>
+<Para>
+     Didn't properly configure postgresql before compilation. 
+     You must run configure with --enable-locale option to enable locale support. 
+     Didn't setup environment correctly when starting postmaster. 
+     You must define environment variables $LC_CTYPE and $LC_COLLATE before running postmaster
+     because backend gets information about locale from environment. I use following shell script
+     (runpostgres): 
+
+<ProgramListing>
+     #!/bin/sh
+
+     export LC_CTYPE=koi8-r
+     export LC_COLLATE=koi8-r
+     postmaster -B 1024 -S -D/usr/local/pgsql/data/ -o '-Fe'
+</ProgramListing>
+
+     and run it from rc.local as 
+
+<ProgramListing>
+     /bin/su - postgres -c "/home/postgres/runpostgres"
+</ProgramListing>
+
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+     Broken locale support in OS (for example, locale support in libc under Linux several times has changed
+     and this caused a lot of problems). Latest perl has also support of locale and if locale is broken perl -v will
+     complain something like: 
+
+     8:17[mira]:~/WWW/postgres>setenv LC_CTYPE not_exist
+     8:18[mira]:~/WWW/postgres>perl -v
+     perl: warning: Setting locale failed.
+     perl: warning: Please check that your locale settings:
+             LC_ALL = (unset),
+             LC_CTYPE = "not_exist",
+             LANG = (unset)
+         are supported and installed on your system.
+     perl: warning: Falling back to the standard locale ("C").
+
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+     Wrong location of locale files!
+
+     Possible location: <FileName>/usr/lib/locale</FileName> (Linux, Solaris), <FileName>/usr/share/locale</FileName> (Linux), <FileName>/usr/lib/nls/loc</FileName> (DUX 4.0)
+     Check man locale for right place. Under Linux I did a symbolical link between <FileName>/usr/lib/locale</FileName> and
+     <FileName>/usr/share/locale</FileName> to be sure next libc will not break my locale.
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Sect2>
+<Title>What are the Benefits?</Title> 
+
+<Para>
+You can use ~* and order by operators for strings contain characters from national alphabets. Non-english users
+definitely need that. If you won't use locale stuff just undefine USE_LOCALE variable. 
+
+<Sect2>
+<Title>What are the Drawbacks?</Title>
+
+<Para>
+There is one evident drawback of using locale - it's speed ! So, use locale only if you really need it. 
+
+</Chapter>
+
+<Chapter>
+<Title>Starting <Application>postmaster</Application></Title>
+
+<Para>
+     Nothing can happen to a database unless the  <Application>postmaster</Application>
+     process  is  running.  As the site administrator, there
+     are a number  of  things  you  should  remember  before
+     starting  the  <Application>postmaster</Application>.   These are discussed in the
+     section of this  manual  titled,  "Administering  Postgres."  
+     However, if <ProductName>Postgres</ProductName> has been installed by following 
+     the installation instructions exactly  as  written,  the  
+     following  simple  command is all you should
+     need to start the <Application>postmaster</Application>:
+<ProgramListing>
+% postmaster
+</ProgramListing>
+     The <Application>postmaster</Application> occasionally prints out  messages  which
+     are  often helpful during troubleshooting.  If you wish
+     to view debugging messages from the <Application>postmaster</Application>, you can
+     start  it with the -d option and redirect the output to
+     the log file:
+<ProgramListing>
+% postmaster -d >& pm.log &
+</ProgramListing>
+     If you do not wish to see these messages, you can type
+<ProgramListing>
+% postmaster -S
+</ProgramListing>
+     and the <Application>postmaster</Application> will be "S"ilent.  Notice that there
+     is no ampersand ("&amp") at the end of the last example.
+</Para>
+</Chapter>
+
+<Chapter>
+<Title>Adding and Deleting Users</Title>
+
+<Para>
+     <Application>createuser</Application> enables specific users to access
+     <ProductName>Postgres</ProductName>.  <Application>destroyuser</Application> removes  users  and
+     prevents them from accessing <ProductName>Postgres</ProductName>.  Note that these
+     commands only affect users with  respect  to  <ProductName>Postgres</ProductName>;
+     they  have  no  effect on users other privileges or status with regards
+to the underlying 
+     operating system.
+</Para>
+</Chapter>
+
+<Chapter>
+<Title>Disk Management</Title>
+
+<Para>
+</Para>
+
+<Sect1>
+<Title>Alternate Locations</Title>
+
+<Para>
+It is possible to create a database in a location other than the default
+location for the installation. Remember that all database access actually
+occurs through the database backend, so that any location specified must
+be accessible by the backend.
+
+<Para>
+ Either an absolute path name or an environment variable
+may be specified as a location. Note that for security and integrity reasons,
+all paths and environment variables so specified have some
+additional path fields appended.
+
+<Note>
+<Para>
+ The environment variable style of specification
+is to be preferred since it allows the site administrator more flexibility in
+managing disk storage.
+</Para>
+</Note>
+
+<Para>
+Remember that database creation is actually performed by the database backend.
+Therefore, any environment variable specifying an alternate location must have
+been defined before the backend was started. To define an alternate location
+PGDATA2 pointing to <FileName>/home/postgres/data</FileName>, type
+<ProgramListing>
+% setenv PGDATA2 /home/postgres/data
+</ProgramListing>
+
+<Para>
+Usually, you will want to define this variable in the <ProductName>Postgres</ProductName> superuser's
+<FileName>.profile</FileName>
+or
+<FileName>.cshrc</FileName>
+initialization file to ensure that it is defined upon system startup.
+
+<Para>
+To create a data storage area in <FileName>/home/postgres/data</FileName>, ensure
+that <FileName>/home/postgres</FileName> already exists and is writable.
+From the command line, type
+<ProgramListing>
+% initlocation $PGDATA2
+Creating Postgres database system directory /home/postgres/data
+
+Creating Postgres database system directory /home/postgres/data/base
+
+</ProgramListing>
+
+<Para>
+To test the new location, create a database <Database>test</Database> by typing
+<ProgramListing>
+% createdb -D PGDATA2 test
+% destroydb test
+</ProgramListing>
+</Sect1>
+</Chapter>
+
+<Chapter>
+<Title>Troubleshooting</Title>
+
+<Para>
+     Assuming that  your  site  administrator  has  properly
+     started  the  <Application>postmaster</Application>  process and authorized you to
+     use the database, you (as a user) may begin to start up
+     applications.   As previously mentioned, you should add
+     <FileName>/usr/local/pgsql/bin</FileName> to your  shell  search  path.
+     In  most  cases,  this  is all you should have to do in
+     terms of preparation.
+
+<Para>
+     If  you get the following error message from a <ProductName>Postgres</ProductName>
+     command (such as <Application>psql</Application> or <Application>createdb</Application>):
+<ProgramListing>
+connectDB() failed: Is the postmaster running at 'localhost' on port '4322'?
+</ProgramListing>
+     it is usually because either the <Application>postmaster</Application>  is  not  running,
+ or you are attempting to connect to the wrong server host.
+     If you get the following error message:
+<ProgramListing>
+FATAL 1:Feb 17 23:19:55:process userid (2360) != database owner (268)
+</ProgramListing>
+     it means that the site administrator started the  <Application>postmaster</Application>
+  as  the  wrong user.  Tell him to restart it as
+     the <ProductName>Postgres</ProductName> superuser.
+</Para>
+</Chapter>
+
+<Chapter>
+<Title>Managing a Database</Title>
+
+<Para>
+     Now that <ProductName>Postgres</ProductName> is up and running we can create  some
+     databases  to  experiment  with.  Here, we describe the
+     basic commands for managing a database.
+</Para>
+
+<Sect1>
+<Title>Creating a Database</Title>
+
+<Para>
+     Let's say you want to create  a  database  named  mydb.
+     You can do this with the following command:
+<ProgramListing>
+% createdb mydb
+</ProgramListing>
+
+     <ProductName>Postgres</ProductName>  allows  you to create any number of databases
+     at a  given  site  and  you  automatically  become  the
+     database  administrator  of  the database you just created.  Database names must  have  an  alphabetic  first
+     character and are limited to 16 characters in length.
+     Not  every  user has authorization to become a database
+     administrator.  If <ProductName>Postgres</ProductName> refuses to create databases
+     for you, then the site administrator needs to grant you
+     permission to  create  databases.   Consult  your  site
+     administrator if this occurs.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Accessing a Database</Title>
+
+<Para>
+     Once you have constructed a database, you can access it
+     by:
+
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+running the <ProductName>Postgres</ProductName>  terminal  monitor  programs  (
+        monitor  or  <Application>psql</Application>) which allows you to interactively
+        enter, edit, and execute <Acronym>SQL</Acronym> commands.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      writing a  C  program  using  the  LIBPQ  subroutine
+        library.   This  allows  you  to submit <Acronym>SQL</Acronym> commands
+        from C and get answers and status messages  back  to
+        your  program.   This interface is discussed further
+        in section ??.
+</Para>
+</ListItem>
+</ItemizedList>
+
+     You might want to start up <Application>psql</Application>, to try out  the  examples  in  this manual. It can be activated for the mydb
+     database by typing the command:
+<ProgramListing>
+% psql mydb
+</ProgramListing>
+
+     You will be greeted with the following message:
+<ProgramListing>
+Welcome to the Postgres interactive sql monitor:
+
+  type \? for help on slash commands
+  type \q to quit
+  type \g or terminate with semicolon to execute query
+You are currently connected to the database: mydb
+
+mydb=>
+</ProgramListing>
+</Para>
+
+<Para>
+This prompt indicates that the terminal monitor is listening  to you and that you can type <Acronym>SQL</Acronym> queries into a
+     workspace maintained by the terminal monitor.
+     The <Application>psql</Application> program responds to escape  codes  that  begin
+     with  the  backslash  character, "\".  For example, you
+     can get help on the syntax of various <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing:
+<ProgramListing>
+mydb=> \h
+</ProgramListing>
+
+     Once  you  have finished entering your queries into the
+     workspace, you can pass the contents of  the  workspace
+     to the <ProductName>Postgres</ProductName> server by typing:
+<ProgramListing>
+mydb=> \g
+</ProgramListing>
+
+     This  tells  the  server  to process the query.  If you
+     terminate your query with a semicolon, the  backslash-g is  not
+     necessary.   <Application>psql</Application> will automatically process semicolon terminated queries.
+     To read queries from a file,  say  myFile,  instead  of
+     entering them interactively, type:
+<ProgramListing>
+mydb=> \i fileName
+</ProgramListing>
+
+     To get out of <Application>psql</Application> and return to UNIX, type
+<ProgramListing>
+mydb=> \q
+</ProgramListing>
+
+     and  <Application>psql</Application>  will  quit  and  return  you to your command
+     shell. (For more escape codes, type backslash-h at  the  monitor
+     prompt.)
+     White  space  (i.e.,  spaces, tabs and newlines) may be
+     used freely in <Acronym>SQL</Acronym> queries.  Single-line comments  are  denoted  by
+     <Quote>--</Quote>.   Everything  after the dashes up to the end of the
+     line is ignored. Multiple-line comments, and comments within a line,
+     are denoted by <Quote>/* ... */</Quote>
+</Para>
+</Sect1>
+     
+<Sect1>
+<Title>Destroying a Database</Title>
+
+<Para>
+     If you are the database administrator for the  database
+     mydb,  you can destroy it using the following UNIX command:
+<ProgramListing>
+% destroydb mydb
+</ProgramListing>
+     This action physically removes all of  the  UNIX  files
+     associated  with  the database and cannot be undone, so
+     this should only be done with a  great  deal  of  forethought.
+</Para>
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..bd6dc001607cc40da2e89495f850e7e5d14727ac
--- /dev/null
+++ b/doc/src/sgml/start.sgml
@@ -0,0 +1,315 @@
+<Chapter>
+<Title>Getting Started</Title>
+
+<Abstract>
+<Para>
+How to begin work with <ProductName>Postgres</ProductName> for a new user.
+</Para>
+</Abstract>
+
+<Para>
+     Some  of the steps required to use <ProductName>Postgres</ProductName>
+     can be performed by any Postgres user, and some must be done by
+     the site database administrator.  This site administrator 
+     is the person who installed the  software,  created
+     the  database  directories  and  started the <Application>postmaster</Application>
+     process.  This person does not  have  to  be  the  UNIX
+     superuser (<Quote>root</Quote>)
+ or the computer system administrator; a person can install and use
+<ProductName>Postgres</ProductName> without any special accounts or privileges.
+</Para>
+
+<Para>
+If you are installing <ProductName>Postgres</ProductName> yourself, then
+refer to the Administrator's Guide for instructions on installation, and return
+to this guide when the installation is complete.
+</Para>
+
+<Para>
+     Throughout this manual, any examples  that  begin  with
+     the  character  <Quote>&percnt</Quote> are commands that should be typed
+     at the UNIX shell prompt.  Examples that begin with the
+     character <Quote>*</Quote> are commands in the Postgres query 
+     language, Postgres <Acronym>SQL</Acronym>.
+</Para>
+
+<Sect1>
+<Title>Setting Up Your Environment</Title>
+
+<Para>
+     This section discusses how to set up
+     your own environment  so  that  you  can  use  frontend
+     applications.  We assume <ProductName>Postgres</ProductName> has already been 
+     successfully installed and started; refer to the Administrator's Guide
+and the installation  notes
+     for how to install Postgres.
+</Para>
+
+<Para>
+<ProductName>Postgres</ProductName> is a client/server application. As a user,
+you only need access to the client portions of the installation (an example
+of a client application is the interactive monitor <Application>psql</Application>).
+     For simplicity,
+     we will assume that <ProductName>Postgres</ProductName> has been installed in  the
+     directory  <FileName>/usr/local/pgsql</FileName>.   Therefore, wherever
+     you see the directory <FileName>/usr/local/pgsql</FileName> you  should
+     substitute  the name of the directory where <ProductName>Postgres</ProductName> is
+     actually installed.
+     All <ProductName>Postgres</ProductName> commands are installed  in  the  directory
+     <FileName>/usr/local/pgsql/bin</FileName>.   Therefore,  you should add
+     this directory to your shell command path.  If you  use
+     a variant of the Berkeley C shell, such as csh or tcsh,
+     you would add
+<ProgramListing>
+% set path = ( /usr/local/pgsql/bin path )
+</ProgramListing>
+     in the <FileName>.login</FileName> file in your home directory.  If you  use
+     a  variant  of  the  Bourne  shell, such as sh, ksh, or
+     bash, then you would add
+<ProgramListing>
+% PATH=/usr/local/pgsql/bin PATH
+% export PATH
+</ProgramListing>
+     to the .profile file in your home directory.
+     From now on, we will assume that  you  have  added  the
+     <ProductName>Postgres</ProductName>  bin  directory to your path.  In addition, we
+     will make frequent reference to <Quote>setting a shell  
+     variable</Quote>  or  <Quote>setting an environment variable</Quote> throughout
+     this document.  If you did  not  fully  understand  the
+     last  paragraph  on  modifying  your  search  path, you
+     should consult the UNIX manual pages that describe your
+     shell before going any further.
+</Para>
+
+<Para>
+If your site administrator has not set things up in the
+default  way,  you may have some more work to do.  For example, if the database
+ server machine is a remote machine, you
+will need to set the <Acronym>PGHOST</Acronym> environment variable to the name
+of the database server machine.   The  environment  variable
+<Acronym>PGPORT</Acronym> may also have to be set.  The bottom line is this: if
+you try to start an application  program  and  it  complains
+that it cannot connect to the <Application>postmaster</Application>,
+ you should immediately consult your site administrator to make sure that your
+environment is properly set up.
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Starting the Interactive Monitor (psql)</Title>
+
+<Para>
+     Assuming that  your  site  administrator  has  properly
+     started  the  <Application>postmaster</Application>  process and authorized you to
+     use the database, you (as a user) may begin to start up
+     applications.   As previously mentioned, you should add
+     <FileName>/usr/local/pgsql/bin</FileName> to your  shell  search  path.
+     In  most  cases,  this  is all you should have to do in
+     terms of preparation.
+</Para>
+
+<Para>
+As of <ProductName>Postgres</ProductName> v6.3, two different styles of connections
+are supported. The site administrator will have chosen to allow TCP/IP network connections
+or will have restricted database access to local (same-machine) socket connections only.
+These choices become significant if you encounter problems in connecting to a database.
+</Para>
+
+<Para>
+     If  you get the following error message from a <ProductName>Postgres</ProductName>
+     command (such as <Application>psql</Application> or <Application>createdb</Application>):
+
+<ProgramListing>
+% psql template1
+Connection to database 'postgres' failed.
+connectDB() failed: Is the postmaster running and accepting connections
+    at 'UNIX Socket' on port '5432'?
+</ProgramListing>
+
+or
+
+<ProgramListing>
+% psql -h localhost template1
+Connection to database 'postgres' failed.
+connectDB() failed: Is the postmaster running and accepting TCP/IP
+    (with -i) connections at 'localhost' on port '5432'?
+</ProgramListing>
+
+     it is usually because (1) the <Application>postmaster</Application>  is  not  running,
+ or (2) you are attempting to connect to the wrong server host.
+     If you get the following error message:
+
+<ProgramListing>
+FATAL 1:Feb 17 23:19:55:process userid (2360) != database owner (268)
+</ProgramListing>
+
+     it means that the site administrator started the  <Application>postmaster</Application>
+  as  the  wrong user.  Tell him to restart it as
+     the <ProductName>Postgres</ProductName> superuser.
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Managing a Database</Title>
+
+<Para>
+     Now that <ProductName>Postgres</ProductName> is up and running we can create  some
+     databases  to  experiment  with.  Here, we describe the
+     basic commands for managing a database.
+</Para>
+
+<Para>
+Most <ProductName>Postgres</ProductName>
+applications assume that the database name, if not specified, is the same as the name on your computer
+account.
+</Para>
+
+<Para>
+If your database administrator has set up your account without database creation privileges,
+then she should have told you what the name of your database is. If this is the case, then you
+can skip the sections on creating and destroying databases.
+</Para>
+
+<Sect2>
+<Title>Creating a Database</Title>
+
+<Para>
+     Let's say you want to create  a  database  named  <Database>mydb</Database>.
+     You can do this with the following command:
+<ProgramListing>
+% createdb mydb
+</ProgramListing>
+</Para>
+
+<Para>
+If you do not have the privileges required to create a database, you will see
+the following:
+<ProgramListing>
+% createdb mydb
+WARN:user "your username" is not allowed to create/destroy databases
+createdb: database creation failed on mydb.
+</ProgramListing>
+</Para>
+
+<Para>
+     <ProductName>Postgres</ProductName>  allows  you to create any number of databases
+     at a  given  site  and  you  automatically  become  the
+     database  administrator  of  the database you just created.  Database names must  have  an  alphabetic  first
+     character and are limited to 32 characters in length.
+     Not  every  user has authorization to become a database
+     administrator.  If <ProductName>Postgres</ProductName> refuses to create databases
+     for you, then the site administrator needs to grant you
+     permission to  create  databases.   Consult  your  site
+     administrator if this occurs.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Accessing a Database</Title>
+
+<Para>
+     Once you have constructed a database, you can access it
+     by:
+
+<ItemizedList Mark="bullet" Spacing="compact">
+<ListItem>
+<Para>
+running the <ProductName>Postgres</ProductName>  terminal  monitor  programs  (e.g.
+        <Application>psql</Application>) which allows you to interactively
+        enter, edit, and execute <Acronym>SQL</Acronym> commands.
+</Para>
+</ListItem>
+<ListItem>
+<Para>
+      writing a <Acronym>C</Acronym>  program  using  the  LIBPQ  subroutine
+        library.   This  allows  you  to submit <Acronym>SQL</Acronym> commands
+        from <Acronym>C</Acronym> and get answers and status messages  back  to
+        your  program.   This interface is discussed further
+        in <XRef LinkEnd="PROGRAMMERS-GUIDE">.
+</Para>
+</ListItem>
+</ItemizedList>
+
+You might want to start up <Application>psql</Application>, to try out the examples in this manual.
+ It can be activated for the <Database>mydb</Database>
+     database by typing the command:
+<ProgramListing>
+% psql mydb
+</ProgramListing>
+
+     You will be greeted with the following message:
+<ProgramListing>
+Welcome to the POSTGRESQL interactive sql monitor:
+  Please read the file COPYRIGHT for copyright terms of POSTGRESQL
+
+   type \? for help on slash commands
+   type \q to quit
+   type \g or terminate with semicolon to execute query
+ You are currently connected to the database: template1
+
+mydb=>
+</ProgramListing>
+</Para>
+
+<Para>
+This prompt indicates that the terminal monitor is listening
+  to you and that you can type <Acronym>SQL</Acronym> queries into a
+     workspace maintained by the terminal monitor.
+     The <Application>psql</Application> program responds to escape  codes  that  begin
+     with  the  backslash  character, <Quote>\</Quote>  For example, you
+     can get help on the syntax of various
+ <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing:
+<ProgramListing>
+mydb=> \h
+</ProgramListing>
+
+     Once  you  have finished entering your queries into the
+     workspace, you can pass the contents of  the  workspace
+     to the <ProductName>Postgres</ProductName> server by typing:
+<ProgramListing>
+mydb=> \g
+</ProgramListing>
+
+     This  tells  the  server  to process the query.  If you
+     terminate your query with a semicolon, the  <Quote>\g</Quote> is  not
+     necessary.   <Application>psql</Application> will automatically process semicolon terminated queries.
+     To read queries from a file,  say  myFile,  instead  of
+     entering them interactively, type:
+<ProgramListing>
+mydb=> \i fileName
+</ProgramListing>
+
+     To get out of <Application>psql</Application> and return to UNIX, type
+<ProgramListing>
+mydb=> \q
+</ProgramListing>
+
+     and  <Application>psql</Application>  will  quit  and  return  you to your command
+     shell. (For more escape codes, type <Command>\h</Command> at  the  monitor
+     prompt.)
+     White  space  (i.e.,  spaces, tabs and newlines) may be
+     used freely in <Acronym>SQL</Acronym> queries.  Single-line comments  are  denoted  by
+     <Quote>--</Quote>.   Everything  after the dashes up to the end of the
+     line is ignored. Multiple-line comments, and comments within a line,
+     are denoted by <Quote>/* ... */</Quote>
+</Para>
+</Sect2>
+     
+<Sect2>
+<Title>Destroying a Database</Title>
+
+<Para>
+     If you are the database administrator for the  database
+     <Database>mydb</Database>,  you can destroy it using the following UNIX command:
+<ProgramListing>
+% destroydb mydb
+</ProgramListing>
+     This action physically removes all of  the  UNIX  files
+     associated  with  the database and cannot be undone, so
+     this should only be done with a  great  deal  of  forethought.
+</Para>
+</Sect2>
+</Sect1>
+
+</Chapter>
diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..7a0495e22704baf4bdfb285cb40b1ee3e3c67683
--- /dev/null
+++ b/doc/src/sgml/storage.sgml
@@ -0,0 +1,9 @@
+<Chapter>
+<Title>Disk Storage</Title>
+
+<Para>
+This section needs to be written. Some information is in the FAQ. Volunteers?
+- thomas 1998-01-11
+</Para>
+
+</Chapter>
diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..b8b7fc12ab318727dc4098d9fe2c241ef0ddbcf4
--- /dev/null
+++ b/doc/src/sgml/trigger.sgml
@@ -0,0 +1,396 @@
+<Chapter>
+<Title>Triggers</Title>
+
+<Para>
+   While the current version of <ProductName>Postgres</ProductName> has various client interfaces
+such as Perl, Tcl, Python and C, it lacks an actual <FirstTerm>Procedural Language</FirstTerm>
+(PL).  We hope to have a proper PL one day.  In the meantime it is possible
+to call C functions as trigger actions.  Note that STATEMENT-level trigger
+events are not supported in the current version.  You can currently specify
+BEFORE or AFTER on INSERT, DELETE or UPDATE of a tuple as a trigger event.
+</Para>
+
+<Sect1>
+<Title>Trigger Creation</Title>
+
+<Para>
+   If a trigger event occurs, the trigger manager (called by the Executor)
+initializes the global structure TriggerData *CurrentTriggerData (described
+below) and calls the trigger function to handle the event.
+</Para>
+
+<Para>
+   The trigger function must be created before the trigger is created as a
+function taking no arguments and returns opaque.
+</Para>
+
+<Para>
+   The syntax for creating triggers is as follows:
+
+<ProgramListing>
+   CREATE TRIGGER &lt;trigger name&gt; &lt;BEFORE|AFTER&gt; &lt;INSERT|DELETE|UPDATE&gt;
+       ON &lt;relation name&gt; FOR EACH &lt;ROW|STATEMENT&gt;
+       EXECUTE PROCEDURE &lt;procedure name&gt; (&lt;function args&gt;);
+</ProgramListing>
+</Para>
+
+<Para>
+   The name of the trigger is used if you ever have to delete the trigger.
+It is used as an argument to the DROP TRIGGER command.
+</Para>
+
+<Para>
+   The next word determines whether the function is called before or after
+the event.
+</Para>
+
+<Para>
+   The next element of the command determines on what event(s) will trigger
+the function.  Multiple events can be specified separated by OR.
+</Para>
+
+<Para>
+   The relation name determines which table the event applies to.
+</Para>
+
+<Para>
+   The FOR EACH statement determines whether the trigger is fired for each
+affected row or before (or after) the entire statement has completed.
+</Para>
+
+<Para>
+   The procedure name is the C function called.
+</Para>
+
+<Para>
+   The args are passed to the function in the CurrentTriggerData structure.
+The purpose of passing arguments to the function is to allow different
+triggers with similar requirements to call the same function.
+</Para>
+
+<Para>
+   Also, function may be used for triggering different relations (these
+functions are named as "general trigger functions").
+</Para>
+
+<Para>
+   As example of using both features above, there could be a general
+function that takes as its arguments two field names and puts the current
+user in one and the current timestamp in the other. This allows triggers to
+be written on INSERT events to automatically track creation of records in a
+transaction table for example. It could also be used as a "last updated"
+function if used in an UPDATE event.
+</Para>
+
+<Para>
+   Trigger functions return HeapTuple to the calling Executor.  This
+is ignored for triggers fired after an INSERT, DELETE or UPDATE operation
+but it allows BEFORE triggers to:
+
+   - return NULL to skip the operation for the current tuple (and so the
+     tuple will not be inserted/updated/deleted);
+   - return a pointer to another tuple (INSERT and UPDATE only) which will
+     be inserted (as the new version of the updated tuple if UPDATE) instead
+     of original tuple.
+</Para>
+
+<Para>
+   Note, that there is no initialization performed by the CREATE TRIGGER
+handler.  This will be changed in the future.  Also, if more than one trigger
+is defined for the same event on the same relation, the order of trigger
+firing is unpredictable. This may be changed in the future.
+</Para>
+
+<Para>
+   If a trigger function executes SQL-queries (using SPI) then these queries
+may fire triggers again. This is known as cascading triggers.  There is no
+explicit limitation on the number of cascade levels.
+</Para>
+
+<Para>
+   If a trigger is fired by INSERT and inserts a new tuple in the same
+relation then this trigger will be fired again.  Currently, there is nothing
+provided for synchronization (etc) of these cases but this may change.  At
+the moment, there is function funny_dup17() in the regress tests which uses
+some techniques to stop recursion (cascading) on itself...
+</Para>
+
+</Sect1>
+
+<Sect1>
+<Title>Interaction with the Trigger Manager</Title>
+
+<Para>
+   As mentioned above, when function is called by the trigger manager,
+structure TriggerData *CurrentTriggerData is NOT NULL and initialized.  So
+it is better to check CurrentTriggerData against being NULL at the start
+and set it to NULL just after fetching the information to prevent calls to
+a trigger function not from the trigger manager.
+</Para>
+
+<Para>
+   struct TriggerData is defined in src/include/commands/trigger.h:
+
+<ProgramListing>
+typedef struct TriggerData
+{
+	TriggerEvent	tg_event;
+	Relation	tg_relation;
+	HeapTuple	tg_trigtuple;
+	HeapTuple	tg_newtuple;
+	Trigger		*tg_trigger;
+} TriggerData;
+</ProgramListing>
+
+<ProgramListing>
+tg_event 
+   describes event for which the function is called. You may use the
+   following macros to examine tg_event:
+
+   TRIGGER_FIRED_BEFORE(event) returns TRUE if trigger fired BEFORE;
+   TRIGGER_FIRED_AFTER(event) returns TRUE if trigger fired AFTER;
+   TRIGGER_FIRED_FOR_ROW(event) returns TRUE if trigger fired for
+                                ROW-level event;
+   TRIGGER_FIRED_FOR_STATEMENT(event) returns TRUE if trigger fired for
+                                STATEMENT-level event;
+   TRIGGER_FIRED_BY_INSERT(event) returns TRUE if trigger fired by INSERT;
+   TRIGGER_FIRED_BY_DELETE(event) returns TRUE if trigger fired by DELETE;
+   TRIGGER_FIRED_BY_UPDATE(event) returns TRUE if trigger fired by UPDATE.
+
+tg_relation
+   is pointer to structure describing the triggered relation. Look at
+   src/include/utils/rel.h for details about this structure.  The most
+   interest things are tg_relation->rd_att (descriptor of the relation
+   tuples) and tg_relation->rd_rel->relname (relation's name. This is not
+   char*, but NameData.  Use SPI_getrelname(tg_relation) to get char* if
+   you need a copy of name).
+
+tg_trigtuple
+   is a pointer to the tuple for which the trigger is fired. This is the tuple
+   being inserted (if INSERT), deleted (if DELETE) or updated (if UPDATE).
+   If INSERT/DELETE then this is what you are to return to Executor if 
+   you don't want to replace tuple with another one (INSERT) or skip the
+   operation.
+
+tg_newtuple
+   is a pointer to the new version of tuple if UPDATE and NULL if this is
+   for an INSERT or a DELETE. This is what you are to return to Executor if
+   UPDATE and you don't want to replace this tuple with another one or skip
+   the operation.
+
+tg_trigger
+   is pointer to structure Trigger defined in src/include/utils/rel.h:
+
+typedef struct Trigger
+{
+	char		*tgname;
+	Oid		tgfoid;
+	func_ptr	tgfunc;
+	int16		tgtype;
+	int16		tgnargs;
+	int16		tgattr[8];
+	char		**tgargs;
+} Trigger;
+
+   tgname is the trigger's name, tgnargs is number of arguments in tgargs,
+   tgargs is an array of pointers to the arguments specified in the CREATE
+   TRIGGER statement. Other members are for internal use only.
+</ProgramListing>
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Visibility of Data Changes</Title>
+
+<Para>
+   <ProductName>Postgres</ProductName> data changes visibility rule: during a query execution, data
+changes made by the query itself (via SQL-function, SPI-function, triggers)
+are invisible to the query scan.  For example, in query
+
+<ProgramListing>
+   INSERT INTO a SELECT * FROM a
+</ProgramListing>
+
+   tuples inserted are invisible for SELECT' scan.  In effect, this
+duplicates the database table within itself (subject to unique index
+rules, of course) without recursing.
+</Para>
+
+<Para>
+   But keep in mind this notice about visibility in the SPI documentation:
+
+<ProgramListing>
+   Changes made by query Q are visible by queries which are started after
+   query Q, no matter whether they are started inside Q (during the
+   execution of Q) or after Q is done.
+</ProgramListing>
+</Para>
+
+<Para>
+   This is true for triggers as well so, though a tuple being inserted
+(tg_trigtuple) is not visible to queries in a BEFORE trigger, this tuple
+(just inserted) is visible to queries in an AFTER trigger, and to queries
+in BEFORE/AFTER triggers fired after this!
+</Para>
+</Sect1>
+
+<Sect1>
+<Title>Examples</Title>
+
+<Para>
+   There are more complex examples in in src/test/regress/regress.c and
+in contrib/spi.
+</Para>
+
+<Para>
+   Here is a very simple example of trigger usage.  Function trigf reports
+the number of tuples in the triggered relation ttest and skips the
+operation if the query attempts to insert NULL into x (i.e - it acts as a
+NOT NULL constraint but doesn't abort the transaction).
+
+<ProgramListing>
+#include "executor/spi.h"	/* this is what you need to work with SPI */
+#include "commands/trigger.h"	/* -"- and triggers */
+
+HeapTuple		trigf(void);
+
+HeapTuple
+trigf()
+{
+	TupleDesc	tupdesc;
+	HeapTuple	rettuple;
+	char		*when;
+	bool		checknull = false;
+	bool		isnull;
+	int		ret, i;
+
+	if (!CurrentTriggerData)
+		elog(WARN, "trigf: triggers are not initialized");
+	
+	/* tuple to return to Executor */
+	if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
+		rettuple = CurrentTriggerData->tg_newtuple;
+	else
+		rettuple = CurrentTriggerData->tg_trigtuple;
+	
+	/* check for NULLs ? */
+	if (!TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event) &&
+		TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
+		checknull = true;
+	
+	if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
+		when = "before";
+	else
+		when = "after ";
+	
+	tupdesc = CurrentTriggerData->tg_relation->rd_att;
+	CurrentTriggerData = NULL;
+	
+	/* Connect to SPI manager */
+	if ((ret = SPI_connect()) < 0)
+		elog(WARN, "trigf (fired %s): SPI_connect returned %d", when, ret);
+	
+	/* Get number of tuples in relation */
+	ret = SPI_exec("select count(*) from ttest", 0);
+	
+	if (ret < 0)
+		elog(WARN, "trigf (fired %s): SPI_exec returned %d", when, ret);
+	
+	i = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &amp;isnull);
+	
+	elog (NOTICE, "trigf (fired %s): there are %d tuples in ttest", when, i);
+	
+	SPI_finish();
+	
+	if (checknull)
+	{
+		i = SPI_getbinval(rettuple, tupdesc, 1, &amp;isnull);
+		if (isnull)
+			rettuple = NULL;
+	}
+
+	return (rettuple);
+}
+</ProgramListing>
+</Para>
+
+<Para>
+   Now, compile and 
+create table ttest (x int4);
+create function trigf () returns opaque as 
+'...path_to_so' language 'c';
+
+<ProgramListing>
+vac=> create trigger tbefore before insert or update or delete on ttest 
+for each row execute procedure trigf();
+CREATE
+vac=> create trigger tafter after insert or update or delete on ttest 
+for each row execute procedure trigf();
+CREATE
+vac=> insert into ttest values (null);
+NOTICE:trigf (fired before): there are 0 tuples in ttest
+INSERT 0 0
+
+-- Insertion skipped and AFTER trigger is not fired
+
+vac=> select * from ttest;
+x
+-
+(0 rows)
+
+vac=> insert into ttest values (1);
+NOTICE:trigf (fired before): there are 0 tuples in ttest
+NOTICE:trigf (fired after ): there are 1 tuples in ttest
+                                       ^^^^^^^^
+                             remember what we said about visibility.
+INSERT 167793 1
+vac=> select * from ttest;
+x
+-
+1
+(1 row)
+
+vac=> insert into ttest select x * 2 from ttest;
+NOTICE:trigf (fired before): there are 1 tuples in ttest
+NOTICE:trigf (fired after ): there are 2 tuples in ttest
+                                       ^^^^^^^^
+                             remember what we said about visibility.
+INSERT 167794 1
+vac=> select * from ttest;
+x
+-
+1
+2
+(2 rows)
+
+vac=> update ttest set x = null where x = 2;
+NOTICE:trigf (fired before): there are 2 tuples in ttest
+UPDATE 0
+vac=> update ttest set x = 4 where x = 2;
+NOTICE:trigf (fired before): there are 2 tuples in ttest
+NOTICE:trigf (fired after ): there are 2 tuples in ttest
+UPDATE 1
+vac=> select * from ttest;
+x
+-
+1
+4
+(2 rows)
+
+vac=> delete from ttest;
+NOTICE:trigf (fired before): there are 2 tuples in ttest
+NOTICE:trigf (fired after ): there are 1 tuples in ttest
+NOTICE:trigf (fired before): there are 1 tuples in ttest
+NOTICE:trigf (fired after ): there are 0 tuples in ttest
+                                       ^^^^^^^^
+                             remember what we said about visibility.
+DELETE 2
+vac=> select * from ttest;
+x
+-
+(0 rows)
+</ProgramListing>
+
+</Para>
+</Sect1>
+</Chapter>
diff --git a/doc/src/sgml/tutorial.sgml b/doc/src/sgml/tutorial.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..6ff48eb750ea508e9826dfadfe180961fe3cdeab
--- /dev/null
+++ b/doc/src/sgml/tutorial.sgml
@@ -0,0 +1,94 @@
+<!-- tutorial.sgml
+-
+- Postgres tutorial. Derived from postgres.sgml.
+- thomas 1998-02-23
+-
+- -->
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!entity intro    SYSTEM "intro.sgml">
+<!entity arch     SYSTEM "arch.sgml">
+<!entity start    SYSTEM "start.sgml">
+<!entity query    SYSTEM "query.sgml">
+<!entity advanced SYSTEM "advanced.sgml">
+<!entity biblio   SYSTEM "biblio.sgml">
+]>
+<Book>
+
+<!-- Title information -->
+
+<Title>PostgreSQL Tutorial</Title>
+<BookInfo>
+    <ReleaseInfo>Covering v6.3 for general release</ReleaseInfo>
+    <BookBiblio>
+    <AuthorGroup>
+      <CorpAuthor>The PostgreSQL Development Team</CorpAuthor>
+    </AuthorGroup>
+<!-- editor in authorgroup is not supported
+    <AuthorGroup>
+-->
+      <Editor>
+        <FirstName>Thomas</FirstName>
+        <SurName>Lockhart</SurName>
+        <Affiliation>
+          <OrgName>Caltech/JPL</OrgName>
+        </Affiliation>
+      </Editor>
+<!--
+    </AuthorGroup>
+-->
+ 
+<!--
+    <AuthorInitials>TGL</AuthorInitials>
+-->
+
+    <Date>(last updated 1998-02-23)</Date>
+    </BookBiblio>
+
+<LegalNotice>
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group.
+</Para>
+</LegalNotice>
+
+</BookInfo>
+
+<!--
+<TOC> </TOC>
+<LOT> </LOT>
+-->
+
+<!--
+<Dedication>
+<Para>
+Your name here...
+</Para>
+</Dedication>
+-->
+
+<Preface>
+<Title>Summary</Title>
+
+<Para>
+<ProductName>Postgres</ProductName>, 
+ developed originally in the UC Berkeley Computer Science Department,
+ pioneered many of the object-relational concepts
+ now becoming available in some commercial databases.
+It provides SQL92/SQL3 language support,
+ transaction integrity, and type extensibility.
+ <ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant
+ of this original Berkeley code.
+</Para>
+</Preface>
+
+&intro;
+&arch;
+&start;
+&query;
+&advanced;
+
+&biblio;
+
+<INDEX> </INDEX>
+
+</Book>
+
diff --git a/doc/src/sgml/user.sgml b/doc/src/sgml/user.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..151dd84b54e552bd9868e609ded9d8fc71260b7a
--- /dev/null
+++ b/doc/src/sgml/user.sgml
@@ -0,0 +1,110 @@
+<!-- user.sgml
+-
+- Postgres User's Manual.
+- Derived from postgres.sgml.
+- thomas 1998-02-24
+-
+- -->
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!entity intro    SYSTEM "intro.sgml">
+<!entity advanced SYSTEM "advanced.sgml">
+<!entity environ  SYSTEM "environ.sgml">
+<!entity manage   SYSTEM "manage.sgml">
+<!entity datatype SYSTEM "datatype.sgml">
+<!entity array    SYSTEM "array.sgml">
+<!entity inherit  SYSTEM "inherit.sgml">
+<!entity query-ug SYSTEM "query-ug.sgml">
+<!entity storage  SYSTEM "storage.sgml">
+<!entity psql     SYSTEM "psql.sgml">
+<!entity pgaccess SYSTEM "pgaccess.sgml">
+<!entity biblio   SYSTEM "biblio.sgml">
+]>
+<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc -->
+<Book>
+
+<!-- Title information -->
+
+<Title>PostgreSQL User's Guide</Title>
+<BookInfo>
+    <ReleaseInfo>Covering v6.3 for general release</ReleaseInfo>
+    <BookBiblio>
+    <AuthorGroup>
+      <CorpAuthor>The PostgreSQL Development Team</CorpAuthor>
+    </AuthorGroup>
+<!-- editor in authorgroup is not supported
+    <AuthorGroup>
+-->
+      <Editor>
+        <FirstName>Thomas</FirstName>
+        <SurName>Lockhart</SurName>
+        <Affiliation>
+          <OrgName>Caltech/JPL</OrgName>
+        </Affiliation>
+      </Editor>
+<!--
+    </AuthorGroup>
+-->
+ 
+<!--
+    <AuthorInitials>TGL</AuthorInitials>
+-->
+
+    <Date>(last updated 1998-02-23)</Date>
+    </BookBiblio>
+
+<LegalNotice>
+<Para>
+<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group.
+</Para>
+</LegalNotice>
+
+</BookInfo>
+
+<!--
+<TOC> </TOC>
+<LOT> </LOT>
+-->
+
+<!--
+<Dedication>
+<Para>
+Your name here...
+</Para>
+</Dedication>
+-->
+
+<Preface>
+<Title>Summary</Title>
+
+<Para>
+<ProductName>Postgres</ProductName>, 
+ developed originally in the UC Berkeley Computer Science Department,
+ pioneered many of the object-relational concepts
+ now becoming available in some commercial databases.
+It provides SQL92/SQL3 language support,
+ transaction integrity, and type extensibility.
+ <ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant
+ of this original Berkeley code.
+</Para>
+</Preface>
+
+&intro;
+&environ;
+&manage;
+&datatype;
+&array;
+&inherit;
+&query-ug;
+&storage;
+&psql;
+&pgaccess;
+
+<!--
+&contacts;
+-->
+&biblio;
+
+<INDEX> </INDEX>
+
+</Book>
+
diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..81df0a8577eb1bdfd7499d63564202adc31344c1
--- /dev/null
+++ b/doc/src/sgml/xaggr.sgml
@@ -0,0 +1,95 @@
+<Chapter>
+<Title>Extending <Acronym>SQL</Acronym>: Aggregates</Title>
+
+<Para>
+     Aggregates  in <ProductName>Postgres</ProductName> are expressed in terms of state
+     transition functions.  That is,  an  aggregate  can  be
+     defined  in terms of state that is modified whenever an
+     instance is processed.  Some state functions look at  a
+     particular value in the instance when computing the new
+     state (<Acronym>sfunc1</Acronym> in the  create  aggregate  syntax)  while
+     others  only  keep  track  of  their own internal state
+     (<Acronym>sfunc2</Acronym>).
+     If we define an aggregate that  uses  only  <Acronym>sfunc1</Acronym>,  we
+     define an aggregate that computes a running function of
+     the attribute values from each instance.  "Sum"  is  an
+     example  of  this  kind  of aggregate.  "Sum" starts at
+     zero and always adds the current  instance's  value  to
+     its  running  total.   We  will  use the <Acronym>int4pl</Acronym> that is
+     built into <ProductName>Postgres</ProductName> to perform this addition.
+     
+<ProgramListing>
+         CREATE AGGREGATE complex_sum (
+              sfunc1 = complex_add,
+              basetype = complex,
+              stype1 = complex,
+              initcond1 = '(0,0)'
+           );
+
+         SELECT complex_sum(a) FROM test_complex;
+
+         +------------+
+         |complex_sum |
+         +------------+
+         |(34,53.9)   |
+         +------------+
+</ProgramListing>
+</Para>
+
+<Para>
+     If we define only <Acronym>sfunc2</Acronym>, we are specifying  an  aggregate  
+     that computes a running function that is independent  of  
+     the  attribute  values  from  each  instance.
+     "Count"  is  the  most  common  example of this kind of
+     aggregate.  "Count" starts at zero and adds one to  its
+     running  total for each instance, ignoring the instance
+     value.  Here, we use the built-in <Acronym>int4inc</Acronym> routine to do
+     the work for us.  This routine increments (adds one to)
+     its argument.
+     
+<ProgramListing>
+         CREATE AGGREGATE my_count (sfunc2 = int4inc, -- add one
+                                      basetype = int4, stype2 = int4,
+                                      initcond2 = '0')
+
+         SELECT my_count(*) as emp_count from EMP;
+
+         +----------+
+         |emp_count |
+         +----------+
+         |5         |
+         +----------+
+</ProgramListing>
+</Para>
+         
+<Para>
+     "Average" is an example of an aggregate  that  requires
+     both  a function to compute the running sum and a function 
+     to compute the running count.   When  all  of  the
+     instances have been processed, the final answer for the
+     aggregate is the running sum  divided  by  the  running
+     count.   We use the <Acronym>int4pl</Acronym> and <Acronym>int4inc</Acronym> routines we used
+     before as well as the <ProductName>Postgres</ProductName>  integer  division  
+     routine,  <Acronym>int4div</Acronym>,  to  compute the division of the sum by
+     the count.
+     
+<ProgramListing>
+         CREATE AGGREGATE my_average (sfunc1 = int4pl, --  sum
+                                        basetype = int4,
+                                        stype1 = int4,
+                                        sfunc2 = int4inc, -- count
+                                        stype2 = int4,
+                                        finalfunc = int4div, -- division
+                                        initcond1 = '0',
+                                        initcond2 = '0')
+
+         SELECT my_average(salary) as emp_average FROM EMP;
+
+         +------------+
+         |emp_average |
+         +------------+
+         |1640        |
+         +------------+
+</ProgramListing>
+</Para>
+</Chapter>
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..f1275bbb462ff6d3dc50f21d015a1efa41765bb1
--- /dev/null
+++ b/doc/src/sgml/xfunc.sgml
@@ -0,0 +1,533 @@
+<Chapter>
+<Title>Extending <Acronym>SQL</Acronym>: Functions</Title>
+
+<Para>
+     As  it  turns  out,  part of defining a new type is the
+     definition of functions  that  describe  its  behavior.
+     Consequently,  while  it  is  possible  to define a new
+     function without defining a new type,  the  reverse  is
+     not  true.   We therefore describe how to add new functions 
+     to <ProductName>Postgres</ProductName> before  describing  how  to  add  new
+     types.
+     <ProductName>Postgres</ProductName>  <Acronym>SQL</Acronym>  provides  two  types of functions: query
+     language functions (functions written in <Acronym>SQL</Acronym>  and  
+     programming  language  functions  (functions  written in a
+     compiled programming language such as <Acronym>C</Acronym>.)  Either  kind
+     of  function  can take a base type, a composite type or
+     some combination as arguments (parameters).   In  addition, 
+     both kinds of functions can return a base type or
+     a composite type.  It's easier to define <Acronym>SQL</Acronym> functions,
+     so we'll start with those.
+     Examples in this section can also be found in <FileName>funcs.sql</FileName>
+     and <FileName>C-code/funcs.c</FileName>.
+</Para>
+
+<Sect1>
+<Title>Query Language (<Acronym>SQL</Acronym>) Functions</Title>
+
+<Sect2>
+<Title><Acronym>SQL</Acronym> Functions on Base Types</Title>
+
+<Para>
+     The simplest possible <Acronym>SQL</Acronym> function has no arguments and
+     simply returns a base type, such as <Acronym>int4</Acronym>:
+     
+<ProgramListing>
+    CREATE FUNCTION one() RETURNS int4
+     AS 'SELECT 1 as RESULT' LANGUAGE 'sql';
+
+    SELECT one() AS answer;
+
+         +-------+
+         |answer |
+         +-------+
+         |1      |
+         +-------+
+</ProgramListing>
+
+</Para>
+<Para>
+     Notice that we defined a target list for  the  function
+     (with  the  name  RESULT),  but  the target list of the
+     query that invoked the function overrode the function's
+     target  list.   Hence,  the  result  is labelled answer
+     instead of one.
+</Para>
+<Para>
+     It's almost as easy to define <Acronym>SQL</Acronym> functions  that  take
+     base  types as arguments.  In the example below, notice
+     how we refer to the arguments within the function as $1
+     and $2.
+     
+<ProgramListing>
+    CREATE FUNCTION add_em(int4, int4) RETURNS int4
+     AS 'SELECT $1 + $2;' LANGUAGE 'sql';
+
+    SELECT add_em(1, 2) AS answer;
+
+         +-------+
+         |answer |
+         +-------+
+         |3      |
+         +-------+
+</ProgramListing>
+</Para>
+
+<Sect2>
+<Title><Acronym>SQL</Acronym> Functions on Composite Types</Title>
+
+<Para>
+     When  specifying  functions with arguments of composite
+     types (such as EMP), we must  not  only  specify  which
+     argument  we  want (as we did above with $1 and $2) but
+     also the attributes of  that  argument.   For  example,
+     take the function double_salary that computes what your
+     salary would be if it were doubled.
+     
+<ProgramListing>
+    CREATE FUNCTION double_salary(EMP) RETURNS int4
+     AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql';
+
+    SELECT name, double_salary(EMP) AS dream
+     FROM EMP
+     WHERE EMP.dept = 'toy';
+
+         +-----+-------+
+         |name | dream |
+         +-----+-------+
+         |Sam  | 2400  |
+         +-----+-------+
+</ProgramListing>
+
+<Para>
+     Notice the use of the syntax $1.salary.
+     Before launching into the  subject  of  functions  that
+     return  composite  types,  we  must first introduce the
+     function notation for projecting attributes.  The  simple  way 
+     to explain this is that we can usually use the
+     notation attribute(class)  and  class.attribute  interchangably.
+     
+<ProgramListing>
+    --
+    -- this is the same as:
+    --  SELECT EMP.name AS youngster FROM EMP WHERE EMP.age &lt; 30
+    --
+    SELECT name(EMP) AS youngster
+     FROM EMP
+     WHERE age(EMP) &lt; 30;
+
+         +----------+
+         |youngster |
+         +----------+
+         |Sam       |
+         +----------+
+</ProgramListing>
+
+<Para>
+     As  we shall see, however, this is not always the case.
+     This function notation is important when we want to use
+     a  function that returns a single instance.  We do this
+     by assembling the entire instance within the  function,
+     attribute  by attribute.  This is an example of a function 
+     that returns a single EMP instance:
+     
+<ProgramListing>
+    CREATE FUNCTION new_emp() RETURNS EMP
+     AS 'SELECT \'None\'::text AS name,
+      1000 AS salary,
+      25 AS age,
+      \'none\'::char16 AS dept;'
+      LANGUAGE 'sql';
+</ProgramListing>
+
+</Para>
+<Para>
+     In this case we have specified each of  the  attributes
+     with  a  constant value, but any computation or expression 
+     could have been substituted for these constants.
+     Defining a function like this can be tricky.   Some  of
+     the more important caveats are as follows:
+     
+     
+<ItemizedList>
+<ListItem>
+<Para>
+The  target  list  order must be exactly the same as
+        that in which the attributes appear  in  the  CREATE
+        TABLE statement (or when you execute a .*  query).
+</Para>
+      <ListItem>
+<Para>
+You  must  typecast the expressions
+        (using ::) very carefully or you will see  the  following error:
+        
+<ProgramListing>
+            WARN::function declared to return type EMP does not retrieve (EMP.*)
+</ProgramListing>
+</Para>
+<ListItem>
+<Para>
+When calling a function that returns an instance, we
+        cannot retrieve the entire instance.  We must either
+        project an attribute out of the instance or pass the
+        entire instance into another function.
+<ProgramListing>
+    SELECT name(new_emp()) AS nobody;
+
+            +-------+
+            |nobody |
+            +-------+
+            |None   |
+            +-------+
+</ProgramListing>
+</Para>
+<ListItem>
+<Para>
+The reason why, in general, we must use the function
+        syntax  for projecting attributes of function return
+        values is that the parser  just  doesn't  understand
+        the  other (dot) syntax for projection when combined
+        with function calls.
+        
+<ProgramListing>
+            SELECT new_emp().name AS nobody;
+            WARN:parser: syntax error at or near "."
+</ProgramListing>
+</Para>
+</ItemizedList>
+     
+<Para>
+     Any collection of commands in the  <Acronym>SQL</Acronym>  query  language
+     can  be  packaged  together  and defined as a function.
+     The commands can include updates (i.e., <Acronym>insert</Acronym>,  <Acronym>update</Acronym>
+     and  <Acronym>delete</Acronym>)  as  well as <Acronym>select</Acronym> queries.  However, the
+     final command must be a <Acronym>select</Acronym> that returns whatever is
+     specified as the function's returntype.
+     
+<ProgramListing>
+    CREATE FUNCTION clean_EMP () RETURNS int4
+     AS 'DELETE FROM EMP WHERE EMP.salary &lt;= 0;
+    SELECT 1 AS ignore_this'
+     LANGUAGE 'sql';
+
+    SELECT clean_EMP();
+
+         +--+
+         |x |
+         +--+
+         |1 |
+         +--+
+</ProgramListing>
+</Para>
+
+<Sect1>
+<Title>Programming Language Functions</Title>
+
+<Sect2>
+<Title>Programming Language Functions on Base Types</Title>
+
+<Para>
+     Internally, <ProductName>Postgres</ProductName> regards a base type as a "blob  of
+     memory."   The  user-defined  functions that you define
+     over a type in turn define the way  that  <ProductName>Postgres</ProductName>  can
+     operate  on  it.  That is, <ProductName>Postgres</ProductName> will only store and
+     retrieve the data from disk and use  your  user-defined
+     functions to input, process, and output the data.
+     Base types can have one of three internal formats:
+<ItemizedList>
+<ListItem><Para>pass by value, fixed-length</Para>
+<ListItem><Para>pass by reference, fixed-length</Para>
+<ListItem><Para>pass by reference, variable-length</Para>
+</ItemizedList>
+</Para>
+
+<Para>
+     By-value  types  can  only be 1, 2 or 4 bytes in length
+     (even if your computer supports by-value types of other
+     sizes).   <ProductName>Postgres</ProductName>  itself only passes integer types by
+     value.  You should be careful to define your types such
+     that  they  will  be  the  same  size (in bytes) on all
+     architectures.  For example, the <Acronym>long</Acronym> type is dangerous
+     because  it  is 4 bytes on some machines and 8 bytes on
+     others, whereas <Acronym>int</Acronym>  type  is  4  bytes  on  most  <Acronym>UNIX</Acronym>
+     machines  (though  not  on most personal computers).  A
+     reasonable implementation of  the  <Acronym>int4</Acronym>  type  on  <Acronym>UNIX</Acronym>
+     machines might be:
+     
+<ProgramListing>
+    /* 4-byte integer, passed by value */
+    typedef int int4;
+</ProgramListing>
+</Para>
+
+<Para>
+     On  the  other hand, fixed-length types of any size may
+     be passed by-reference.  For example, here is a  sample
+     implementation of the <ProductName>Postgres</ProductName> char16 type:
+     
+<ProgramListing>
+         /* 16-byte structure, passed by reference */
+         typedef struct {
+             char data[16];
+         } char16;
+</ProgramListing>
+</Para>
+
+<Para>
+     Only  pointers  to  such types can be used when passing
+     them in and out of <ProductName>Postgres</ProductName> functions.
+     Finally, all variable-length types must also be  passed
+     by  reference.   All  variable-length  types must begin
+     with a length field of exactly 4 bytes, and all data to
+     be  stored within that type must be located in the memory 
+     immediately  following  that  length  field.   The
+     length  field  is  the  total  length  of the structure
+     (i.e.,  it  includes  the  size  of  the  length  field
+     itself).  We can define the text type as follows:
+</Para>
+
+<Para>
+<ProgramListing>
+         typedef struct {
+             int4 length;
+             char data[1];
+         } text;
+</ProgramListing>
+</Para>
+
+<Para>
+     Obviously,  the  data  field is not long enough to hold
+     all possible strings -- it's impossible to declare such
+     a  structure  in  <Acronym>C</Acronym>.  When manipulating variable-length
+     types, we must  be  careful  to  allocate  the  correct
+     amount  of memory and initialize the length field.  For
+     example, if we wanted to  store  40  bytes  in  a  text
+     structure, we might use a code fragment like this:
+<ProgramListing>
+         #include "postgres.h"
+         #include "utils/palloc.h"
+         ...
+         char buffer[40]; /* our source data */
+         ...
+         text *destination = (text *) palloc(VARHDRSZ + 40);
+         destination-&gt;length = VARHDRSZ + 40;
+         memmove(destination-&gt;data, buffer, 40);
+         ...
+</ProgramListing>
+</Para>
+
+<Para>
+     Now that we've gone over all of the possible structures
+     for base types, we can show some examples of real functions. 
+     Suppose <FileName>funcs.c</FileName> look like:
+<ProgramListing>
+         #include &lt;string.h&gt;
+         #include "postgres.h"  /* for char16, etc. */
+         #include "utils/palloc.h" /* for palloc */
+         int
+         add_one(int arg)
+         {
+             return(arg + 1);
+         }
+         char16 *
+         concat16(char16 *arg1, char16 *arg2)
+         {
+             char16 *new_c16 = (char16 *) palloc(sizeof(char16));
+             memset((void *) new_c16, 0, sizeof(char16));
+             (void) strncpy(new_c16, arg1, 16);
+             return (char16 *)(strncat(new_c16, arg2, 16));
+         }
+         text *
+         copytext(text *t)
+         {
+             /*
+              * VARSIZE is the total size of the struct in bytes.
+              */
+             text *new_t = (text *) palloc(VARSIZE(t));
+             memset(new_t, 0, VARSIZE(t));
+             VARSIZE(new_t) = VARSIZE(t);
+             /*
+              * VARDATA is a pointer to the data region of the struct.
+              */
+             memcpy((void *) VARDATA(new_t), /* destination */
+                    (void *) VARDATA(t),     /* source */
+                    VARSIZE(t)-VARHDRSZ);        /* how many bytes */
+             return(new_t);
+         }
+</ProgramListing>
+</Para>
+
+<Para>
+     On <Acronym>OSF/1</Acronym> we would type:
+     
+<ProgramListing>
+         CREATE FUNCTION add_one(int4) RETURNS int4
+              AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c';
+
+         CREATE FUNCTION concat16(char16, char16) RETURNS char16
+              AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c';
+
+         CREATE FUNCTION copytext(text) RETURNS text
+              AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c';
+</ProgramListing>
+</Para>
+
+<Para>
+     On  other  systems,  we might have to make the filename
+     end in .sl (to indicate that it's a shared library).
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Programming Language Functions on Composite Types</Title>
+
+<Para>
+     Composite types do not  have  a  fixed  layout  like  C
+     structures.   Instances of a composite type may contain
+     null fields.  In addition,  composite  types  that  are
+     part  of  an  inheritance  hierarchy may have different
+     fields than other members of the same inheritance hierarchy.    
+     Therefore,  <ProductName>Postgres</ProductName>  provides  a  procedural
+     interface for accessing fields of composite types  from
+     C.
+     As <ProductName>Postgres</ProductName> processes a set of instances, each instance
+     will be passed into your function as an  opaque  structure of type <Acronym>TUPLE</Acronym>.
+     Suppose we want to write a function to answer the query
+<ProgramListing>
+         * SELECT name, c_overpaid(EMP, 1500) AS overpaid
+           FROM EMP
+           WHERE name = 'Bill' or name = 'Sam';
+</ProgramListing>
+     In the query above, we can define c_overpaid as:
+     
+<ProgramListing>
+         #include "postgres.h"  /* for char16, etc. */
+         #include "libpq-fe.h" /* for TUPLE */
+         bool
+         c_overpaid(TUPLE t,/* the current instance of EMP */
+                    int4 limit)
+         {
+             bool isnull = false;
+             int4 salary;
+             salary = (int4) GetAttributeByName(t, "salary", &amp;isnull);
+             if (isnull)
+                 return (false);
+             return(salary &gt; limit);
+         }
+</ProgramListing>
+</Para>
+
+<Para>
+     <Acronym>GetAttributeByName</Acronym> is the <ProductName>Postgres</ProductName> system function that
+     returns attributes out of the current instance.  It has
+     three arguments: the argument of type TUPLE passed into
+     the  function, the name of the desired attribute, and a
+     return parameter that describes whether  the  attribute
+     is  null.   <Acronym>GetAttributeByName</Acronym> will align data properly
+     so you can cast its return value to the  desired  type.
+     For  example, if you have an attribute name which is of
+     the type char16, the <Acronym>GetAttributeByName</Acronym> call would look
+     like:
+<ProgramListing>
+         char *str;
+         ...
+         str = (char *) GetAttributeByName(t, "name", &amp;isnull)
+</ProgramListing>
+</Para>
+
+<Para>
+     The  following  query  lets  <ProductName>Postgres</ProductName>  know  about  the
+     c_overpaid function:
+<ProgramListing>
+         * CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool
+              AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c';
+</ProgramListing>
+</Para>
+
+<Para>
+     While there are ways to construct new instances or modify  
+     existing instances from within a C function, these
+     are far too complex to discuss in this manual.
+</Para>
+</Sect2>
+
+<Sect2>
+<Title>Caveats</Title>
+
+<Para>
+     We now turn to the more difficult task of writing  
+     programming  language  functions.  Be warned: this section
+     of the manual will not make you a programmer.  You must
+     have  a  good  understanding of <Acronym>C</Acronym> (including the use of
+     pointers and the malloc memory manager)  before  trying
+     to write <Acronym>C</Acronym> functions for use with <ProductName>Postgres</ProductName>.
+     While  it  may be possible to load functions written in
+     languages other than <Acronym>C</Acronym> into  <ProductName>Postgres</ProductName>,  this  is  often
+     difficult  (when  it  is possible at all) because other
+     languages, such as <Acronym>FORTRAN</Acronym> and <Acronym>Pascal</Acronym> often do not follow 
+     the same "calling convention" as <Acronym>C</Acronym>.  That is, other
+     languages  do  not  pass  argument  and  return  values
+     between functions in the same way.  For this reason, we
+     will assume that your  programming  language  functions
+     are written in <Acronym>C</Acronym>.
+     The  basic  rules  for building <Acronym>C</Acronym> functions are as follows:
+
+<ItemizedList>
+<ListItem>
+<Para>
+Most of the header (include) files for  <ProductName>Postgres</ProductName>
+            should      already      be     installed     in
+            <FileName>PGROOT/include</FileName>  (see  Figure  2).
+            You should always include
+            
+<ProgramListing>
+                -I$PGROOT/include
+</ProgramListing>
+            on  your  cc  command lines.  Sometimes, you may
+            find that you require header files that  are  in
+            the  server source itself (i.e., you need a file
+            we neglected to install in include).   In  those
+            cases you may need to add one or more of
+<ProgramListing>
+                -I$PGROOT/src/backend
+                -I$PGROOT/src/backend/include
+                -I$PGROOT/src/backend/port/&lt;PORTNAME&gt;
+                -I$PGROOT/src/backend/obj
+</ProgramListing>
+            (where &lt;PORTNAME&gt; is the name of the port, e.g.,
+            alpha or sparc).
+</ListItem>
+<ListItem>
+<Para>   When allocating memory, use  the  <ProductName>Postgres</ProductName>  
+            routines  palloc  and  pfree  instead of the 
+            corresponding <Acronym>C</Acronym> library  routines  malloc  and  free.
+            The  memory  allocated  by  palloc will be freed
+            automatically at the end  of  each  transaction,
+            preventing memory leaks.
+</Para>
+      <ListItem>
+<Para>   Always  zero  the bytes of your structures using
+            memset or bzero.  Several routines (such as  the
+            hash access method, hash join and the sort algorithm) 
+            compute functions of the  raw  bits  contained  in 
+            your structure.  Even if you initialize all fields 
+            of your structure, there  may  be
+            several bytes of alignment padding (holes in the
+            structure) that may contain garbage values.
+</Para>
+      <ListItem>
+<Para>   Most of the internal <ProductName>Postgres</ProductName> types are declared
+            in  postgres.h,  so  it's usually a good idea to
+            include that file as well.
+</Para>
+      <ListItem>
+<Para>   Compiling and loading your object code  so  that
+            it  can  be  dynamically  loaded  into  <ProductName>Postgres</ProductName>
+            always requires special flags.  See  Appendix  A
+            for  a  detailed explanation of how to do it for
+            your particular operating system.
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+</Sect2>
diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..b77af369e6a2ba6bb6998bc79dda18663cd28a00
--- /dev/null
+++ b/doc/src/sgml/xindex.sgml
@@ -0,0 +1,515 @@
+<Chapter>
+<Title>Interfacing Extensions To Indices</Title>
+
+<Para>
+     The procedures described thus far let you define a  new
+     type,  new  functions  and  new operators.  However, we
+     cannot yet define a secondary index (such as a  <Acronym>B-tree</Acronym>,
+     <Acronym>R-tree</Acronym>  or  hash  access method) over a new type or its
+     operators.
+</Para>
+
+<Para>
+     Look back at
+<XRef LinkEnd="EXTEND-CATALOGS" EndTerm="EXTEND-CATALOGS">.
+     The right half shows the  catalogs  
+     that we must modify in order to tell <ProductName>Postgres</ProductName> how
+     to use a user-defined type and/or  user-defined  operators 
+     with an index (i.e., <FileName>pg_am, pg_amop, pg_amproc</FileName> and
+     <FileName>pg_opclass</FileName>).  Unfortunately, there is no simple command
+     to  do  this.   We will demonstrate how to modify these
+     catalogs through a  running  example:  a  new  operator
+     class  for the <Acronym>B-tree</Acronym> access method that sorts integers
+     in ascending absolute value order.
+</Para>
+
+<Para>
+     The <FileName>pg_am</FileName> class contains one instance for  every  user
+     defined  access  method.   Support  for the heap access
+     method is built into <ProductName>Postgres</ProductName>, but every  other  access
+     method is described here.  The schema is
+
+<TABLE TOCENTRY="1">
+<Title>Index Schema</Title>
+<TitleAbbrev>Indices</TitleAbbrev>
+<TGroup Cols="2">
+<THead>
+<Row>
+  <Entry>Attribute</Entry>
+  <Entry>Description</Entry>
+</Row>
+</THead>
+<TBody>
+<Row>
+  <Entry>amname</Entry>
+  <Entry>name of the access method</Entry>
+</Row>
+<Row>
+<Entry>amowner</Entry>
+<Entry>object id of the owner's instance in pg_user</Entry>
+</Row>
+<Row>
+<Entry>amkind</Entry>
+<Entry>not used at present, but set to 'o' as a place holder</Entry>
+</Row>
+<Row>
+<Entry>amstrategies</Entry>
+<Entry>number of strategies for this access method (see below)</Entry>
+</Row>
+<Row>
+<Entry>amsupport</Entry>
+<Entry>number of support routines for this access method (see below)</Entry>
+</Row>
+<Row>
+<Entry>amgettuple
+    aminsert
+    ...</Entry>
+
+<Entry>procedure  identifiers  for  interface routines to the access
+    method.  For example, regproc ids for opening,  closing,  and
+    getting instances from the access method appear here. </Entry>
+</Row>
+</TBody>
+</TGroup>
+</TABLE>
+</Para>
+
+<Para>
+     The  <Acronym>object  ID</Acronym>  of  the instance in <FileName>pg_am</FileName> is used as a
+     foreign key in lots of other classes.  You  don't  need
+     to  add a new instance to this class; all you're interested in 
+     is the <Acronym>object ID</Acronym> of the access method instance
+     you want to extend:
+
+<ProgramListing>
+SELECT oid FROM pg_am WHERE amname = 'btree';
+
+         +----+
+         |oid |
+         +----+
+         |403 |
+         +----+
+</ProgramListing>
+</Para>
+
+<Para>
+     The  <FileName>amstrategies</FileName>  attribute exists to standardize 
+     comparisons  across  data  types.   For  example,  <Acronym>B-tree</Acronym>s
+     impose  a  strict  ordering on keys, lesser to greater.
+     Since <ProductName>Postgres</ProductName> allows the  user  to  define  operators,
+     <ProductName>Postgres</ProductName>  cannot look at the name of an operator (eg, ">"
+     or "<") and tell what kind of comparison it is.  In fact,
+     some  access  methods don't impose any ordering at all.
+     For example, <Acronym>R-tree</Acronym>s  express  a  rectangle-containment
+     relationship, whereas a hashed data structure expresses
+     only bitwise similarity based on the value  of  a  hash
+     function.  <ProductName>Postgres</ProductName> needs some consistent way of taking
+     a qualification in your query, looking at the  operator
+     and  then  deciding  if  a  usable  index exists.  This
+     implies that <ProductName>Postgres</ProductName> needs to know, for example,  that
+     the  "<="  and  ">" operators partition a <Acronym>B-tree</Acronym>.  <ProductName>Postgres</ProductName>
+     uses strategies to express these relationships  between
+     operators and the way they can be used to scan indices.
+</Para>
+
+<Para>
+     Defining a new set of strategies is beyond the scope of
+     this  discussion,  but we'll explain how <Acronym>B-tree</Acronym> strategies 
+     work because you'll need to know that to add a new
+     operator  class.   In the <FileName>pg_am</FileName> class, the amstrategies
+     attribute is the number of strategies defined for  this
+     access  method.   For <Acronym>B-tree</Acronym>s, this number is 5.  These
+     strategies correspond to
+
+<TABLE TOCENTRY="1">
+<Title>B-tree Strategies</Title>
+<TitleAbbrev>B-tree</TitleAbbrev>
+<TGroup Cols="2">
+<THead>
+<Row>
+<Entry>Operation</Entry>
+<Entry>Index</Entry>
+</Row>
+</THead>
+<TBody>
+<Row>
+<Entry>less than</Entry>
+<Entry>1</Entry>
+</Row>
+<Row>
+<Entry>less than or equal</Entry>
+<Entry>2</Entry>
+</Row>
+<Row>
+<Entry>equal</Entry>
+<Entry>3</Entry>
+</Row>
+<Row>
+<Entry>greater than or equal</Entry>
+<Entry>4</Entry>
+</Row>
+<Row>
+<Entry>greater than</Entry>
+<Entry>5</Entry>
+</Row>
+</TBody>
+</TGroup>
+</TABLE>
+</Para>
+
+<Para>
+     The idea is that you'll need to add  procedures  corresponding  
+     to the comparisons above to the <FileName>pg_amop</FileName> relation 
+     (see below).  The access method code can use these
+     strategy  numbers,  regardless  of data type, to figure
+     out how to partition the <Acronym>B-tree</Acronym>,  compute  selectivity,
+     and  so  on.   Don't  worry about the details of adding
+     procedures yet; just understand that there  must  be  a
+     set  of these procedures for <FileName>int2, int4, oid,</FileName> and every
+     other data type on which a <Acronym>B-tree</Acronym> can operate.
+
+     Sometimes, strategies aren't enough information for the
+     system  to figure out how to use an index.  Some access
+     methods require other  support  routines  in  order  to
+     work.   For  example,  the <Acronym>B-tree</Acronym> access method must be
+     able to compare two keys and determine whether  one  is
+     greater  than, equal to, or less than the other.  
+     Similarly, the <Acronym>R-tree</Acronym> access method must be able to compute
+     intersections,  unions, and sizes of rectangles.  These
+     operations do not correspond to user qualifications  in
+     SQL  queries;  they are administrative routines used by
+     the access methods, internally.
+</Para>
+
+<Para>
+     In order to manage  diverse  support  routines  
+     consistently   across  all  <ProductName>Postgres</ProductName>  access  methods,  <FileName>pg_am</FileName>
+     includes an attribute called <FileName>amsupport</FileName>.  This attribute
+     records  the  number  of  support  routines  used by an
+     access method.  For <Acronym>B-tree</Acronym>s, this number is one --  the
+     routine  to  take  two  keys  and  return -1, 0, or +1,
+     depending on whether the first key is less than,  equal
+     to, or greater than the second.
+<Note>
+<Para>
+Strictly  speaking, this routine can return a negative
+number (< 0), 0, or a non-zero positive number (> 0).
+</Para>
+</Note>
+
+<Para>
+     The <FileName>amstrategies</FileName> entry in pg_am is just the  number  of
+     strategies  defined  for the access method in question.
+     The procedures for less than, less  equal,  and  so  on
+     don't  appear  in  <FileName>pg_am</FileName>.  Similarly, <FileName>amsupport</FileName> is just
+     the number of support routines required by  the  access
+     method.  The actual routines are listed elsewhere.
+</Para>
+
+<Para>
+     The  next  class of interest is pg_opclass.  This class
+     exists only to  associate  a  name  with  an  oid.   In
+     pg_amop,  every <Acronym>B-tree</Acronym> operator class has a set of 
+     procedures,  one  through  five,  above.   Some   existing
+     opclasses  are  <FileName>int2_ops,  int4_ops,  and oid_ops</FileName>.  You
+     need to add an instance with  your  opclass  name  (for
+     example,  <FileName>complex_abs_ops</FileName>)  to  <FileName>pg_opclass</FileName>.  The <FileName>oid</FileName> of
+     this instance is a foreign key in other classes.
+
+<ProgramListing>
+INSERT INTO pg_opclass (opcname) VALUES ('complex_abs_ops');
+
+SELECT oid, opcname
+    FROM pg_opclass
+    WHERE opcname = 'complex_abs_ops';
+
+         +------+--------------+
+         |oid   | opcname      |
+         +------+--------------+
+         |17314 | int4_abs_ops |
+         +------+--------------+
+</ProgramListing>
+
+     Note that the oid for your <FileName>pg_opclass</FileName> instance will  be
+     different!   You should substitute your value for 17314
+     wherever it appears in this discussion.
+</Para>
+
+<Para>
+     So now we have an access method and an operator  class.
+     We  still  need  a  set of operators; the procedure for
+     defining operators was discussed earlier in  this  manual.   
+     For  the  complex_abs_ops  operator  class on Btrees, 
+     the operators we require are:
+
+<ProgramListing>
+        absolute value less-than
+        absolute value less-than-or-equal
+        absolute value equal
+        absolute value greater-than-or-equal
+        absolute value greater-than
+</ProgramListing>
+</Para>
+
+<Para>
+     Suppose the code that implements the functions  defined
+     is stored in the file
+<FileName>PGROOT/src/tutorial/complex.c</FileName>
+</Para>
+
+<Para>
+     Part  of  the  code  look like this: (note that we will
+     only show the equality operator for  the  rest  of  the
+     examples.  The  other  four operators are very similar.
+     Refer to <FileName>complex.c</FileName> or <FileName>complex.sql</FileName> for the details.)
+
+<ProgramListing>
+#define Mag(c) ((c)-&gt;x*(c)-&gt;x + (c)-&gt;y*(c)-&gt;y)
+
+         bool
+         complex_abs_eq(Complex *a, Complex *b)
+         {
+             double amag = Mag(a), bmag = Mag(b);
+             return (amag==bmag);
+         }
+</ProgramListing>
+</Para>
+
+<Para>
+     There are a couple of important things that are happening below.
+</Para>
+
+<Para>
+     First, note that operators for less-than, less-than-or
+     equal, equal, greater-than-or-equal,  and  greater-than
+     for <FileName>int4</FileName> are being defined.  All of these operators are
+     already defined for <FileName>int4</FileName> under the names &lt;, &lt;=, =,  &gt;=,
+     and  &gt;.   The  new  operators  behave  differently,  of
+     course.  In order to guarantee that <ProductName>Postgres</ProductName> uses these
+     new operators rather than the old ones, they need to be
+     named differently from the old ones.   This  is  a  key
+     point: you can overload operators in <ProductName>Postgres</ProductName>, but only
+     if the operator isn't already defined for the  argument
+     types.   That  is,  if  you  have  &lt; defined for (int4,
+     int4), you can't define it again.   <ProductName>Postgres</ProductName>  does  not
+     check  this  when you define your operator, so be careful.  
+     To avoid this problem, odd names will be used for
+     the operators.  If you get this wrong, the access methods 
+     are likely to crash when you try to do scans.
+</Para>
+
+<Para>
+     The other important point  is  that  all  the  operator
+     functions  return  Boolean  values.  The access methods
+     rely on this fact.  (On the  other  hand,  the  support
+     function  returns whatever the particular access method
+     expects -- in this case, a signed integer.)
+     The final routine in the file is the "support  routine"
+     mentioned  when we discussed the amsupport attribute of
+     the <FileName>pg_am</FileName> class.  We will use this later on.  For  now,
+     ignore it.
+</Para>
+
+<Para>
+<ProgramListing>
+CREATE FUNCTION complex_abs_eq(complex, complex)
+              RETURNS bool
+              AS 'PGROOT/tutorial/obj/complex.so'
+              LANGUAGE 'c';
+</ProgramListing>
+</Para>
+
+<Para>
+     Now  define the operators that use them.  As noted, the
+     operator names must be unique among all operators  that
+     take  two <FileName>int4</FileName> operands.  In order to see if the 
+     operator names listed below are taken, we can do a query  on
+     <FileName>pg_operator</FileName>:
+
+<ProgramListing>
+    /*
+     * this query uses the regular expression operator (~)
+     * to find three-character operator names that end in
+     * the character &amp;
+     */
+    SELECT *
+     FROM pg_operator
+     WHERE oprname ~ '^..&amp;$'::text;
+</ProgramListing>
+
+</Para>
+
+<Para>
+     to  see  if  your name is taken for the types you want.
+     The important things here are the procedure (which  are
+     the  <Acronym>C</Acronym> functions defined above) and the restriction and
+     join selectivity functions.  You should  just  use  the
+     ones  used  below--note  that  there are different such
+     functions for the less-than,  equal,  and  greater-than
+     cases.   These  must  be supplied, or the access method
+     will crash when it tries  to  use  the  operator.   You
+     should  copy  the  names for restrict and join, but use
+     the procedure names you defined in the last step.
+
+<ProgramListing>
+CREATE OPERATOR = (
+     leftarg = complex, rightarg = complex,
+     procedure = complex_abs_eq,
+     restrict = eqsel, join = eqjoinsel
+         )
+</ProgramListing>
+</Para>
+
+<Para>
+     Notice that five operators corresponding to less,  less
+     equal, equal, greater, and greater equal are defined.
+</Para>
+
+<Para>
+     We're just about finished. the last thing we need to do
+     is to update the <FileName>pg_amop</FileName> relation.  To do this, we need
+     the following attributes:
+     
+<TABLE TOCENTRY="1">
+<Title><FileName>pg_amproc</FileName> Schema</Title>
+<TitleAbbrev><FileName>pg_amproc</FileName></TitleAbbrev>
+<TGroup Cols="2">
+<THead>
+<Row>
+<Entry>Attribute</Entry>
+<Entry>Description</Entry>
+</Row>
+</THead>
+<TBody>
+<Row>
+<Entry>amopid</Entry>
+<Entry>the <FileName>oid</FileName> of the <FileName>pg_am</FileName> instance
+ for  B-tree (== 403, see above)</Entry>
+</Row>
+<Row>
+<Entry>amopclaid</Entry>
+<Entry>the <FileName>oid</FileName> of the 
+<FileName>pg_opclass</FileName>  instance for <FileName>int4_abs_ops</FileName>
+ (== whatever you got instead  of <FileName>17314</FileName>, see above)</Entry>
+</Row>
+<Row>
+<Entry>amopopr</Entry>
+<Entry>the <FileName>oid</FileName>s of the  operators  for the opclass
+  (which we'll get in just a minute)</Entry>
+</Row>
+<Row>
+<Entry>amopselect, amopnpages</Entry>
+<Entry>cost functions</Entry>
+</Row>
+</TBody>
+</TGroup>
+</TABLE>
+
+     The cost functions are used by the query  optimizer  to
+     decide  whether  or not to use a given index in a scan.
+     Fortunately, these already exist.   The  two  functions
+     we'll use are <FileName>btreesel</FileName>, which estimates the selectivity
+     of the <Acronym>B-tree</Acronym>, and <FileName>btreenpage</FileName>, which estimates the 
+     number of pages a search will touch in the tree.
+</Para>
+
+<Para>
+     So  we  need the <FileName>oid</FileName>s of the operators we just defined.
+     We'll look up the names of all the operators that  take
+     two <FileName>int4</FileName>s, and pick ours out:
+
+<ProgramListing>
+    SELECT o.oid AS opoid, o.oprname
+     INTO TABLE complex_ops_tmp
+     FROM pg_operator o, pg_type t
+     WHERE o.oprleft = t.oid and o.oprright = t.oid
+      and t.typname = 'complex';
+
+         +------+---------+
+         |oid   | oprname |
+         +------+---------+
+         |17321 | &lt;       |
+         +------+---------+
+         |17322 | &lt;=      |
+         +------+---------+
+         |17323 |  =      |
+         +------+---------+
+         |17324 | &gt;=      |
+         +------+---------+
+         |17325 | &gt;       |
+         +------+---------+
+</ProgramListing>
+
+     (Again,  some of your <FileName>oid</FileName> numbers will almost certainly
+     be different.)  The operators we are interested in  are
+     those  with  <FileName>oid</FileName>s  17321 through 17325.  The values you
+     get will probably be different, and you should  
+     substitute  them  for  the  values below.  We can look at the
+     operator names and pick out the ones we just added.
+</Para>
+
+<Para>
+     Now we're ready to update <FileName>pg_amop</FileName> with our new operator
+     class.  The most important thing in this entire 
+     discussion is that the operators are ordered, from less equal
+     through   greater   equal,  in  <FileName>pg_amop</FileName>.   We  add  the
+     instances we need:
+
+<ProgramListing>
+    INSERT INTO pg_amop (amopid, amopclaid,
+     amopopr, amopstrategy,
+     amopselect, amopnpages)
+    SELECT am.oid, opcl.oid, c.opoid, 3,
+     'btreesel'::regproc, 'btreenpage'::regproc
+    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
+    WHERE amname = 'btree'
+     and opcname = 'complex_abs_ops'
+     and c.oprname = '=';
+</ProgramListing>
+
+     Note the order: "less than" is 1, "less than or  equal"
+     is  2,  "equal" is 3, "greater than or equal" is 4, and
+     "greater than" is 5.
+</Para>
+
+<Para>
+     The last step (finally!) is registration of  the  
+     "support routine" previously described in our discussion of
+     <FileName>pg_am</FileName>.  The <FileName>oid</FileName> of this support routine  is  stored  in
+     the <FileName>pg_amproc</FileName> class, keyed by the access method <FileName>oid</FileName> and
+     the operator class <FileName>oid</FileName>.  First, we need to register the
+     function  in  <ProductName>Postgres</ProductName>  (recall  that we put the <Acronym>C</Acronym> code
+     that implements this routine in the bottom of the  file
+     in which we implemented the operator routines):
+
+<ProgramListing>
+    CREATE FUNCTION int4_abs_cmp(int4, int4)
+     RETURNS int4
+     AS 'PGROOT/tutorial/obj/complex.so'
+     LANGUAGE 'c';
+
+    SELECT oid, proname FROM pg_proc
+     WHERE prname = 'int4_abs_cmp';
+
+         +------+--------------+
+         |oid   | proname      |
+         +------+--------------+
+         |17328 | int4_abs_cmp |
+         +------+--------------+
+</ProgramListing>
+
+     (Again,  your <FileName>oid</FileName> number will probably be different and
+     you should substitute the value you see for  the  value
+     below.)   Recalling  that  the <Acronym>B-tree</Acronym> instance's oid is
+     403 and that of <FileName>int4_abs_ops</FileName> is 17314, we can  add  the
+     new instance as follows:
+
+<ProgramListing>
+    INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+     VALUES ('403'::oid, -- btree oid
+     '17314'::oid,       --  pg_opclass tuple
+     '17328'::oid,       -- new pg_proc oid
+     '1'::int2);
+</ProgramListing>
+</Para>
+</Chapter>
diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..fa5e7342f674248774c0af23ca3f08eeba41e818
--- /dev/null
+++ b/doc/src/sgml/xoper.sgml
@@ -0,0 +1,52 @@
+<Chapter>
+<Title>Extending <Acronym>SQL</Acronym>: Operators</Title>
+
+<Para>
+     <ProductName>Postgres</ProductName> supports left unary, right  unary  and  binary
+     operators.   Operators  can  be  overloaded, or re-used
+     with different numbers  and  types  of  arguments.   If
+     there  is  an ambiguous situation and the system cannot
+     determine the correct operator to use, it  will  return
+     an  error  and you may have to typecast the left and/or
+     right operands to help it understand which operator you
+     meant to use.
+     To  create  an  operator for adding two complex numbers
+     can be done as follows.  First  we  need  to  create  a
+     function  to add the new types. Then, we can create the
+     operator with the function.
+
+<ProgramListing>
+         CREATE FUNCTION complex_add(complex, complex)
+            RETURNS complex
+            AS '$PWD/obj/complex.so'
+            LANGUAGE 'c';
+
+         CREATE OPERATOR + (
+            leftarg = complex,
+            rightarg = complex,
+            procedure = complex_add,
+            commutator = +
+         );
+</ProgramListing>
+</Para>
+
+<Para>
+     We've shown how to create a binary  operator  here.  To
+     create  unary  operators, just omit one of leftarg (for
+     left unary) or rightarg (for right unary).
+     If we give the system enough type information,  it  can
+     automatically figure out which operators to use.
+     
+<ProgramListing>
+         SELECT (a + b) AS c FROM test_complex;
+
+         +----------------+
+         |c               |
+         +----------------+
+         |(5.2,6.05)      |
+         +----------------+
+         |(133.42,144.95) |
+         +----------------+
+</ProgramListing>
+</Para>
+</Chapter>
diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..980fa2f00936bd1296ba177c8cdf0325a3c5ef49
--- /dev/null
+++ b/doc/src/sgml/xtypes.sgml
@@ -0,0 +1,149 @@
+<Chapter>
+<Title>Extending <Acronym>SQL</Acronym>: Types</Title>
+<Para>
+     As previously mentioned, there are two kinds  of  types
+     in  <ProductName>Postgres</ProductName>: base types (defined in a programming language) 
+     and composite types (instances).
+     Examples in this section up to interfacing indices  can
+     be  found in <FileName>complex.sql</FileName> and <FileName>complex.c</FileName>.  Composite examples 
+     are in <FileName>funcs.sql</FileName>.
+</Para>
+
+<Sect1>
+<Title>User-Defined Types</Title>
+
+<Sect2>
+<Title>Functions Needed for a User-Defined Type</Title>
+<Para>
+     A  user-defined  type must always have input and output
+     functions.  These  functions  determine  how  the  type
+     appears in strings (for input by the user and output to
+     the user) and how the type is organized in memory.  The
+     input  function takes a null-delimited character string
+     as its input and returns the internal (in memory)  
+     representation of the type.  The output function takes the
+     internal representation of the type and returns a null
+     delimited character string.
+     Suppose  we  want to define a complex type which represents 
+     complex numbers. Naturally, we choose  to  represent a 
+     complex in memory as the following <Acronym>C</Acronym> structure:
+<ProgramListing>
+         typedef struct Complex {
+             double      x;
+             double      y;
+         } Complex;
+</ProgramListing>
+     and  a  string of the form (x,y) as the external string
+     representation.
+     These functions are usually not hard  to  write,  especially  
+     the output function.  However, there are a number of points 
+     to remember:
+
+<ItemizedList>
+<ListItem>
+<Para>  When defining your external (string) representation,  
+            remember that you must eventually write a
+            complete and robust parser for that  representation 
+            as your input function!
+<ProgramListing>
+                Complex *
+                complex_in(char *str)
+                {
+                    double x, y;
+                    Complex *result;
+                    if (sscanf(str, " ( &percnt;lf , &percnt;lf )", &amp;x, &amp;y) != 2) {
+                        elog(WARN, "complex_in: error in parsing
+                        return NULL;
+                    }
+                    result = (Complex *)palloc(sizeof(Complex));
+                    result-&gt;x = x;
+                    result-&gt;y = y;
+                    return (result);
+                }
+</ProgramListing>
+
+            The output function can simply be:
+<ProgramListing>
+                char *
+                complex_out(Complex *complex)
+                {
+                    char *result;
+                    if (complex == NULL)
+                        return(NULL);
+                    result = (char *) palloc(60);
+                    sprintf(result, "(&percnt;g,&percnt;g)", complex-&gt;x, complex-&gt;y);
+                    return(result);
+                }
+</ProgramListing>
+</Para>
+</ListItem>
+<ListItem>
+<Para>  You  should  try  to  make  the input and output
+            functions inverses of each  other.   If  you  do
+            not, you will have severe problems when you need
+            to dump your data into a file and then  read  it
+            back  in  (say,  into someone else's database on
+            another computer).  This is a particularly  common  
+            problem  when  floating-point  numbers  are
+            involved.
+</Para>
+</ListItem>
+</ItemizedList>
+
+<Para>
+     To define the <Acronym>complex</Acronym> type, we need to create  the  two
+     user-defined   functions   complex_in  and  complex_out
+     before creating the type:
+<ProgramListing>
+         CREATE FUNCTION complex_in(opaque)
+            RETURNS complex
+            AS 'PGROOT/tutorial/obj/complex.so'
+            LANGUAGE 'c';
+
+         CREATE FUNCTION complex_out(opaque)
+            RETURNS opaque
+            AS 'PGROOT/tutorial/obj/complex.so'
+            LANGUAGE 'c';
+
+         CREATE TYPE complex (
+            internallength = 16,
+            input = complex_in,
+            output = complex_out
+         );
+</ProgramListing>
+</Para>
+
+<Para>
+     As discussed earlier, <ProductName>Postgres</ProductName> fully supports arrays of
+     base  types.  Additionally, <ProductName>Postgres</ProductName> supports arrays of
+     user-defined types as well.  When you  define  a  type,
+     <ProductName>Postgres</ProductName>  automatically  provides support for arrays of
+     that type.  For historical reasons, the array type  has
+     the  same name as the user-defined type with the 
+     underscore character _ prepended.
+     Composite types do not need  any  function  defined  on
+     them,  since  the  system already understands what they
+     look like inside.
+</Para>
+
+<Sect2>
+<Title>Large Objects</Title>
+
+<Para>
+     The types discussed  to  this  point  are  all  "small"
+     objects -- that is, they are smaller than 8KB in size.
+<Note>
+<Para>
+ 1024 longwords == 8192 bytes.  In fact, the type must be considerably smaller than 8192 bytes,
+ since the <ProductName>Postgres</ProductName>  tuple
+and  page  overhead  must also fit into this 8KB limitation.
+The actual value that fits depends on the machine  architecture.
+</Para>
+</Note>
+     If you require a larger type for something like a document  
+     retrieval system or for storing bitmaps, you will
+     need to use the <ProductName>Postgres</ProductName> large object interface.
+
+</Sect2>
+</Sect1>
+</Chapter>