OSDN Git Service

Complete merge of all old man page information.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 22 Jul 1999 15:11:05 +0000 (15:11 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 22 Jul 1999 15:11:05 +0000 (15:11 +0000)
lisp.sgml is a placeholder for Eric Marsden's upcoming contribution.
catalogs.sgml is not yet marked up or integrated.
 It should perhaps become an appendix.

14 files changed:
doc/src/sgml/catalogs.sgml [new file with mode: 0644]
doc/src/sgml/dfunc.sgml
doc/src/sgml/extend.sgml
doc/src/sgml/indices.sgml
doc/src/sgml/lisp.sgml [new file with mode: 0644]
doc/src/sgml/oper.sgml
doc/src/sgml/postgres.sgml
doc/src/sgml/programmer.sgml
doc/src/sgml/security.sgml
doc/src/sgml/syntax.sgml
doc/src/sgml/user.sgml
doc/src/sgml/xfunc.sgml
doc/src/sgml/xindex.sgml
doc/src/sgml/xplang.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
new file mode 100644 (file)
index 0000000..7af8722
--- /dev/null
@@ -0,0 +1,450 @@
+.\" This is -*-nroff-*-
+.\" XXX standard disclaimer belongs here....
+.\" $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.1 1999/07/22 15:11:03 thomas Exp $
+.TH "SYSTEM CATALOGS" INTRO 03/13/94 PostgreSQL PostgreSQL
+.SH "Section 7 - System Catalogs"
+.de LS
+.PP
+.if n .ta 5 +13 +13
+.if t .ta 0.5i +1.3i +1.3i
+.in 0
+.nf
+..
+.de LE
+.fi
+.in
+..
+.SH "DESCRIPTION"
+In this
+section we list each of the attributes of the system catalogs and
+define their meanings.
+.SH "CLASS/TYPE SYSTEM CATALOGS"
+These catalogs form the core of the extensibility system:
+.LS
+       \fBname\fP      \fBshared/local\fP      \fBdescription\fP
+       pg_aggregate    local   aggregate functions
+       pg_am   local   access methods
+       pg_amop local   operators usable with specific access methods
+       pg_amproc       local   procedures used with specific access methods
+       pg_attribute    local   class attributes
+       pg_class        local   classes
+       pg_index        local   secondary indices
+       pg_inherits     local   class inheritance hierarchy
+       pg_language     local   procedure implementation languages
+       pg_opclass      local   operator classes
+       pg_operator     local   query language operators
+       pg_proc local   procedures (functions)
+       pg_type local   data types
+.LE
+.SH "ENTITIES"
+These catalogs deal with identification of entities known throughout
+the site:
+.LS
+       \fBname\fP      \fBshared/local\fP      \fBdescription\fP
+       pg_database     shared  current databases
+       pg_group        shared  user groups
+       pg_shadow       shared  valid users
+.LE
+.SH "RULE SYSTEM CATALOGS"
+.LS
+       \fBname\fP      \fBshared/local\fP      \fBdescription\fP
+       pg_listener     local   processes waiting on alerters
+       pg_prs2plans    local   instance system procedures
+       pg_prs2rule     local   instance system rules
+       pg_prs2stub     local   instance system ``stubs''
+       pg_rewrite      local   rewrite system information
+.LE
+.SH "LARGE OBJECT CATALOGS"
+.PP
+These catalogs are specific to the Inversion file system and large
+objects in general:
+.LS
+       \fBname\fP      \fBshared/local\fP      \fBdescription\fP
+       pg_lobj local   description of a large object
+       pg_naming       local   Inversion name space mapping
+       pg_platter      local   jukebox platter inventory
+       pg_plmap        local   jukebox platter extent map
+.LE
+.SH "INTERNAL CATALOGS"
+.PP
+These catalogs are internal classes that are not stored as normal
+heaps and cannot be accessed through normal means (attempting to do so
+causes an error).
+.LS
+       \fBname\fP      \fBshared/local\fP      \fBdescription\fP
+       pg_log  shared  transaction commit/rollback log
+       pg_magic        shared  magic constant
+       pg_time shared  commit/rollback times
+       pg_variable     shared  special variable values
+.LE
+.PP
+There are several other classes defined with \*(lqpg_\*(rq names.
+Aside from those that end in \*(lqind\*(rq (secondary indices), these
+are all obsolete or otherwise deprecated.
+.SH "CLASS/TYPE SYSTEM CATALOGS"
+.PP
+The following catalogs relate to the class/type system.
+.nf M
+/*
+ * aggregates
+ *
+ * see DEFINE AGGREGATE for an explanation of transition functions
+ */
+pg_aggregate
+    NameData      aggname      /* aggregate name (e.g., "count") */
+    oid         aggowner       /* usesysid of creator */
+    regproc     aggtransfn1    /* first transition function */
+    regproc     aggtransfn2    /* second transition function */
+    regproc     aggfinalfn     /* final function */
+    oid         aggbasetype    /* type of data on which aggregate
+                                  operates */
+    oid         aggtranstype1  /* type returned by aggtransfn1 */
+    oid         aggtranstype2  /* type returned by aggtransfn2 */
+    oid         aggfinaltype   /* type returned by aggfinalfn */
+    text        agginitval1    /* external format of initial
+                                  (starting) value of aggtransfn1 */
+    text        agginitval2    /* external format of initial
+                                  (starting) value of aggtransfn2 */
+.fi
+.nf M
+pg_am
+    NameData      amname               /* access method name */
+    oid         amowner        /* usesysid of creator */
+    char        amkind         /* - deprecated */
+                               /* originally:
+                                  h=hashed
+                                  o=ordered
+                                  s=special */
+    int2        amstrategies   /* total NUMBER of strategies by which
+                                  we can traverse/search this AM */
+    int2        amsupport      /* total NUMBER of support functions
+                                  that this AM uses */
+    regproc     amgettuple     /* "next valid tuple" function */
+    regproc     aminsert       /* "insert this tuple" function */
+    regproc     amdelete       /* "delete this tuple" function */
+    regproc     amgetattr      /* - deprecated */
+    regproc     amsetlock      /* - deprecated */
+    regproc     amsettid       /* - deprecated */
+    regproc     amfreetuple    /* - deprecated */
+    regproc     ambeginscan    /* "start new scan" function */
+    regproc     amrescan       /* "restart this scan" function */
+    regproc     amendscan      /* "end this scan" function */
+    regproc     ammarkpos      /* "mark current scan position"
+                                  function */
+    regproc     amrestrpos     /* "restore marked scan position"
+                                  function */
+    regproc     amopen         /* - deprecated */
+    regproc     amclose        /* - deprecated */
+    regproc     ambuild        /* "build new index" function */
+    regproc     amcreate       /* - deprecated */
+    regproc     amdestroy      /* - deprecated */
+.fi
+.nf M
+pg_amop
+    oid         amopid         /* access method with which this 
+                                  operator be used */
+    oid         amopclaid      /* operator class with which this
+                                  operator can be used */
+    oid         amopopr        /* the operator */
+    int2        amopstrategy   /* traversal/search strategy number
+                                  to which this operator applies */
+    regproc     amopselect     /* function to calculate the operator
+                                  selectivity */
+    regproc     amopnpages     /* function to calculate the number of
+                                  pages that will be examined */
+.fi
+.nf M
+pg_amproc
+    oid         amid           /* access method with which this
+                                  procedure is associated */
+    oid         amopclaid      /* operator class with which this
+                                  operator can be used */
+    oid         amproc         /* the procedure */
+    int2        amprocnum      /* support function number to which
+                                  this operator applies */
+.fi
+.nf M
+pg_class
+     NameData     relname      /* class name */
+     oid        relowner       /* usesysid of owner */
+     oid        relam  /* access method */
+     int4       relpages       /* # of 8KB pages */
+     int4       reltuples      /* # of instances */
+     abstime    relexpires     /* time after which instances are
+                                  deleted from non-archival storage */
+     reltime    relpreserved   /* timespan after which instances are
+                                  deleted from non-archival storage */
+     bool       relhasindex    /* does the class have a secondary
+                                  index? */
+     bool       relisshared    /* is the class shared or local? */
+     char       relkind                /* type of relation:
+                                  i=index
+                                  r=relation (heap)
+                                  s=special
+                                  u=uncatalogued (temporary) */
+     char       relarch        /* archive mode:
+                          h=heavy
+                          l=light
+                          n=none */
+     int2       relnatts       /* current # of non-system
+                                  attributes */
+     int2       relsmgr        /* storage manager:
+                          0=magnetic disk
+                          1=sony WORM jukebox
+                          2=main memory */
+     int28      relkey /* - unused */
+     oid8       relkeyop       /* - unused */
+     aclitem    relacl[1]      /* access control lists */
+.fi
+.nf M
+pg_attribute
+    oid         attrelid       /* class containing this attribute */
+    NameData      attname      /* attribute name */
+    oid         atttypid       /* attribute type */
+    oid         attdefrel      /* - deprecated */
+    int4        attnvals       /* - deprecated */
+    oid         atttyparg      /* - deprecated */
+    int2        attlen /* attribute length, in bytes
+                          -1=variable */
+    int2        attnum /* attribute number
+                          >0=user attribute
+                          <0=system attribute */
+    int2        attbound       /* - deprecated */
+    bool        attbyval       /* type passed by value? */
+    bool        attcanindex    /* - deprecated */
+    oid         attproc        /* - deprecated */
+    int4        attnelems      /* # of array dimensions */
+    int4        attcacheoff    /* cached offset into tuple */
+    bool        attisset       /* is attribute set-valued? */
+.fi
+.nf M
+pg_inherits
+    oid         inhrel /* child class */
+    oid         inhparent      /* parent class */
+    int4        inhseqno       /* - deprecated */
+.fi
+.nf M
+    oid         indexrelid     /* oid of secondary index class */
+    oid         indrelid       /* oid of indexed heap class */
+    oid         indproc        /* function to compute index key from
+                                  attribute(s) in heap
+                                  0=not a functional index */
+    int28       indkey /* attribute numbers of key 
+                          attribute(s) */
+    oid8        indclass       /* opclass of each key */
+    bool        indisclustered /* is the index clustered?
+                                  - unused */
+    bool        indisarchived  /* is the index archival?
+                                  - unused */
+    text        indpred        /* query plan for partial index 
+                          predicate */
+.fi
+.nf M
+pg_type
+    NameData      typname      /* type name */
+    oid         typowner       /* usesysid of owner */
+    int2        typlen /* length in internal form
+                          -1=variable-length */
+    int2        typprtlen      /* length in external form */
+    bool        typbyval       /* type passed by value? */
+    char        typtype        /* kind of type:
+                          c=catalog (composite)
+                          b=base */
+    bool        typisdefined   /* defined or still a shell? */
+    char        typdelim       /* delimiter for array external form */
+    oid         typrelid       /* class (if composite) */
+    oid         typelem        /* type of each array element */
+    regproc     typinput       /* external-internal conversion
+                                  function */ 
+    regproc     typoutput      /* internal-external conversion
+                                  function */
+    regproc     typreceive     /* client-server conversion function */
+    regproc     typsend        /* server-client conversion function */
+    text        typdefault     /* default value */
+.fi
+.nf M
+pg_operator
+    NameData      oprname      /* operator name */
+    oid         oprowner       /* usesysid of owner */
+    int2        oprprec        /* - deprecated */
+    char        oprkind        /* kind of operator:
+                          b=binary
+                          l=left unary
+                          r=right unary */
+    bool        oprisleft      /* is operator left/right associative? */
+    bool        oprcanhash     /* is operator usable for hashjoin? */
+    oid         oprleft        /* left operand type */
+    oid         oprright       /* right operand type */
+    oid         oprresult      /* result type */
+    oid         oprcom /* commutator operator */
+    oid         oprnegate      /* negator operator */
+    oid         oprlsortop     /* sort operator for left operand */
+    oid         oprrsortop     /* sort operator for right operand */
+    regproc     oprcode        /* function implementing this operator */
+    regproc     oprrest        /* function to calculate operator
+                          restriction selectivity */
+    regproc     oprjoin        /* function to calculate operator 
+                          join selectivity */
+.fi
+.nf M
+pg_opclass
+    NameData      opcname      /* operator class name */
+.fi
+.nf M
+pg_proc
+    NameData      proname      /* function name */
+    oid         proowner       /* usesysid of owner */
+    oid         prolang        /* function implementation language */
+    bool        proisinh       /* - deprecated */
+    bool        proistrusted   /* run in server or untrusted function
+                                  process? */
+    bool        proiscachable  /* can the function return values be
+                                  cached? */
+    int2        pronargs       /* # of arguments */
+    bool        proretset      /* does the function return a set?
+                                  - unused */
+    oid         prorettype     /* return type */
+    oid8        proargtypes    /* argument types */
+    int4        probyte_pct    /* % of argument size (in bytes) that
+                                  needs to be examined in order to
+                                  compute the function */ 
+    int4        properbyte_cpu /* sensitivity of the function's
+                                  running time to the size of its
+                                  inputs */
+    int4        propercall_cpu /* overhead of the function's
+                                  invocation (regardless of input
+                                  size) */
+    int4        prooutin_ratio /* size of the function's output as a
+                                  percentage of the size of the input */
+    text        prosrc /* function definition:
+                          INTERNAL function: actual C name of function
+                          C function: currently, this field is unused
+                          SQL function: text of query(s)
+                          PL function: text in procedural language */
+    bytea       probin /* path to object file (C functions only) */
+.fi
+.nf M
+pg_language
+    NameData      lanname      /* language name */
+    text        lancompiler    /* - deprecated */
+.fi
+.SH "ENTITIES"
+.nf M
+pg_database
+    NameData      datname              /* database name */
+    oid         datdba         /* usesysid of database administrator */
+    text        datpath                /* directory of database under
+                                  $PGDATA */ 
+.fi
+.nf M
+pg_group
+    NameData      groname      /* group name */
+    int2        grosysid       /* group's UNIX group id */
+    int2        grolist[1]     /* list of usesysids of group members */
+.fi
+.nf M
+pg_shadow
+    NameData      usename              /* user's name */
+    int2        usesysid       /* user's UNIX user id */
+    bool        usecreatedb    /* can user create databases? */
+    bool        usetrace       /* can user set trace flags? */
+    bool        usesuper       /* can user be POSTGRES superuser? */
+    bool        usecatupd      /* can user update catalogs? */
+.fi
+.SH "RULE SYSTEM CATALOGS"
+.nf M
+pg_listener
+    NameData      relname      /* class for which asynchronous 
+                          notification is desired */
+    int4        listenerpid    /* process id of server corresponding
+                                  to a frontend program waiting for
+                                  asynchronous notification */
+    int4        notification   /* whether an event notification for
+                                  this process id still pending */
+
+.fi
+.nf M
+pg_prs2rule
+    NameData      prs2name     /* rule name */
+    char        prs2eventtype  /* rule event type:
+                                  R=retrieve
+                                  U=update (replace)
+                                  A=append
+                                  D=delete */
+    oid         prs2eventrel   /* class to which event applies */
+    int2        prs2eventattr  /* attribute to which event applies */
+    float8      necessary      /* - deprecated */
+    float8      sufficient     /* - deprecated */
+    text        prs2text       /* text of original rule definition */
+.fi
+.nf M
+pg_prs2plans
+    oid         prs2ruleid     /* prs2rule instance for which this
+                                  plan is used */
+    int2        prs2planno     /* plan number (one rule may invoke
+                                  multiple plans) */
+    text        prs2code       /* external representation of the plan */
+.fi
+.nf M
+pg_prs2stub
+    oid         prs2relid      /* class to which this rule applies */
+    bool        prs2islast     /* is this the last stub fragment? */
+    int4        prs2no         /* stub fragment number */
+    stub        prs2stub       /* stub fragment */
+.fi
+.nf M
+pg_rewrite
+    NameData      rulename     /* rule name */
+    char        ev_type        /* event type:
+                          RETRIEVE, REPLACE, APPEND, DELETE
+                          codes are parser-dependent (!?) */
+    oid         ev_class       /* class to which this rule applies */
+    int2        ev_attr        /* attribute to which this rule applies */
+    bool        is_instead     /* is this an "instead" rule? */
+    text        ev_qual        /* qualification with which to modify
+                          (rewrite) the plan that triggered this
+                          rule */
+    text        action /* parse tree of action */
+.fi
+.SH "LARGE OBJECT CATALOGS"
+.nf M
+pg_lobj
+    oid         ourid          /* 'ourid' from pg_naming that
+                                  identifies this object in the
+                                  Inversion file system namespace */
+    int4        objtype                /* storage type code:
+                                  0=Inversion
+                                  1=Unix
+                                  2=External
+                                  3=Jaquith */
+    bytea       object_descripto/* opaque object-handle structure */
+.fi
+.nf M
+pg_naming
+    NameData      filename     /* filename component */
+    oid         ourid          /* random oid used to identify this
+                                  instance in other instances (can't
+                                  use the actual oid for obscure
+                                  reasons */
+    oid         parentid       /* pg_naming instance of parent
+                                  Inversion file system directory */
+.fi
+.nf M
+pg_platter
+     NameData     plname               /* platter name */
+     int4       plstart                /* the highest OCCUPIED extent */
+.fi
+.nf M
+pg_plmap
+     oid        plid           /* platter (in pg_platter) on which
+                                  this extent (of blocks) resides */
+     oid        pldbid         /* database of the class to which this
+                                  extent (of blocks) belongs */
+     oid        plrelid                /* class to which this extend (of
+                                  blocks) belongs */
+     int4       plblkno                /* starting block number within the
+                                  class */ 
+     int4       ploffset       /* offset within the platter at which
+                                  this extent begins */
+     int4       plextentsz     /* length of this extent */
+.fi
index 28e7428..9da3668 100644 (file)
-<Chapter Id="dfunc">
-<Title>Linking Dynamically-Loaded Functions</Title>
+ <chapter id="dfunc">
+  <title id="dfunc-title">Linking Dynamically-Loaded Functions</title>
 
-<Para>
+<!--
+.SH "Compiling Dynamically-Loaded C Functions"
+.PP
+Different operating systems require different procedures for compiling
+C source files so that Postgres can load them dynamically.  This section
+discusses the required compiler and loader options on each system.
+.PP
+Under Linux ELF, object files can be generated by specifing the compiler
+flag -fpic.
+.PP
+Under Ultrix, all object files that Postgres is expected to load
+dynamically must be compiled using
+.IR /bin/cc
+with the \*(lq-G 0\*(rq option turned on.  The object file name in the
+.IR as
+clause should end in \*(lq.o\*(rq.
+.PP
+Under HP-UX, DEC OSF/1, AIX and SunOS 4, all object files must be
+turned into
+.IR "shared libraries"
+using the operating system's native object file loader,
+.IR ld(1).
+.PP
+Under HP-UX, an object file must be compiled using the native HP-UX C
+compiler,
+.IR /bin/cc ,
+with both the \*(lq+z\*(rq and \*(lq+u\*(rq flags turned on.  The
+first flag turns the object file into \*(lqposition-independent
+code\*(rq (PIC); the second flag removes some alignment restrictions
+that the PA-RISC architecture normally enforces.  The object file must
+then be turned into a shared library using the HP-UX loader,
+.IR /bin/ld .
+The command lines to compile a C source file, \*(lqfoo.c\*(rq, look
+like:
+.nf
+cc <other flags> +z +u -c foo.c
+ld <other flags> -b -o foo.sl foo.o
+.fi
+The object file name in the
+.BR as
+clause should end in \*(lq.sl\*(rq.
+.PP
+An extra step is required under versions of HP-UX prior to 9.00.  If
+the Postgres header file
+.nf
+include/c.h
+.fi
+is not included in the source file, then the following line must also
+be added at the top of every source file:
+.nf
+#pragma HP_ALIGN HPUX_NATURAL_S500
+.fi
+However, this line must not appear in programs compiled under HP-UX
+9.00 or later.
+.PP
+Under DEC OSF/1, an object file must be compiled and then turned
+into a shared library using the OSF/1 loader,
+.IR /bin/ld .
+In this case, the command lines look like:
+.nf
+cc <other flags> -c foo.c
+ld <other flags> -shared -expect_unresolved '*' -o foo.so foo.o
+.fi
+The object file name in the
+.BR as
+clause should end in \*(lq.so\*(rq.
+.PP
+Under SunOS 4, an object file must be compiled and then turned into a
+shared library using the SunOS 4 loader,
+.IR /bin/ld .
+The command lines look like:
+.nf
+cc <other flags> -PIC -c foo.c
+ld <other flags> -dc -dp -Bdynamic -o foo.so foo.o
+.fi
+The object file name in the
+.BR as
+clause should end in \*(lq.so\*(rq.
+.PP
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` > foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+You should look at the Postgres User's Manual for an explanation of this
+procedure.
+-->
+
+<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
+     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  
+     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  
      link-edit  it  in  a  special  way.   This  section  briefly
      describes how to  perform  the  compilation  and  
      link-editing  required before you can load your user-defined
-     functions into a running <ProductName>Postgres</ProductName>  server.   Note  that
+     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 
+<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
+<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.
@@ -30,58 +129,59 @@ 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
+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>
+</tip>
 </para>
 <para>
      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 
+     <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>
+<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  <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>
+</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>
+</listitem>
+</itemizedlist>
+</para>
 
-<Para>
+<para>
      The following general restrictions and notes also apply
      to the discussion below:
-<ItemizedList>
-<ListItem>
-<Para>
+<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>
+        <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
@@ -89,45 +189,45 @@ 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
+</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
+        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>
+</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>
+        <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>
+</para>
+</listitem>
+</itemizedlist>
 </para>
 
-<Sect1>
-<Title><Acronym>ULTRIX</Acronym></Title>
+<sect1>
+<title><acronym>ULTRIX</acronym></title>
 
-<Para>
+<para>
      It is very  easy  to  build  dynamically-loaded  object
      files  under  ULTRIX.  ULTRIX does not have any shared library 
      mechanism and hence does not place any restrictions  on  
@@ -138,42 +238,42 @@ The GNU C compiler usually does not provide the special
      produce each object file with the option -G 0.  (Notice
      that  that's  the  numeral  ``0''  and  not  the letter
      ``O'').  For example,
-<ProgramListing>
+<programlisting>
 # simple ULTRIX example
 % cc -G 0 -c foo.c
-</ProgramListing>
+</programlisting>
      produces an object file called foo.o that can  then  be
-     dynamically  loaded into <ProductName>Postgres</ProductName>.
+     dynamically  loaded into <productname>Postgres</productname>.
 No additional loading or link-editing must be performed.
-</Para>
-</Sect1>
+</para>
+</sect1>
 
-<Sect1>
-<Title><Acronym>DEC OSF/1</Acronym></Title>
+<sect1>
+<title><acronym>DEC OSF/1</acronym></title>
 
-<Para>
+<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>
+<programlisting>
 # simple DEC OSF/1 example
 % cc -c foo.c
 % ld -shared -expect_unresolved '*' -o foo.so foo.o
-</ProgramListing>
+</programlisting>
 
      The  resulting  shared  object  file can then be loaded
-     into <ProductName>Postgres</ProductName>.  When specifying the object file name to
+     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
+<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>
+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
@@ -183,19 +283,20 @@ 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>
+</para>
+</tip>
 
 If the file you specify is
      not a shared object, the backend will hang!
-</Para>
-</Sect1>
+</para>
+</sect1>
 
-<Sect1>
-<Title>
-<Acronym>SunOS 4.x</Acronym>, <Acronym>Solaris 2.x</Acronym> and <Acronym>HP-UX</Acronym></Title>
+<sect1>
+<title>
+<acronym>SunOS 4.x</acronym>, <acronym>Solaris 2.x</acronym> and
+    <acronym>HP-UX</acronym></title>
 
-<Para>
+<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
@@ -209,44 +310,61 @@ If the file you specify is
      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>
+<programlisting>
 # simple HP-UX example
 % cc +z +u -c foo.c
 % ld -b -o foo.sl foo.o
-</ProgramListing>
-</Para>
+</programlisting>
+</para>
 
-<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>
+<programlisting>
 # simple SunOS 4.x example
 % cc -PIC -c foo.c
 % ld -dc -dp -Bdynamic -o foo.so foo.o
-</ProgramListing>
+</programlisting>
 
      and the equivalent lines under Solaris 2.x are:
-<ProgramListing>
+<programlisting>
 # simple Solaris 2.x example
 % cc -K PIC -c foo.c
 % ld -G -Bdynamic -o foo.so foo.o
-</ProgramListing>
+</programlisting>
     or
-<ProgramListing>
+<programlisting>
 # simple Solaris 2.x example
 % gcc -fPIC -c foo.c
 % ld -G -Bdynamic -o foo.so foo.o
-</ProgramListing>
-</Para>
+</programlisting>
+</para>
 
-<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>
+</para>
+</sect1>
+</chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->
index 0b8eb1a..cad198c 100644 (file)
-<Chapter Id="extend">
-<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>
+ <chapter id="extend">
+  <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 spacing="compact" mark="bullet">
+    <listitem>
+     <para>
       functions
-</Para>
-</ListItem>
-<ListItem>
-<Para>
+     </para>
+    </listitem>
+    <listitem>
+     <para>
       types
-</Para>
-</ListItem>
-<ListItem>
-<Para>
+     </para>
+    </listitem>
+    <listitem>
+     <para>
       operators
-</Para>
-</ListItem>
-<ListItem>
-<Para>
+     </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:
+     </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 float="1" id="EXTEND-CATALOGS">
+     <title>The major <productname>Postgres</productname> system catalogs</title>
+     <graphic fileref="catalogs.gif" format="GIF" align="center"></graphic>
+    </figure>
+
+    The Reference Manual gives a more detailed  explanation
+    of  these catalogs and their attributes.  However,
+    <xref endterm="EXTEND-CATALOGS" linkend="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.
-</para>
-</ListItem>
-</ItemizedList>
-
-</Para>
-</sect1>
-</Chapter>
+    <itemizedlist spacing="compact" mark="bullet">
+     <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.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </para>
+  </sect1>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->
index 85abcf0..420ee00 100644 (file)
-<chapter id="indices">
-<title>Indices</title>
+ <chapter id="indices">
+  <title id="indices-title">Indices and Keys</title>
 
-<para>
+  <para>
+   Indexes are primarily used to enhance database
+   performance. They should be defined on table columns (or class
+   attributes) which are used as qualifications in repetative queries.
+   Inappropriate use will result in slower performance, since update
+   and insertion times are increased in the presence of indices.
+  </para>
 
-<sect1>
-<title>Partial Indices</title>
+  <para>
+   Two forms of indices may be defined:
 
-<para>
-<note>
-<title>Author</title>
-<para>
-This is from a reply to a question on the e-mail list
-by <ulink url="aoki@CS.Berkeley.EDU">Paul M. Aoki</ulink>
-on 1998-08-11.
+   <itemizedlist>
+    <listitem>
+     <para>
+      For a <firstterm>value index</firstterm>,
+      the key fields for the
+      index are specified as column names; a column may also have
+      an associated operator class. An operator class is used
+      to specify the operators to be used for a particular
+      index. For example, a btree index on four-byte integers
+      would use the <literal>int4_ops</literal> class;
+      this operator class includes
+      comparison functions for four-byte integers. The default
+      operator class is the appropriate operator class for that
+      field type.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      For a <firstterm>functional index</firstterm>, an index is defined
+      on the result of a user-defined function applied
+      to one or more attributes of a single class.
+      These functional indices
+      can be used to obtain fast access to data
+      based on operators that would normally require some
+      transformation to apply them to the base data.
+     </para>
+    </listitem>
+   </itemizedlist>
+  </para>
+
+  <para>
+   Postgres provides btree, rtree and hash access methods for
+   secondary indices.  The btree access method is an implementation of
+   the Lehman-Yao high-concurrency btrees.  The rtree access method
+   implements standard rtrees using Guttman's quadratic split algorithm.
+   The hash access method is an implementation of Litwin's linear
+   hashing.  We mention the algorithms used solely to indicate that all
+   of these access methods are fully dynamic and do not have to be
+   optimized periodically (as is the case with, for example, static hash
+   access methods).
+  </para>
+
+  <para>
+   The Postgres query optimizer will consider using btree indices in a scan
+   whenever an indexed attribute is involved in a comparison using one of:
+
+   <simplelist type="inline">
+    <member>&lt;</member>
+    <member>&lt;=</member>
+    <member>=</member>
+    <member>&gt;=</member>
+    <member>&gt;</member>
+   </simplelist>
+  </para>
+
+  <para>
+   Both box classes support indices on the <literal>box</literal> data 
+   type in <productname>Postgres</productname>.
+   The difference between them is that <literal>bigbox_ops</literal>
+   scales box coordinates down, to avoid floating point exceptions from
+   doing multiplication, addition, and subtraction on very large
+   floating-point coordinates.  If the field on which your rectangles lie
+   is about 20,000 units square or larger, you should use
+   <literal>bigbox_ops</literal>.
+   The <literal>poly_ops</literal> operator class supports rtree
+   indices on <literal>polygon</literal> data.
+  </para>
+
+  <para>
+   The <productname>Postgres</productname>
+   query optimizer will consider using an rtree index whenever
+   an indexed attribute is involved in a comparison using one of:
+
+   <simplelist type="inline">
+    <member>&lt;&lt;</member>
+    <member>&amp;&lt;</member>
+    <member>&amp;&gt;</member>
+    <member>&gt;&gt;</member>
+    <member>@</member>
+    <member>~=</member>
+    <member>&amp;&amp;</member>
+   </simplelist>
+  </para>
+
+  <para>
+   The <productname>Postgres</productname>
+   query optimizer will consider using a hash index whenever
+   an indexed attribute is involved in a comparison using
+   the <literal>=</literal> operator.
+  </para>
+
+  <para>
+   Currently, only the BTREE access method supports multi-column
+   indexes. Up to 7 keys may be specified.
+  </para>
+
+  <para>
+   Use <xref endterm="sql-dropindex-title"
+    linkend="sql-dropindex-title">
+   to remove an index.
+  </para>
+
+  <para>
+   The <literal>int24_ops</literal>
+   operator class is useful for constructing indices on int2 data, and
+   doing comparisons against int4 data in query qualifications.
+   Similarly, <literal>int42_ops</literal>
+   support indices on int4 data that is to be compared against int2 data
+   in queries.
+  </para>
+
+  <para>
+   The following select list returns all ops_names:
+
+   <programlisting>
+SELECT am.amname AS acc_name,
+       opc.opcname AS ops_name,
+       opr.oprname AS ops_comp
+    FROM pg_am am, pg_amop amop,
+         pg_opclass opc, pg_operator opr
+    WHERE amop.amopid = am.oid AND
+          amop.amopclaid = opc.oid AND
+          amop.amopopr = opr.oid
+    ORDER BY acc_name, ops_name, ops_comp
+   </programlisting>
+  </para>
+
+  <sect1 id="keys">
+   <title id="keys-title">Keys</title>
+
+   <para>
+    <note>
+     <title>Author</title>
+     <para>
+      Written by 
+      <ulink url="herouth@oumail.openu.ac.il">Herouth Maoz</ulink>
+      This originally appeared on the User's Mailing List on 1998-03-02
+      in response to the question:
+      "What is the difference between PRIMARY KEY and UNIQUE constraints?".
+     </para>
+    </note>
+   </para>
+
+   <para>
+    <programlisting>
+Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE
+
+        What's the difference between:
+
+              PRIMARY KEY(fields,...) and
+              UNIQUE (fields,...)
+
+       - Is this an alias?
+       - If PRIMARY KEY is already unique, then why
+         is there another kind of key named UNIQUE?
+    </programlisting>
+   </para>
+
+   <para>
+    A primary key is the field(s) used to identify a specific row. For example,
+    Social Security numbers identifying a person.
+   </para>
+
+   <para>
+    A simply UNIQUE combination of fields has nothing to do with identifying
+    the row. It's simply an integrity constraint. For example, I have
+    collections of links. Each collection is identified by a unique number,
+    which is the primary key. This key is used in relations.
+   </para>
+
+   <para>
+    However, my application requires that each collection will also have a
+    unique name. Why? So that a human being who wants to modify a collection
+    will be able to identify it. It's much harder to know, if you have two
+    collections named "Life Science", the the one tagged 24433 is the one you
+    need, and the one tagged 29882 is not.
+   </para>
+
+   <para>
+    So, the user selects the collection by its name. We therefore make sure,
+    withing the database, that names are unique. However, no other table in the
+    database relates to the collections table by the collection Name. That
+    would be very inefficient.
+   </para>
+
+   <para>
+    Moreover, despite being unique, the collection name does not actually
+    define the collection! For example, if somebody decided to change the name
+    of the collection from "Life Science" to "Biology", it will still be the
+    same collection, only with a different name. As long as the name is unique,
+    that's OK.
+   </para>
+
+   <para>
+    So:
+
+    <itemizedlist>
+     <listitem>
+      <para>
+       Primary key:
+       <itemizedlist spacing="compact" mark="bullet">
+       <listitem>
+        <para>
+         Is used for identifying the row and relating to it.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Is impossible (or hard) to update.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Should not allow NULLs.
+        </para>
+       </listitem>
+       </itemizedlist>
+      </para>
+     </listitem>
+
+     <listitem>
+      <para>
+       Unique field(s):
+       <itemizedlist spacing="compact" mark="bullet">
+       <listitem>
+        <para>
+         Are used as an alternative access to the row.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Are updateable, so long as they are kept unique.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         NULLs are acceptable.
+        </para>
+       </listitem>
+       </itemizedlist>
+      </para>
+     </listitem>
+    </itemizedlist>
+   </para>
+
+   <para>
+    As for why no non-unique keys are defined explicitly in standard
+    <acronym>SQL</acronym> syntax? Well, you
+    must understand that indices are implementation-dependent.
+    <acronym>SQL</acronym> does not
+    define the implementation, merely the relations between data in the
+    database. <productname>Postgres</productname> does allow
+    non-unique indices, but indices
+    used to enforce <acronym>SQL</acronym> keys are always unique.
+   </para>
+
+   <para>
+    Thus, you may query a table by any combination of its columns, despite the
+    fact that you don't have an index on these columns. The indexes are merely
+    an implementational aid which each <acronym>RDBMS</acronym> offers
+    you, in order to cause
+    commonly used queries to be done more efficiently.
+    Some <acronym>RDBMS</acronym> may give you
+    additional measures, such as keeping a key stored in main memory. They will
+    have a special command, for example
+    <programlisting>
+CREATE MEMSTORE ON &lt;table&gt; COLUMNS &lt;cols&gt;
+    </programlisting>
+    (this is not an existing command, just an example).
+   </para>
+
+   <para>
+    In fact, when you create a primary key or a unique combination of fields,
+    nowhere in the <acronym>SQL</acronym> specification does it say
+    that an index is created, nor that
+    the retrieval of data by the key is going to be more efficient than a
+    sequential scan!
+   </para>
+
+   <para>
+    So, if you want to use a combination of fields which is not unique as a
+    secondary key, you really don't have to specify anything - just start
+    retrieving by that combination! However, if you want to make the retrieval
+    efficient, you'll have to resort to the means your
+    <acronym>RDBMS</acronym> provider gives you
+    - be it an index, my imaginary MEMSTORE command, or an intelligent
+    <acronym>RDBMS</acronym>
+    which creates indices without your knowledge based on the fact that you have
+    sent it many queries based on a specific combination of keys... (It learns
+    from experience).
+   </para>
+  </sect1>
+
+  <sect1 id="partial-index">
+   <title id="partial-index-title">Partial Indices</title>
+
+   <note>
+    <title>Author</title>
+    <para>
+     This is from a reply to a question on the e-mail list
+     by <ulink url="aoki@CS.Berkeley.EDU">Paul M. Aoki</ulink>
+     on 1998-08-11.
 <!--
   Paul M. Aoki         | University of California at Berkeley
   aoki@CS.Berkeley.EDU | Dept. of EECS, Computer Science Division #1776
                        | Berkeley, CA 94720-1776
 -->
-</note>
-
-A <firstterm>partial index</firstterm>
-is an index built over a subset of a table; the subset is defined by
-a predicate.  <productname>Postgres</productname>
- supported partial indices with arbitrary
-predicates.  I believe IBM's db2 for as/400 supports partial indices
-using single-clause predicates.
-
-<para>
-The main motivation for partial indices is this:
-if all of the queries you ask that can
-profitably use an index fall into a certain range, why build an index
-over the whole table and suffer the associated space/time costs?
-
-(There are other reasons too; see 
-<xref linkend="STON89b-full" endterm="STON89b"> for details.)
-
-<para>
-The machinery to build, update and query partial indices isn't too
-bad.  The hairy parts are index selection (which indices do I build?)
-and query optimization (which indices do I use?); i.e., the parts
-that involve deciding what predicate(s) match the workload/query in
-some useful way.  For those who are into database theory, the problems
-are basically analogous to the corresponding materialized view
-problems, albeit with different cost parameters and formulae.  These
-are, in the general case, hard problems for the standard ordinal 
-<acronym>SQL</acronym>
-types; they're super-hard problems with black-box extension types,
-because the selectivity estimation technology is so crude.
-
-<para>
-Check <xref linkend="STON89b-full" endterm="STON89b">,
-<xref linkend="OLSON93-full" endterm="OLSON93">,
-and
-<xref linkend="SESHADRI95-full" endterm="SESHADRI95">
-for more information.
+    </para>
+   </note>
+
+   <para>
+    A <firstterm>partial index</firstterm>
+    is an index built over a subset of a table; the subset is defined by
+    a predicate.  <productname>Postgres</productname>
+    supported partial indices with arbitrary
+    predicates.  I believe IBM's db2 for as/400 supports partial indices
+    using single-clause predicates.
+   </para>
+
+   <para>
+    The main motivation for partial indices is this:
+    if all of the queries you ask that can
+    profitably use an index fall into a certain range, why build an index
+    over the whole table and suffer the associated space/time costs?
+
+    (There are other reasons too; see 
+    <xref endterm="STON89b" linkend="STON89b-full"> for details.)
+   </para>
+
+   <para>
+    The machinery to build, update and query partial indices isn't too
+    bad.  The hairy parts are index selection (which indices do I build?)
+    and query optimization (which indices do I use?); i.e., the parts
+    that involve deciding what predicate(s) match the workload/query in
+    some useful way.  For those who are into database theory, the problems
+    are basically analogous to the corresponding materialized view
+    problems, albeit with different cost parameters and formulae.  These
+    are, in the general case, hard problems for the standard ordinal 
+    <acronym>SQL</acronym>
+    types; they're super-hard problems with black-box extension types,
+    because the selectivity estimation technology is so crude.
+   </para>
+
+   <para>
+    Check <xref endterm="STON89b" linkend="STON89b-full">,
+    <xref endterm="OLSON93" linkend="OLSON93-full">,
+    and
+    <xref endterm="SESHADRI95" linkend="SESHADRI95-full">
+    for more information.
+   </para>
+  </sect1>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/lisp.sgml b/doc/src/sgml/lisp.sgml
new file mode 100644 (file)
index 0000000..08f4aca
--- /dev/null
@@ -0,0 +1,104 @@
+ <chapter id="lisp">
+  <title id="lisp-title">Lisp Programming Interface</title>
+
+  <abstract>
+   <para>
+    <filename>pg.el</filename> is a socket-level interface to
+    <productname>Postgres</productname> for emacs.
+   </para>
+  </abstract>
+
+  <note>
+   <title>Author</title>
+   <para>
+    Written by
+    <ulink url="mailto:emarsden@mail.dotcom.fr">Eric Marsden</ulink>
+    on 21 Jul 1999.
+   </para>
+  </note>
+
+  <para>
+   <filename>pg.el</filename> is a socket-level interface to
+   <productname>Postgres</productname> for emacs (text
+   editor extraordinaire). The module is capable of type coercions from a
+   range of SQL types to the equivalent Emacs Lisp type. It currently
+   supports neither crypt or Kerberos authentication, nor large objects.
+  </para>
+
+  <para>
+   The code (version 0.2) is available under GNU GPL from
+   <ulink url="http://www.chez.com/emarsden/downloads/pg.el">
+    http://www.chez.com/emarsden/downloads/pg.el</ulink>
+  </para>
+
+  <para>
+Changes since last release:
+
+   <itemizedlist mark="bullet" spacing="compact">
+    <listitem>
+     <para>
+      now works with XEmacs (tested with Emacs 19.34 & 20.2, and XEmacs
+      20.4)
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      added functions to provide database metainformation (list of
+      databases, of tables, of columns)
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      arguments to `pg:result' are now :keywords
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      MULE-resistant
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      more self-testing code
+     </para>
+    </listitem>
+   </itemizedlist>
+  </para>
+
+  <para>
+   Please note that this is a programmer's API, and doesn't provide any
+   form of user interface. Example:
+
+   <programlisting>
+ (defun demo ()
+    (interactive)
+    (let* ((conn (pg:connect "template1" "postgres" "postgres"))
+           (res (pg:exec conn "SELECT * from scshdemo WHERE a = 42")))
+      (message "status is %s"   (pg:result res :status))
+      (message "metadata is %s" (pg:result res :attributes))
+      (message "data is %s"     (pg:result res :tuples))
+      (pg:disconnect conn)))
+   </programlisting>
+  </para>
+ </chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->
index a2452db..673adfb 100644 (file)
@@ -12,7 +12,7 @@
    <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
+   <literal>pg_operator</literal>.  Every entry in <literal>pg_operator</literal> includes
    the name of the procedure that implements the operator and the
    class <Acronym>OIDs</Acronym> of the input and output types.
   </Para>
index a0dfcc3..99c72d1 100644 (file)
@@ -1,105 +1,3 @@
-<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.28 1999/06/23 06:15:12 thomas Exp $
-
-Postgres integrated documentation.
-Other subset docs should be copied and shrunk from here.
-thomas 1998-02-23
-
-$Log: postgres.sgml,v $
-Revision 1.28  1999/06/23 06:15:12  thomas
-Add backup/restore info to Admin Guide.
-Split management chapter from start-ag.sgml to manage-ag.sgml.
-
-Revision 1.27  1999/06/03 04:21:49  thomas
-Markup changes for v6.5 release.
-Clean out duplicate stuff in odbc.sgml resulting from a faulty patch.
-
-Revision 1.26  1999/06/01 17:26:18  thomas
-Make sure that only one intro is included in the integrated doc.
-Multiple intros cause trouble since they have some section elements
- (e.g. "y2k.sgml") in common leading to duplicate labels.
-Include emacs formatting hints in the intro*.sgml sources.
-
-Revision 1.25  1999/05/27 15:49:08  thomas
-Markup fixes.
-Update for v6.5 release.
-
-Revision 1.24  1999/05/26 17:30:29  thomas
-Add chapters on CVS access, MVCC, SQL theory to the docs.
-Add an appendix with more details on date/time attributes and handling.
-Update most references to Postgres version numbers to 6.5,
- *except* for the porting list which will require a report
- from a successful installation to be updated.
-
-Revision 1.23  1999/05/22 02:27:24  thomas
-Finish initial markup of cvs.sgml, and include it in the programmer's guide
- and the integrated doc. Clean up other markup.
-
-Revision 1.22  1999/05/20 05:39:27  thomas
-Rearrange and consolidate the Admin Guide.
-Add reference pages for utilities and remove standalone chapters for same.
-Add material for an appendix on date/time properties, but not yet
- integrated with the User's Guide.
-Break up the former chapter on pg_options
- into Admin and Programmer's Guides.
-
-Revision 1.21  1999/05/04 02:19:20  thomas
-Include chapters on security and an intro to SQL.
-
-Revision 1.20  1999/04/06 15:41:13  thomas
-Fix markup to include all closing tags.
-Required by newest versions of DocBook and style sheets.
-
-Revision 1.19  1999/03/30 15:23:03  thomas
-Include libpq+.sgml in the doc set.
-Had been omitted from the integrated doc for no good reason.
-
-Revision 1.18  1999/02/13 03:52:46  thomas
-Include chapter on SQL language elements (keywords, etc).
-Should merge with or complement Stefan's Master's Thesis intro to SQL.
-
-Revision 1.17  1999/01/19 16:06:25  thomas
-Merge current.sgml into release.sgml so all release notes are in the same
- file. Per Bruce's preference. Go to it Bruce!
-No info yet for v6.4.2 or upcoming releases.
-
-Revision 1.16  1999/01/07 02:59:45  thomas
-Include installation instructions for WIN32 client-side libraries.
-From Magnus Hagander <mha@sollentuna.net>.
-
-Revision 1.15  1998/12/18 16:23:34  thomas
-Fix typos in rules.sgml.
-Add Emacs configuration block to postgres.sgml.
-
-Revision 1.14  1998/10/31 09:36:34  thomas
-Cleanup for v6.4 release.
-Make new file current.sgml to hold release info for the current release.
- Should be moved to release.sgml before filling with next release info.
-
-Revision 1.13  1998/10/30 19:37:09  thomas
-Minor editing and markup changes as a result of preparing the Postscript
- documentation for v6.4.
-Bigger updates to the installation instructions (install and config).
-
-Revision 1.12  1998/10/27 06:14:01  thomas
-Include configuration chapter with new info on configure and make.
-
-Revision 1.11  1998/10/25 00:24:31  thomas
-Add Y2K statement for intros.
-Make sure notation section is included in most intros.
-
-Revision 1.7-1.10  1998/10/21 05:31:52  thomas
-Include new information from Massimo. Rearrange ODBC docs.
-Add information for operator precedence.
-Split introduction sections into separate files to allow the legal notice
- and notation sections appear in all documents without having the history
- show up everplace too.
-Add full list of reserved and non-reserved key words in syntax.sgml.
-Add a separate chapter to the admin guide on security.
-Move SQL reference pages up into the User's Guide.
-
--->
-
 <!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
 
 <!entity about    SYSTEM "about.sgml">
@@ -123,8 +21,8 @@ Move SQL reference pages up into the User's Guide.
 <!entity datetime SYSTEM "datetime.sgml">
 <!entity environ  SYSTEM "environ.sgml">
 <!entity func     SYSTEM "func.sgml">
+<!entity indices  SYSTEM "indices.sgml">
 <!entity inherit  SYSTEM "inherit.sgml">
-<!entity keys     SYSTEM "keys.sgml">
 <!entity manage   SYSTEM "manage.sgml">
 <!entity mvcc     SYSTEM "mvcc.sgml">
 <!entity oper     SYSTEM "oper.sgml">
@@ -156,28 +54,29 @@ Move SQL reference pages up into the User's Guide.
 <!entity trouble   SYSTEM "trouble.sgml">
 
 <!-- programmer's guide -->
-<!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 ecpg     SYSTEM "ecpg.sgml">
+<!entity extend   SYSTEM "extend.sgml">
 <!entity func-ref SYSTEM "func-ref.sgml">
+<!entity gist     SYSTEM "gist.sgml">
+<!entity intro-pg SYSTEM "intro-pg.sgml">
+<!entity jdbc     SYSTEM "jdbc.sgml">
 <!entity libpq    SYSTEM "libpq.sgml">
 <!entity libpqpp  SYSTEM "libpq++.sgml">
 <!entity libpgtcl SYSTEM "libpgtcl.sgml">
-<!entity ecpg     SYSTEM "ecpg.sgml">
+<!entity lisp     SYSTEM "lisp.sgml">
+<!entity lobj     SYSTEM "lobj.sgml">
 <!entity odbc     SYSTEM "odbc.sgml">
-<!entity jdbc     SYSTEM "jdbc.sgml">
+<!entity rules    SYSTEM "rules.sgml">
+<!entity spi      SYSTEM "spi.sgml">
+<!entity trigger  SYSTEM "trigger.sgml">
+<!entity xaggr    SYSTEM "xaggr.sgml">
+<!entity xfunc    SYSTEM "xfunc.sgml">
+<!entity xindex   SYSTEM "xindex.sgml">
 <!entity xplang   SYSTEM "xplang.sgml">
+<!entity xoper    SYSTEM "xoper.sgml">
+<!entity xtypes   SYSTEM "xtypes.sgml">
 
 <!-- developer's guide -->
 <!entity arch-dev SYSTEM "arch-dev.sgml">
@@ -277,7 +176,7 @@ Your name here...
   &oper;
   &func;
   &typeconv;
-  &keys;
+  &indices;
   &array;
   &inherit;
   &mvcc;
@@ -341,7 +240,6 @@ Your name here...
    &trigger;
    &spi;
    &xplang;
-  <!-- &libpq; -->
  </Part>
 
  <part Id="part-interfaces">
@@ -359,6 +257,7 @@ Your name here...
    &libpgtcl;
    &odbc;
    &jdbc;
+   &lisp;
  </Part>
  
  <part Id="part-developer">
index 663e304..93ea1db 100644 (file)
@@ -1,9 +1,15 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.18 1999/06/23 06:21:19 thomas Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.19 1999/07/22 15:11:04 thomas Exp $
 
 Postgres Programmer's Guide.
 
 $Log: programmer.sgml,v $
+Revision 1.19  1999/07/22 15:11:04  thomas
+Complete merge of all old man page information.
+lisp.sgml is a placeholder for Eric Marsden's upcoming contribution.
+catalogs.sgml is not yet marked up or integrated.
+ It should perhaps become an appendix.
+
 Revision 1.18  1999/06/23 06:21:19  thomas
 Remove User's Guide entities since they were not being used.
 
@@ -34,28 +40,29 @@ Make new file current.sgml to hold release info for the current release.
 <!entity notation SYSTEM "notation.sgml">
 <!entity y2k      SYSTEM "y2k.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 ecpg     SYSTEM "ecpg.sgml">
+<!entity extend   SYSTEM "extend.sgml">
 <!entity func-ref SYSTEM "func-ref.sgml">
+<!entity gist     SYSTEM "gist.sgml">
+<!entity intro-pg SYSTEM "intro-pg.sgml">
+<!entity jdbc     SYSTEM "jdbc.sgml">
 <!entity libpq    SYSTEM "libpq.sgml">
 <!entity libpqpp  SYSTEM "libpq++.sgml">
 <!entity libpgtcl SYSTEM "libpgtcl.sgml">
-<!entity ecpg     SYSTEM "ecpg.sgml">
+<!entity lisp     SYSTEM "lisp.sgml">
+<!entity lobj     SYSTEM "lobj.sgml">
 <!entity odbc     SYSTEM "odbc.sgml">
-<!entity jdbc     SYSTEM "jdbc.sgml">
+<!entity rules    SYSTEM "rules.sgml">
+<!entity spi      SYSTEM "spi.sgml">
+<!entity trigger  SYSTEM "trigger.sgml">
+<!entity xaggr    SYSTEM "xaggr.sgml">
+<!entity xfunc    SYSTEM "xfunc.sgml">
+<!entity xindex   SYSTEM "xindex.sgml">
 <!entity xplang   SYSTEM "xplang.sgml">
+<!entity xoper    SYSTEM "xoper.sgml">
+<!entity xtypes   SYSTEM "xtypes.sgml">
 
 <!-- developer's guide -->
 <!entity arch-dev SYSTEM "arch-dev.sgml">
@@ -172,6 +179,7 @@ Disable it until we put in some info.
   &ecpg;
   &odbc;
   &jdbc;
+  &lisp;
  
 <!-- development -->
  
index 1539f98..85f9d08 100644 (file)
      </varlistentry>
     </variablelist>
    </para>
+
+   <Sect2>
+    <Title>Host-Based Access Control</Title>
+
+    <Para>
+.SH NAME
+$PGDATA/pg_hba.conf
+.SH DESCRIPTION
+
+     <firstterm>Host-based access control</firstterm>
+     is the name for the basic controls PostgreSQL
+     exercises on what clients are allowed to access a database and how
+     the users on those clients must authenticate themselves.
+    </para>
+
+    <para>
+     Each database system contains a file named
+     <filename>pg_hba.conf</filename>, in its <envar>PGDATA</envar>
+     directory, which controls who can connect to each database.
+    </para>
+
+    <para>
+     Every client accessing a database
+     <emphasis>must</emphasis>
+     be covered by one of
+     the entries in <filename>pg_hba.conf</filename>.
+     Otherwise all attempted connections from that
+     client will be rejected with a "User authentication failed" error
+     message.
+    </para>
+
+    <para>
+     The general format of the <filename>pg_hba.conf</filename>
+     file is of a set of records, one per
+     line.  Blank lines and lines beginning with a hash character
+     ("#") are ignored.  A record is
+     made up of a number of fields which are separated by spaces and/or tabs.
+    </para>
+
+    <para>
+     Connections from clients can be made using UNIX domain sockets or Internet
+     domain sockets (ie. TCP/IP).  Connections made using UNIX domain sockets
+     are controlled using records of the following format:
+
+     <synopsis>
+local <replaceable>database</replaceable> <replaceable>authentication method</replaceable>
+     </synopsis>
+
+     where
+
+     <simplelist>
+      <member>
+       <replaceable>database</replaceable>
+       specifies the database that this record applies to.  The value
+       <literal>all</literal>
+       specifies that it applies to all databases.
+      </member>
+      <member>
+       <replaceable>authentication method</replaceable>
+       specifies the method a user must use to authenticate themselves when
+       connecting to that database using UNIX domain sockets.  The different methods
+       are described below.
+      </member>
+     </simplelist>
+    </para>
+
+    <para>
+     Connections made using Internet domain sockets are controlled using records
+     of the following format.
+
+     <synopsis>
+host <replaceable>database</replaceable> <replaceable>TCP/IP address</replaceable> <replaceable>TCP/IP mask</replaceable> <replaceable>authentication method</replaceable>
+     </synopsis>
+    </para>
+
+    <para>
+     The <replaceable>TCP/IP address</replaceable>
+     is logically anded to both the specified
+     <replaceable>TCP/IP mask</replaceable>
+     and the TCP/IP address
+     of the connecting client.
+     If the two resulting values are equal then the
+     record is used for this connection.  If a connection matches more than one
+     record then the earliest one in the file is used.
+     Both the
+     <replaceable>TCP/IP address</replaceable>
+     and the
+     <replaceable>TCP/IP mask</replaceable>
+     are specified in dotted decimal notation.
+    </para>
+
+    <para>
+     If a connection fails to match any record then the
+     <firstterm>reject</firstterm>
+     authentication method is applied (see below).
+    </para>
+
+    <sect3>
+     <title>Authentication Methods</title>
+
+     <para>
+      The following authentication methods are supported for both UNIX and TCP/IP
+      domain sockets:
+
+      <variablelist>
+       <varlistentry>
+       <term>trust</term>
+       <listitem>
+        <para>
+         The connection is allowed unconditionally.
+        </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+       <term>reject</term>
+       <listitem>
+        <para>
+         The connection is rejected unconditionally.
+        </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+       <term>crypt</term>
+       <listitem>
+        <para>
+         The client is asked for a password for the user.  This is sent encrypted
+         (using <citetitle>crypt(3)</citetitle>)
+         and compared against the password held in the 
+         <filename>pg_shadow</filename> table.
+         If the passwords match, the connection is allowed.
+        </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+       <term>password</term>
+       <listitem>
+        <para>
+         The client is asked for a password for the user.  This is sent in clear
+         and compared against the password held in the
+         <filename>pg_shadow</filename> table.
+         If the passwords match, the connection is allowed.  An optional password file
+         may be specified after the
+         <literal>password</literal>
+         keyword which is used to match the supplied password rather than the pg_shadow
+         table.  See
+         <citerefentry><refentrytitle>pg_passwd</refentrytitle></citerefentry>.
+        </para>
+       </listitem>
+       </varlistentry>
+      </variablelist>
+     </para>
+
+     <para>
+      The following authentication methods are supported for TCP/IP
+      domain sockets only:
+
+      <variablelist>
+       <varlistentry>
+       <term>krb4</term>
+       <listitem>
+        <para>
+         Kerberos V4 is used to authenticate the user.
+        </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+       <term>krb5</term>
+       <listitem>
+        <para>
+         Kerberos V5 is used to authenticate the user.
+        </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+       <term>ident</term>
+       <listitem>
+        <para>
+         The ident server on the client is used to authenticate the user (RFC 1413).
+         An optional map name may be specified after the
+         <literal>ident</literal>
+         keyword which allows ident user names to be mapped onto
+         <productname>Postgres</productname> user names.
+         Maps are held in the file
+         <filename>$<envar>PGDATA</envar>/pg_ident.conf</filename>.
+        </para>
+       </listitem>
+       </varlistentry>
+      </variablelist>
+     </para>
+    </sect3>
+
+    <sect3>
+     <title>Examples</title>
+
+     <para>
+      <programlisting>
+# Trust any connection via UNIX domain sockets.
+local  trust
+# Trust any connection via TCP/IP from this machine.
+host   all     127.0.0.1       255.255.255.255         trust
+# We don't like this machine.
+host   all     192.168.0.10    255.255.255.0           reject
+# This machine can't encrypt so we ask for passwords in clear.
+host   all     192.168.0.3     255.255.255.0           password
+# The rest of this group of machines should provide encrypted passwords.
+host   all     192.168.0.0     255.255.255.0           crypt
+      </programlisting>
+     </para>
+    </sect3>
+   </sect2>
   </sect1>
 
   <sect1>
      have to explicitly insert/update the <literal>pg_group table</literal>.
      For example:
 
-        jolly=> insert into pg_group (groname, grosysid, grolist)
-        jolly=>     values ('posthackers', '1234', '{5443, 8261}');
-        INSERT 548224
-        jolly=> grant insert on foo to group posthackers;
-        CHANGE
-        jolly=>
-
-   The fields in pg_group are:
-     * groname: the group name. This a name and should be purely
-       alphanumeric. Do not include underscores or other punctuation.
-     * grosysid: the group id. This is an int4. This should be unique for
-       each group.
-     * grolist: the list of pg_user id's that belong in the group. This
-       is an int4[].
+     <programlisting>
+jolly=> insert into pg_group (groname, grosysid, grolist)
+jolly=>     values ('posthackers', '1234', '{5443, 8261}');
+INSERT 548224
+jolly=> grant insert on foo to group posthackers;
+CHANGE
+jolly=>
+     </programlisting>
+    </para>
+
+    <para>
+     The fields in <filename>pg_group</filename> are:
+
+     <variablelist>
+      <varlistentry>
+       <term>groname</term>
+       <listitem>
+       <para>
+        The group name. This a name and should be purely
+        alphanumeric. Do not include underscores or other punctuation.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>grosysid</term>
+       <listitem>
+       <para>
+        The group id. This is an int4. This should be unique for
+        each group.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>grolist</term>
+       <listitem>
+       <para>
+        The list of pg_user id's that belong in the group. This
+        is an int4[].
+       </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
     </para>
    </sect2>
 
index e9c3467..ee27118 100644 (file)
@@ -3,14 +3,18 @@
 
   <abstract>
    <para>
-    <acronym>SQL</acronym> manipulates sets of data. The language is
-    composed of various <firstterm>key words</firstterm>. Arithmetic
-    and procedural expressions are allowed. We will cover these topics
-    in this chapter; subsequent chapters will include details on data
-    types, functions, and operators.
+    A description of the general syntax of SQL.
    </para>
   </abstract>
 
+  <para>
+   <acronym>SQL</acronym> manipulates sets of data. The language is
+   composed of various <firstterm>key words</firstterm>. Arithmetic
+   and procedural expressions are allowed. We will cover these topics
+   in this chapter; subsequent chapters will include details on data
+   types, functions, and operators.
+  </para>
+
   <sect1>
    <title>Key Words</title>
 
@@ -230,7 +234,7 @@ MAXVALUE MINVALUE MODE
 NOCREATEDB NOCREATEUSER NOTHING NOTNULL 
 OIDS OPERATOR 
 PASSWORD PROCEDURAL
-RECIPE RENAME  RETURNS ROW RULE
+RECIPE RENAME RETURNS ROW RULE
 SEQUENCE SERIAL SHARE START STATEMENT STDIN STDOUT 
 TRUSTED 
 VALID VERSION
@@ -303,17 +307,454 @@ UNCOMMITTED UNNAMED
   </sect1>
 
   <sect1>
+   <title>Comments</title>
+
+   <para>
+    A <firstterm>comment</firstterm>
+    is an arbitrary sequence of characters following double dashes up to the end
+    of the line.  We also support double-slashes as comments, e.g.:
+
+    <programlisting>
+-- This is a standard SQL comment
+// And this is another supported comment style, like C++
+    </programlisting>
+
+We also support C-style block comments, e.g.:
+
+    <programlisting>
+/* multi
+   line
+   comment */
+    </programlisting>
+   </para>
+  </sect1>
+
+  <sect1>
+   <title>Names</title>
+
+   <para>
+    Names in SQL are sequences of less than NAMEDATALEN alphanumeric characters,
+    starting with an alphabetic character.  By default, NAMEDATALEN is set
+    to 32, but at the time the system is built, NAMEDATALEN can be changed
+    by changing the #ifdef in src/backend/include/postgres.h.  Underscore
+    ("_") is considered an alphabetic character.
+   </para>
+  </sect1>
+
+  <sect1>
+   <title>Constants</title>
+
+   <para>
+    There are six types of
+    <firstterm>constants</firstterm>
+    for use in SQL.  They are described below.
+   </para>
+
+   <sect2>
+    <title>String Constants</title>
+
+    <para>
+     <firstterm>Strings</firstterm>
+     in SQL are arbitrary sequences of ASCII characters bounded by single
+     quotes ("'", e.g. 'This is a string').
+     Uppercase alphabetics within strings are accepted
+     literally.  Non-printing characters may be embedded within strings by
+     prepending them with a backslash
+     ("\"; e.g. "\<replaceable>tab</replaceable>".
+     SQL92 allows single quotes to be embedded in strings by typing two 
+     adjacent single quotes (e.g. 'Dianne''s horse'), and for
+     historical reasons <productname>Postgres</productname> also allows 
+     single quotes to be escaped with a backslash
+     (e.g. 'Dianne\'s horse').
+    </para>
+
+    <para>
+     Because of the limitations on
+     instance sizes, string constants are currently limited to a length of
+     a little less than 8192 bytes.  Larger strings may be handled using the
+     Postgres Large Object interface.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Integer Constants</title>
+
+    <para>
+     <firstterm>Integer constants</firstterm>
+     in SQL are collection of ASCII digits with no decimal point.  Legal
+     values range from -2147483648 to +2147483647.  This will vary
+     depending on the operating system and host machine.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Floating Point Constants</title>
+
+    <para>
+     <firstterm>Floating point constants</firstterm>
+     consist of an integer part, a decimal point, and a fraction part or
+     scientific notation of the following format:
+
+     <synopsis>
+{<replaceable>dig</replaceable>}.{<replaceable>dig</replaceable>} [e [+-] {<replaceable>dig</replaceable>}]
+     </synopsis>
+
+     where <replaceable>dig</replaceable> is one or more digits.
+     You must include at least one <replaceable>dig</replaceable> after the
+     period and after the [+-] if you use those options.  An exponent with
+     a missing mantissa has a mantissa of 1 inserted.  There may be no
+     extra characters embedded in the string.  
+     Floating point constaints are of type float8.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Constants of Postgres User-Defined Types</title>
+
+    <para>
+     A constant of an
+     <emphasis>arbitrary</emphasis>
+     type can be entered using the notations:
+
+     <synopsis>
+<replaceable>type</replaceable> '<replaceable>string</replaceable>'
+'<replaceable>string</replaceable>'::<replaceable>type</replaceable>
+CAST '<replaceable>string</replaceable>' AS <replaceable>type</replaceable>
+     </synopsis>
+
+     The value inside the string is passed to the input
+     conversion routine for the type called type-name. The result is a
+     constant of the indicated type.  The explicit typecast may be omitted
+     if there is no ambiguity as to the type the constant must be, in which
+     case it is automatically coerced.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Array constants</title>
+
+    <para>
+     <firstterm>Array constants</firstterm>
+     are arrays of any Postgres type, including other arrays, string
+     constants, etc.  The general format of an array constant is the
+     following:
+
+     <synopsis>
+{<replaceable>val1</replaceable><replaceable>delim</replaceable><replaceable>val2</replaceable><replaceable>delim</replaceable>}
+     </synopsis>
+
+     where <replaceable>delim</replaceable>
+     is the delimiter for the type stored in the <literal>pg_type</literal> class.
+     (For built-in types, this is the comma character (",").  An
+     example of an array constant is
+
+     <programlisting>
+{{1,2,3},{4,5,6},{7,8,9}}
+     </programlisting>
+
+     This constant is a two-dimensional, 3 by 3 array consisting of three
+     sub-arrays of integers.
+    </para>
+
+    <para>
+     Individual array elements can and should be placed between quotation
+     marks whenever possible to avoid ambiguity problems with respect to
+     leading white space.
+    </para>
+   </sect2>
+  </sect1>
+
+  <sect1>
+   <title>Fields and Columns</title>
+
+   <sect2>
+    <title>Fields</title>
+
+    <para>
+     A <firstterm>field</firstterm>
+     is either an attribute of a given class or one of the following:
+
+     <variablelist>
+      <varlistentry>
+       <term>oid</term>
+       <listitem>
+       <para>
+        stands for the unique identifier of an instance which is added by
+        Postgres to all instances automatically. Oids are not reused and are 32
+        bit quantities.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>xmin</term>
+       <listitem>
+       <para>
+        The identity of the inserting transaction.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>xmax</term>
+       <listitem>
+       <para>
+        The identity of the deleting transaction.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>cmin</term>
+       <listitem>
+       <para>
+        The command identifier within the transaction.
+       </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>cmax</term>
+       <listitem>
+       <para>
+        The identity of the deleting command.
+       </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </para>
+
+    <para>
+     For further information on these fields consult
+     <xref linkend="STON87a" endterm="STON87a">.
+     Times are represented internally as instances of the
+     <literal>abstime</literal>
+     data type.  Transaction and command identifiers are 32 bit quantities.
+     Transactions are assigned sequentially starting at 512.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Columns</title>
+
+    <para>
+     A <firstterm>column</firstterm> is a construct of the form:
+
+     <synopsis>
+<replaceable>instance</replaceable>{.<replaceable>composite_field</replaceable>}.<replaceable>field</replaceable> `['<replaceable>number</replaceable>`]'
+     </synopsis>
+
+     <replaceable>instance</replaceable>
+     identifies a particular class and can be thought of as standing for
+     the instances of that class.  An instance variable is either a class
+     name, a surrogate for a class defined by means of a FROM clause,
+     or the keyword NEW or CURRENT.
+     NEW and CURRENT can only appear in the action portion of a rule, while
+     other instance variables can be used in any SQL statement.
+     <replaceable>composite_field</replaceable>
+     is a field of of one of the Postgres composite types,
+     while successive composite fields address attributes in the
+     class(s) to which the composite field evaluates.  Lastly,
+     <replaceable>field</replaceable>
+     is a normal (base type) field in the class(s) last addressed.  If
+     <replaceable>field</replaceable>
+     is of type <literal>array</literal>,
+     then the optional <replaceable>number</replaceable>
+     designator indicates a specific element in the array.  If no number is
+     indicated, then all array elements are returned.
+    </para>
+   </sect2>
+  </sect1>
+
+  <sect1>
+   <title>Operators</title>
+
+   <para>
+    Any built-in system, or user-defined operator may be used in SQL.
+    For the list of built-in and system operators consult
+    <xref linkend="operators" endterm="operators">.
+    For a list of user-defined operators consult your system administrator
+    or run a query on the <literal>pg_operator</literal> class.
+    Parentheses may be used for arbitrary grouping of operators in expressions.
+   </para>
+  </sect1>
+
+  <sect1>
    <title>Expressions</title>
 
    <para>
     <acronym>SQL92</acronym> allows <firstterm>expressions</firstterm>
-    to transform data in expressions. Expressions may contain operators
+    to transform data in tables. Expressions may contain operators
     (see <xref linkend="operators-title" endterm="operators-title">
     for more details) and functions
     (<xref linkend="functions-title" endterm="functions-title"> has
     more information).
+   </para>
 
+   <para>
+    An expression is one of the following:
+
+    <simplelist>
+     <member>( a_expr )</member>
+     <member>constant</member>
+     <member>attribute</member>
+     <member><replaceable>a_expr</replaceable> <replaceable>binary_operator</replaceable> <replaceable>a_expr</replaceable></member>
+     <member><replaceable>a_expr</replaceable> <replaceable>right_unary_operator</replaceable></member>
+     <member><replaceable>left_unary_operator</replaceable> <replaceable>a_expr</replaceable></member>
+     <member>parameter</member>
+     <member>functional expressions</member>
+     <member>aggregate expressions</member>
+    </simplelist>
+   </para>
+
+   <para>
+    We have already discussed constants and attributes.  The two kinds of
+    operator expressions indicate respectively binary and left_unary
+    expressions.  The following sections discuss the remaining options.
    </para>
+
+   <sect2>
+    <title>Parameters</title>
+
+    <para>
+     A <firstterm>parameter</firstterm>
+     is used to indicate a parameter in a SQL function.  Typically this
+     is used in SQL function definition statement.  The form of a
+     parameter is:
+
+     <synopsis>
+$<replaceable class="parameter">number</replaceable>
+     </synopsis>
+    </para>
+
+    <para>
+     For example, consider the definition of a function,
+     <function>dept</function>, as
+
+     <programlisting>
+CREATE FUNCTION dept (name)
+       RETURNS dept
+       AS 'select * from 
+           dept where name=$1'
+       LANGUAGE 'sql';
+     </programlisting>
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Functional Expressions</title>
+
+    <para>
+     A <firstterm>functional expression</firstterm>
+     is the name of a legal SQL function, followed by its argument list
+     enclosed in parentheses:
+
+     <synopsis>
+<replaceable>function</replaceable> (<replaceable>a_expr</replaceable> [, <replaceable>a_expr</replaceable> )
+     </synopsis>
+    </para>
+
+    <para>
+     For example, the following computes the square root of an employee
+     salary:
+
+     <programlisting>
+sqrt(emp.salary)
+     </programlisting>
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Aggregate Expression</title>
+
+    <para>
+     An <firstterm>aggregate expression</firstterm>
+     represents a simple aggregate (i.e., one that computes a single value)
+     or an aggregate function (i.e., one that computes a set of values).
+     The syntax is the following:
+
+     <synopsis>
+<replaceable>aggregate_name</replaceable> (<replaceable>attribute</replaceable>)
+     </synopsis>
+
+     where <replaceable>aggregate_name</replaceable>
+     must be a previously defined aggregate.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Target List</title>
+
+    <para>
+     A <firstterm>target list</firstterm>
+     is a parenthesized, comma-separated list of one or more elements, each
+     of which must be of the form:
+
+     <synopsis>
+<replaceable>a_expr</replaceable> [ AS <replaceable>result_attname</replaceable> ]
+     </synopsis>
+
+     where <replaceable>result_attname</replaceable>
+     is the name of the attribute to be created (or an
+     already existing attribute name in the case of update statements.)  If
+     <replaceable>result_attname</replaceable>
+     is not present, then 
+     <replaceable>a_expr</replaceable>
+     must contain only one attribute name which is assumed to be the name
+     of the result field.  In <productname>Postgres</productname>
+     default naming is only used if
+     <replaceable>a_expr</replaceable>
+     is an attribute.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Qualification</title>
+
+    <para>
+     A <firstterm>qualification</firstterm>
+     consists of any number of clauses connected by the logical operators:
+
+     <simplelist>
+      <member>NOT</member>
+      <member>AND</member>
+      <member>OR</member>
+     </simplelist>
+
+     A clause is an <replaceable>a_expr</replaceable>
+     that evaluates to a <literal>boolean</literal> over a set of instances.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>From List</title>
+
+    <para>
+     The <firstterm>from list</firstterm>
+     is a comma-separated list of <firstterm>from expressions</firstterm>.
+     Each "from expression" is of the form:
+
+     <synopsis>
+[ <replaceable>class_reference</replaceable> ] <replaceable>instance_variable</replaceable>
+       {, [ <replaceable>class_ref</replaceable> ] <replaceable>instance_variable</replaceable>... }
+     </synopsis>
+
+     where <replaceable>class_reference</replaceable>
+     is of the form
+
+     <synopsis>
+<replaceable>class_name</replaceable> [ * ]
+     </synopsis>
+
+     The "from expression"
+     defines one or more instance variables to range over the class
+     indicated in <replaceable>class_reference</replaceable>.
+     One can also request 
+     the instance variable to range over all classes that are beneath the
+     indicated class in the inheritance hierarchy by postpending the
+     designator asterisk ("*").
+    </para>
+   </sect2>
   </sect1>
  </chapter>
 
index 3323e16..0bb677c 100644 (file)
@@ -1,56 +1,3 @@
-<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/Attic/user.sgml,v 1.12 1999/06/03 04:21:51 thomas Exp $
-
-Postgres User's Manual.
-Derived from postgres.sgml.
-thomas 1998-02-24
-
-$Log: user.sgml,v $
-Revision 1.12  1999/06/03 04:21:51  thomas
-Markup changes for v6.5 release.
-Clean out duplicate stuff in odbc.sgml resulting from a faulty patch.
-
-Revision 1.11  1999/05/26 17:30:30  thomas
-Add chapters on CVS access, MVCC, SQL theory to the docs.
-Add an appendix with more details on date/time attributes and handling.
-Update most references to Postgres version numbers to 6.5,
- *except* for the porting list which will require a report
- from a successful installation to be updated.
-
-Revision 1.10  1999/05/22 02:27:25  thomas
-Finish initial markup of cvs.sgml, and include it in the programmer's guide
- and the integrated doc. Clean up other markup.
-
-Revision 1.9  1999/05/20 05:39:29  thomas
-Rearrange and consolidate the Admin Guide.
-Add reference pages for utilities and remove standalone chapters for same.
-Add material for an appendix on date/time properties, but not yet
- integrated with the User's Guide.
-Break up the former chapter on pg_options
- into Admin and Programmer's Guides.
-
-Revision 1.8  1999/05/04 02:26:06  thomas
-Include new introductory chapter on SQL from Stefan S.
-Should this be in the tutorial instead?
-
-Revision 1.7  1998/10/30 19:37:16  thomas
-Minor editing and markup changes as a result of preparing the Postscript
- documentation for v6.4.
-Bigger updates to the installation instructions (install and config).
-
-Revision 1.6  1998/09/30 05:41:54  thomas
-Clean up pages. Add information for operator precedence.
-Split introduction sections into separate files to allow the legal notice
- and notation sections appear in all documents without having the history
- show up everplace too.
-Add full list of reserved and non-reserved key words in syntax.sgml.
-Add a separate chapter to the admin guide on security.
-
-Revision 1.5  1998/08/17 16:20:32  thomas
-Move SQL reference pages up into the User's Guide.
-
--->
-
 <!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
 
 <!entity about    SYSTEM "about.sgml">
@@ -67,9 +14,9 @@ Move SQL reference pages up into the User's Guide.
 <!entity datetime SYSTEM "datetime.sgml">
 <!entity environ  SYSTEM "environ.sgml">
 <!entity func     SYSTEM "func.sgml">
+<!entity indices  SYSTEM "indices.sgml">
 <!entity inherit  SYSTEM "inherit.sgml">
 <!entity intro    SYSTEM "intro.sgml">
-<!entity keys     SYSTEM "keys.sgml">
 <!entity manage   SYSTEM "manage.sgml">
 <!entity mvcc     SYSTEM "mvcc.sgml">
 <!entity oper     SYSTEM "oper.sgml">
@@ -157,7 +104,7 @@ Your name here...
  &oper;
  &func;
  &typeconv;
- &keys;
+ &indices;
  &array;
  &inherit;
  &mvcc;
index a59d15d..036d029 100644 (file)
-<Chapter Id="xfunc">
-<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>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>:
+ <chapter id="xfunc">
+  <title id="xfunc-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.
+  </para>
+
+  <para>
+   <productname>Postgres</productname>  <acronym>SQL</acronym>  
+   provides  three types of functions:
+
+   <itemizedlist>
+    <listitem>
+     <para>
+      query language functions 
+      (functions written in <acronym>SQL</acronym>)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      procedural language 
+      functions (functions written in, for example, PLTCL or PLSQL)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      programming  
+      language  functions  (functions  written in a compiled 
+      programming language such as <acronym>C</acronym>)
+     </para>
+    </listitem>
+   </itemizedlist>
+
+   Every kind
+   of  function  can take a base type, a composite type or
+   some combination as arguments (parameters).   In  addition, 
+   every kind of function can return a base type or
+   a composite type.  It's easiest 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>funcs.c</filename>.
+  </para>
+
+  <sect1>
+   <title>Query Language (<acronym>SQL</acronym>) Functions</title>
+
+   <para>
+    SQL functions execute an arbitrary list of SQL queries, returning
+    the results of the last query in the list.  SQL functions in general
+    return sets.  If their returntype is not specified as a
+    <literal>setof</literal>,
+    then an arbitrary element of the last query's result will be returned.
+   </para>
+
+   <para>
+    The body of a SQL function following AS
+    should be a list of queries separated by whitespace characters and
+    bracketed within quotation marks.  Note that quotation marks used in
+    the queries must be escaped, by preceding them with two
+    backslashes.
+   </para>
+
+   <para>
+    Arguments to the SQL function may be referenced in the queries using
+    a $n syntax: $1 refers to the first argument, $2 to the second, and so
+    on.  If an argument is complex, then a <firstterm>dot</firstterm>
+    notation (e.g. "$1.emp") may be
+    used to access attributes of the argument or
+    to invoke functions.
+   </para>
+
+   <sect2>
+    <title>Examples</title>
+
+    <para>
+     To illustrate a simple SQL function, consider the following,
+     which might be used to debit a bank account:
+
+     <programlisting>
+create function TP1 (int4, float8) returns int4
+    as 'update BANK set balance = BANK.balance - $2
+        where BANK.acctountno = $1
+        select(x = 1)'
+    language 'sql';
+     </programlisting>
+
+     A user could execute this function to debit account 17 by $100.00 as
+     follows:
+
+     <programlisting>
+select (x = TP1( 17,100.0));
+     </programlisting>
+    </para>
+
+    <para>
+     The following more interesting example takes a single argument of type
+     EMP, and retrieves multiple results:
+
+     <programlisting>
+select function hobbies (EMP) returns set of HOBBIES
+    as 'select (HOBBIES.all) from HOBBIES
+        where $1.name = HOBBIES.person'
+    language 'sql';
+     </programlisting>
+    </para>
+   </sect2>
+
+   <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>
+     <programlisting>
     CREATE FUNCTION one() RETURNS int4
      AS 'SELECT 1 as RESULT' LANGUAGE 'sql';
 
          +-------+
          |1      |
          +-------+
-</ProgramListing>
-
-</Para>
-<Para>
+     </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  
+    </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>
+     and $2:
+
+     <programlisting>
     CREATE FUNCTION add_em(int4, int4) RETURNS int4
      AS 'SELECT $1 + $2;' LANGUAGE 'sql';
 
          +-------+
          |3      |
          +-------+
-</ProgramListing>
-</Para>
-</sect2>
+     </programlisting>
+    </para>
+   </sect2>
 
-<Sect2>
-<Title><Acronym>SQL</Acronym> Functions on Composite Types</Title>
+   <sect2>
+    <title><acronym>SQL</acronym> Functions on Composite Types</title>
 
-<Para>
+    <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>
+     salary would be if it were doubled:
+
+     <programlisting>
     CREATE FUNCTION double_salary(EMP) RETURNS int4
      AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql';
 
          +-----+-------+
          |Sam  | 2400  |
          +-----+-------+
-</ProgramListing>
-</para>
-<Para>
+     </programlisting>
+    </para>
+    <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>
+     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
          +----------+
          |Sam       |
          +----------+
-</ProgramListing>
-</para>
-<Para>
+     </programlisting>
+    </para>
+    <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>
+
+     <programlisting>
     CREATE FUNCTION new_emp() RETURNS EMP
      AS 'SELECT \'None\'::text AS name,
       1000 AS salary,
       25 AS age,
        \'(2,2)\'::point AS cubicle'
       LANGUAGE 'sql';
-</ProgramListing>
-
-</Para>
-<Para>
+     </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>
-      <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>
-<ListItem>
-<Para>
-When calling a function that returns an instance, we
+
+     <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>
+      <listitem>
+       <para>
+       You must typecast the expressions (using ::) very carefully 
+       or you will see  the  following error:
+
+       <programlisting>
+        <computeroutput>
+WARN::function declared to return type EMP does not retrieve (EMP.*)
+        </computeroutput>
+       </programlisting>
+       </para>
+      </listitem>
+      <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>
+
+       <programlisting>
     SELECT name(new_emp()) AS nobody;
 
             +-------+
@@ -184,35 +269,35 @@ When calling a function that returns an instance, we
             +-------+
             |None   |
             +-------+
-</ProgramListing>
-</Para>
-      </ListItem>
-<ListItem>
-<Para>
-The reason why, in general, we must use the function
+       </programlisting>
+       </para>
+      </listitem>
+      <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>
+
+       <programlisting>
             SELECT new_emp().name AS nobody;
             WARN:parser: syntax error at or near "."
-</ProgramListing>
-</Para>
-      </ListItem>
-</ItemizedList>
-</para>     
-<Para>
-     Any collection of commands in the  <Acronym>SQL</Acronym>  query  
+       </programlisting>
+       </para>
+      </listitem>
+     </itemizedlist>
+    </para>     
+    <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
+     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>
+
+     <programlisting>
     CREATE FUNCTION clean_EMP () RETURNS int4
      AS 'DELETE FROM EMP WHERE EMP.salary &lt;= 0;
     SELECT 1 AS ignore_this'
@@ -226,74 +311,312 @@ The reason why, in general, we must use the function
          |1 |
          +--+
          
-</ProgramListing>
-</Para>
-</sect2>
-</sect1>
+     </programlisting>
+    </para>
+   </sect2>
+  </sect1>
+
+  <sect1>
+   <title>Procedural Language Functions</title>
+
+   <para>
+    Procedural languages aren't built into Postgres. They are offered
+    by loadable modules. Please refer to the documentation for the
+    PL in question for details about the syntax and how the AS
+    clause is interpreted by the PL handler.
+   </para>
 
-<Sect1>
-<Title>Programming Language Functions</Title>
+   <para>
+    There are two procedural languages available with the standard
+    <productname>Postgres</productname> distribution (PLTCL and PLSQL), and other
+    languages can be defined.
+    Refer to <xref linkend="xplang-title" endterm="xplang-title"> for
+    more information.
+   </para>
+  </sect1>
 
-<Sect2>
-<Title>Programming Language Functions on Base Types</Title>
+  <sect1>
+   <title>Internal Functions</title>
 
-<Para>
-     Internally, <ProductName>Postgres</ProductName> regards a
+   <para>
+    Internal functions are functions written in C which have been statically
+    linked into the <productname>Postgres</productname> backend
+    process. The AS
+    clause gives the C-language name of the function, which need not be the
+    same as the name being declared for SQL use.
+    (For reasons of backwards compatibility, an empty AS
+    string is accepted as meaning that the C-language function name is the
+    same as the SQL name.)  Normally, all internal functions present in the
+    backend are declared as SQL functions during database initialization,
+    but a user could use <command>CREATE FUNCTION</command>
+    to create additional alias names for an internal function.
+   </para>
+  </sect1>
+
+  <sect1>
+   <title>Compiled (C) Language Functions</title>
+
+   <para>
+    Functions written in C can be defined to Postgres, which will dynamically
+    load them into its address space.  The AS
+    clause gives the full path name of the object file that contains the
+    function.  This file is loaded either using
+    load(l)
+    or automatically the first time the function is necessary for
+    execution. Repeated execution of a function will cause negligible
+    additional overhead, as the function will remain in a main memory
+    cache.
+   </para>
+
+   <para>
+    The string which specifies the object file (the string in the AS clause)
+    should be the <emphasis>full path</emphasis>
+    of the object code file for the function, bracketed by quotation
+    marks.  (<productname>Postgres</productname> will not compile a
+    function automatically; it must
+    be compiled before it is used in a CREATE FUNCTION
+    command.  See below for additional information.)
+   </para>
+
+   <sect2>
+    <title>C Language Functions on Base Types</title>
+
+    <para>
+     The following table gives the C type required for parameters in the C
+     functions that will be loaded into Postgres.  The "Defined In"
+     column gives the actual header file (in the
+     <filename>.../src/backend/</filename>
+     directory) that the equivalent C type is defined.  However, if you
+     include <filename>utils/builtins.h</filename>,
+     these files will automatically be
+     included.
+
+     <table tocentry="1">
+      <title>Equivalent C Types
+       for Built-In <productname>Postgres</productname> Types</title>
+      <titleabbrev>Equivalent C Types</titleabbrev>
+      <tgroup cols="3">
+       <thead>
+       <row>
+        <entry>
+         Built-In Type
+        </entry>
+        <entry>
+         C Type
+        </entry>
+        <entry>
+         Defined In
+        </entry>
+       </row>
+       </thead>
+       <tbody>
+       <row>
+        <entry>abstime</entry>
+        <entry>AbsoluteTime</entry>
+        <entry>utils/nabstime.h</entry>
+       </row>
+       <row>
+        <entry>bool</entry>
+        <entry>bool</entry>
+        <entry>include/c.h</entry>
+       </row>
+       <row>
+        <entry>box</entry>
+        <entry>(BOX *)</entry>
+        <entry>utils/geo-decls.h</entry>
+       </row>
+       <row>
+        <entry>bytea</entry>
+        <entry>(bytea *)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>char</entry>
+        <entry>char</entry>
+        <entry>N/A</entry>
+       </row>
+       <row>
+        <entry>cid</entry>
+        <entry>CID</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>datetime</entry>
+        <entry>(DateTime *)</entry>
+        <entry>include/c.h or include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>int2</entry>
+        <entry>int2</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>int28</entry>
+        <entry>(int28 *)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>int4</entry>
+        <entry>int4</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>float4</entry>
+        <entry>float32 or (float4 *)</entry>
+       <entry>include/c.h or include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>float8</entry>
+        <entry>float64 or (float8 *)</entry>
+        <entry>include/c.h or include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>lseg</entry>
+        <entry>(LSEG *)</entry>
+        <entry>include/geo-decls.h</entry>
+       </row>
+       <row>
+        <entry>name</entry>
+        <entry>(Name)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>oid</entry>
+        <entry>oid</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>oid8</entry>
+        <entry>(oid8 *)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>path</entry>
+        <entry>(PATH *)</entry>
+        <entry>utils/geo-decls.h</entry>
+       </row>
+       <row>
+        <entry>point</entry>
+        <entry>(POINT *)</entry>
+        <entry>utils/geo-decls.h</entry>
+       </row>
+       <row>
+        <entry>regproc</entry>
+        <entry>regproc or REGPROC</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>reltime</entry>
+        <entry>RelativeTime</entry>
+        <entry>utils/nabstime.h</entry>
+       </row>
+       <row>
+        <entry>text</entry>
+        <entry>(text *)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>tid</entry>
+        <entry>ItemPointer</entry>
+        <entry>storage/itemptr.h</entry>
+       </row>
+       <row>
+        <entry>timespan</entry>
+        <entry>(TimeSpan *)</entry>
+        <entry>include/c.h or include/postgres.h</entry>
+       </row>
+       <row>
+        <entry>tinterval</entry>
+        <entry>TimeInterval</entry>
+        <entry>utils/nabstime.h</entry>
+       </row>
+       <row>
+        <entry>uint2</entry>
+        <entry>uint16</entry>
+        <entry>include/c.h</entry>
+       </row>
+       <row>
+        <entry>uint4</entry>
+        <entry>uint32</entry>
+        <entry>include/c.h</entry>
+       </row>
+       <row>
+        <entry>xid</entry>
+        <entry>(XID *)</entry>
+        <entry>include/postgres.h</entry>
+       </row>
+       </tbody>
+      </tgroup>
+     </table>
+    </para>
+
+    <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 
+     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>
-<ListItem><Para>pass by reference, fixed-length</Para>
-      </ListItem>
-<ListItem><Para>pass by reference, variable-length</Para>
-      </ListItem>
-</ItemizedList>
-</Para>
-
-<Para>
+
+     <itemizedlist>
+      <listitem>
+       <para>
+       pass by value, fixed-length
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+       pass by reference, fixed-length
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+       pass by reference, variable-length
+       </para>
+      </listitem>
+     </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 
+     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  
+     <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 
+     <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>
+     the  <acronym>int4</acronym>  type  on  <acronym>UNIX</acronym>
      machines might be:
      
-<ProgramListing>
-    /* 4-byte integer, passed by value */
-    typedef int int4;
-</ProgramListing>
-</Para>
+     <programlisting>
+/* 4-byte integer, passed by value */
+typedef int int4;
+     </programlisting>
+    </para>
 
-<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 a <ProductName>Postgres</ProductName> type:
+     implementation of a <productname>Postgres</productname> type:
      
-<ProgramListing>
-         /* 16-byte structure, passed by reference */
-    typedef struct
-    {
-        double  x, y;
-    } Point;
-</ProgramListing>
-</Para>
-
-<Para>
+     <programlisting>
+/* 16-byte structure, passed by reference */
+typedef struct
+{
+    double  x, y;
+} Point;
+     </programlisting>
+    </para>
+
+    <para>
      Only  pointers  to  such types can be used when passing
-     them in and out of <ProductName>Postgres</ProductName> functions.
+     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
@@ -302,42 +625,42 @@ The reason why, in general, we must use the function
      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>
+
+     <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 
+     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"
-         ...
-         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>
+     <programlisting>
+#include "postgres.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>
+     Suppose <filename>funcs.c</filename> look like:
+
+     <programlisting>
          #include &lt;string.h&gt;
          #include "postgres.h"
 
@@ -394,56 +717,58 @@ The reason why, in general, we must use the function
              strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ);
              return (new_text);
          }
-</ProgramListing>
-</Para>
+     </programlisting>
+    </para>
 
-<Para>
-     On <Acronym>OSF/1</Acronym> we would type:
+    <para>
+     On <acronym>OSF/1</acronym> we would type:
      
-<ProgramListing>
+     <programlisting>
          CREATE FUNCTION add_one(int4) RETURNS int4
-              AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c';
+              AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
 
          CREATE FUNCTION makepoint(point, point) RETURNS point
-              AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c';
+              AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
     
          CREATE FUNCTION concat_text(text, text) RETURNS text
-              AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c';
+              AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
                                   
          CREATE FUNCTION copytext(text) RETURNS text
-              AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c';
-</ProgramListing>
-</Para>
+              AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
+     </programlisting>
+    </para>
 
-<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>
+    </para>
+   </sect2>
 
-<Sect2>
-<Title>Programming Language Functions on Composite Types</Title>
+   <sect2>
+    <title>C Language Functions on Composite Types</title>
 
-<Para>
+    <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  
+     Therefore,  <productname>Postgres</productname>  provides  
      a  procedural interface for accessing fields of composite types  
-     from C.  As <ProductName>Postgres</ProductName> processes 
+     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>.
+     function as an  opaque  structure of type <acronym>TUPLE</acronym>.
      Suppose we want to write a function to answer the query
-<ProgramListing>
+
+     <programlisting>
          * SELECT name, c_overpaid(EMP, 1500) AS overpaid
            FROM EMP
            WHERE name = 'Bill' or name = 'Sam';
-</ProgramListing>
+     </programlisting>
+
      In the query above, we can define c_overpaid as:
      
-<ProgramListing>
+     <programlisting>
          #include "postgres.h"
          #include "executor/executor.h"  /* for GetAttributeByName() */
          
@@ -458,136 +783,248 @@ The reason why, in general, we must use the function
                  return (false);
              return(salary &gt; limit);
          }
-</ProgramListing>
-</Para>
+     </programlisting>
+    </para>
 
-<Para>
-     <Acronym>GetAttributeByName</Acronym> is the 
-     <ProductName>Postgres</ProductName> system function that
+    <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 
+     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 name, the <Acronym>GetAttributeByName</Acronym> 
+     name which is of the type name, the <acronym>GetAttributeByName</acronym> 
      call would look like:
-<ProgramListing>
+
+     <programlisting>
          char *str;
          ...
          str = (char *) GetAttributeByName(t, "name", &amp;isnull)
-</ProgramListing>
-</Para>
+     </programlisting>
+    </para>
 
-<Para>
-     The  following  query  lets  <ProductName>Postgres</ProductName>  
+    <para>
+     The  following  query  lets  <productname>Postgres</productname>  
      know  about  the c_overpaid function:
-<ProgramListing>
+
+     <programlisting>
          * CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool
-              AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c';
-</ProgramListing>
-</Para>
+              AS '<replaceable>PGROOT</replaceable>/tutorial/obj/funcs.so' LANGUAGE 'c';
+     </programlisting>
+    </para>
 
-<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>
+    </para>
+   </sect2>
 
-<Sect2>
-<Title>Caveats</Title>
+   <sect2>
+    <title>Writing Code</title>
 
-<Para>
+    <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> 
+     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 
+     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>,  
+     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
+     because other languages, such as <acronym>FORTRAN</acronym> 
+     and <acronym>Pascal</acronym> often do not follow the same 
+     <firstterm>calling convention</firstterm>
+     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 written in <acronym>C</acronym>.
+    </para>
+
+    <para>
+     C functions with base type arguments can be written in a
+     straightforward fashion.  The C equivalents of built-in Postgres types
+     are accessible in a C file if 
+     <filename><replaceable>PGROOT</replaceable>/src/backend/utils/builtins.h</filename>
+     is included as a header file.  This can be achieved by having
+
+     <programlisting>
+#include &lt;utils/builtins.h&gt;
+     </programlisting>
+
+     at the top of the C source file.
+    </para>
+
+    <para>
+     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).
-</para>
-</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>
-      <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>
-      <ListItem>
-<Para>      Most of the internal <ProductName>Postgres</ProductName> 
-            types are declared in  postgres.h,  so  it's a good 
-            idea to always include that file as well.  Including 
-            postgres.h will also include elog.h and palloc.h for you.
-</Para>
-      </ListItem>
-      <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>
-</sect1>
-</chapter>
+     <itemizedlist>
+      <listitem>
+       <para>
+       Most of the header (include) files for 
+       <productname>Postgres</productname>
+       should      already      be     installed     in
+       <filename><replaceable>PGROOT</replaceable>/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).
+       </para>
+      </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>
+      <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>
+      <listitem>
+       <para>
+           Most of the internal <productname>Postgres</productname> 
+       types are declared in <filename>postgres.h</filename>,
+           so  it's a good 
+       idea to always include that file as well.  Including 
+       postgres.h will also include elog.h and palloc.h for you.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+       Compiling and loading your object code  so  that
+       it  can  be  dynamically  loaded  into  
+       <productname>Postgres</productname>
+       always requires special flags.
+       See <xref linkend="dfunc-title" endterm="dfunc-title">
+       for  a  detailed explanation of how to do it for
+       your particular operating system.
+       </para>
+      </listitem>
+     </itemizedlist>
+    </para>
+   </sect2>
+  </sect1>
+
+  <sect1>
+   <title>Function Overloading</title>
+
+   <para>
+    More than one function may be defined with the same name, as long as
+    the arguments they take are different.  In other words, function names
+    can be <firstterm>overloaded</firstterm>.
+    A function may also have the same name as an attribute.  In the case
+    that there is an ambiguity between a function on a complex type and
+    an attribute of the complex type, the attribute will always be used.
+   </para>
+
+   <sect2>
+    <title>Name Space Conflicts</title>
+
+    <para>
+     As of <productname>Postgres</productname> v6.5,
+     <command>CREATE FUNCTION</command> can decouple a C language
+     function name from the name of the entry point. This is now the
+     preferred technique to accomplish function overloading.
+    </para>
+
+    <sect3>
+     <title>Pre-v6.5</title>
+
+     <para>
+      For functions written in C, the SQL name declared in
+      <command>CREATE FUNCTION</command>
+      must be exactly the same as the actual name of the function in the
+      C code (hence it must be a legal C function name).
+     </para>
+
+     <para>
+      There is a subtle implication of this restriction: while the
+      dynamic loading routines in most operating systems are more than 
+      happy to allow you to load any number of shared libraries that 
+      contain conflicting (identically-named) function names, they may 
+      in fact botch the load in interesting ways.  For example, if you
+      define a dynamically-loaded function that happens to have the
+      same name as a function built into Postgres, the DEC OSF/1 dynamic 
+      loader causes Postgres to call the function within itself rather than 
+      allowing Postgres to call your function.  Hence, if you want your
+      function to be used on different architectures, we recommend that 
+      you do not overload C function names.
+     </para>
+
+     <para>
+      There is a clever trick to get around the problem just described.
+      Since there is no problem overloading SQL functions, you can 
+      define a set of C functions with different names and then define 
+      a set of identically-named SQL function wrappers that take the
+      appropriate argument types and call the matching C function.
+     </para>
+
+     <para>
+      Another solution is not to use dynamic loading, but to link your
+      functions into the backend statically and declare them as INTERNAL
+      functions.  Then, the functions must all have distinct C names but
+      they can be declared with the same SQL names (as long as their
+      argument types differ, of course).  This way avoids the overhead of
+      an SQL wrapper function, at the cost of more effort to prepare a
+      custom backend executable.
+     </para>
+    </sect3>
+   </sect2>
+  </sect1>
+ </chapter>
 
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->
index 4c0db10..771c30e 100644 (file)
@@ -1,3 +1,8 @@
+<!--
+$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.5 1999/07/22 15:11:05 thomas Exp $
+Postgres documentation
+-->
+
  <chapter id="xindex">
   <title>Interfacing Extensions To Indices</title>
 
index a87404b..f9752d1 100644 (file)
@@ -1,14 +1,14 @@
-<Chapter Id="xplang">
-<Title>Procedural Languages</Title>
+ <chapter id="xplang">
+  <title id="xplang-title">Procedural Languages</title>
 
 <!-- **********
      * General information about procedural language support
      **********
 -->
 
-<Para>
+<para>
     Beginning with the release of version 6.3,
-    <ProductName>Postgres</ProductName> supports
+    <productname>Postgres</productname> supports
     the definition of procedural languages.
     In the case of a function or trigger
     procedure defined in a procedural language, the database has
     handler itself is a special programming language function
     compiled into a shared object
     and loaded on demand.
-</Para>
+</para>
 
 <!-- **********
      * Installation of procedural languages
      **********
 -->
 
-<Sect1>
-<Title>Installing Procedural Languages</Title>
+<sect1>
+<title>Installing Procedural Languages</title>
 
-<Procedure>
-    <Title>
+<procedure>
+    <title>
     Procedural Language Installation
-    </Title>
+    </title>
 
     <para>
     A procedural language is installed in the database in three steps.
     </para>
-       <Step Performance="Required">
-           <Para>
+       <step performance="Required">
+           <para>
                The shared object for the language handler
                must be compiled and installed. By default the
                handler for PL/pgSQL is built and installed into the
                database library directory. If Tcl/Tk support is
                configured in, the handler for PL/Tcl is also built
                and installed in the same location.
-           </Para>
-           <Para>
+           </para>
+           <para>
                Writing a handler for a new procedural language (PL)
                is outside the scope of this manual. 
-           </Para>
-       </Step>
-       <Step Performance="Required">
-           <Para>
+           </para>
+       </step>
+       <step performance="Required">
+           <para>
                The handler must be declared with the command
-               <ProgramListing>
-    CREATE FUNCTION <Replaceable>handler_function_name</Replaceable> () RETURNS OPAQUE AS
-        '<Filename>path-to-shared-object</Filename>' LANGUAGE 'C';
-               </ProgramListing>
-               The special return type of <Acronym>OPAQUE</Acronym> tells
+               <programlisting>
+    CREATE FUNCTION <replaceable>handler_function_name</replaceable> () RETURNS OPAQUE AS
+        '<filename>path-to-shared-object</filename>' LANGUAGE 'C';
+               </programlisting>
+               The special return type of <acronym>OPAQUE</acronym> tells
                the database, that this function does not return one of
                the defined base- or composite types and is not directly usable
-               in <Acronym>SQL</Acronym> statements.
-           </Para>
-       </Step>
-       <Step Performance="Required">
-           <Para>
+               in <acronym>SQL</acronym> statements.
+           </para>
+       </step>
+       <step performance="Required">
+           <para>
                The PL must be declared with the command
-               <ProgramListing>
-    CREATE [ TRUSTED ] PROCEDURAL LANGUAGE '<Replaceable>language-name</Replaceable>'
-        HANDLER <Replaceable>handler_function_name</Replaceable>
-       LANCOMPILER '<Replaceable>description</Replaceable>';
-               </ProgramListing>
-               The optional keyword <Acronym>TRUSTED</Acronym> tells
+               <programlisting>
+    CREATE [ TRUSTED ] PROCEDURAL LANGUAGE '<replaceable>language-name</replaceable>'
+        HANDLER <replaceable>handler_function_name</replaceable>
+       LANCOMPILER '<replaceable>description</replaceable>';
+               </programlisting>
+               The optional keyword <acronym>TRUSTED</acronym> tells
                if ordinary database users that have no superuser
                privileges can use this language to create functions
                and trigger procedures. Since PL functions are
                languages that don't gain access to database backends
                internals or the filesystem. The languages PL/pgSQL and
                PL/Tcl are known to be trusted.
-           </Para>
-       </Step>
-</Procedure>
-
-<Procedure>
-    <Title>Example</Title>
-    <Step Performance="Required">
-    <Para>
+           </para>
+       </step>
+</procedure>
+
+<procedure>
+    <title>Example</title>
+    <step performance="Required">
+    <para>
         The following command tells the database where to find the 
        shared object for the PL/pgSQL languages call handler function.
-    </Para>
-    <ProgramListing>
+    </para>
+    <programlisting>
     CREATE FUNCTION plpgsql_call_handler () RETURNS OPAQUE AS
         '/usr/local/pgsql/lib/plpgsql.so' LANGUAGE 'C';
-    </ProgramListing>
-    </Step>
+    </programlisting>
+    </step>
 
-    <Step Performance="Required">
-    <Para>
+    <step performance="Required">
+    <para>
         The command
-    </Para>
-    <ProgramListing>
+    </para>
+    <programlisting>
     CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql'
         HANDLER plpgsql_call_handler
         LANCOMPILER 'PL/pgSQL';
-    </ProgramListing>
-    <Para>
+    </programlisting>
+    <para>
         then defines that the previously declared call handler
        function should be invoked for functions and trigger procedures
        where the language attribute is 'plpgsql'.
-    </Para>
-    <Para>
+    </para>
+    <para>
         PL handler functions have a special call interface that is
        different from regular C language functions. One of the arguments
-       given to the handler is the object ID in the <FileName>pg_proc</FileName>
+       given to the handler is the object ID in the <filename>pg_proc</filename>
        tables entry for the function that should be executed.
         The handler examines various system catalogs to analyze the
        functions call arguments and it's return data type. The source
        text of the functions body is found in the prosrc attribute of
-       <FileName>pg_proc</FileName>.
+       <filename>pg_proc</filename>.
        Due to this, in contrast to C language functions, PL functions
        can be overloaded like SQL language functions. There can be
        multiple different PL functions having the same function name,
        as long as the call arguments differ.
-    </Para>
-    <Para>
-        Procedural languages defined in the <FileName>template1</FileName>
+    </para>
+    <para>
+        Procedural languages defined in the <filename>template1</filename>
        database are automatically defined in all subsequently created
        databases. So the database administrator can decide which
        languages are available by default.
-    </Para>
-    </Step>
-</Procedure>
-</Sect1> <!-- **** End of PL installation **** -->
+    </para>
+    </step>
+</procedure>
+</sect1> <!-- **** End of PL installation **** -->
 
 <!-- **********
      * The procedural language PL/pgSQL
      **********
 -->
 
-<Sect1>
-<Title>PL/pgSQL</Title>
+<sect1>
+<title>PL/pgSQL</title>
 
-<Para>
+<para>
     PL/pgSQL is a loadable procedural language for the
-    <ProductName>Postgres</ProductName> database system.
-</Para>
+    <productname>Postgres</productname> database system.
+</para>
 
-<Para>
+<para>
     This package was originally written by Jan Wieck.
-</Para>
+</para>
 
 <!-- **** PL/pgSQL overview **** -->
 
-<Sect2>
-<Title>Overview</Title>
+<sect2>
+<title>Overview</title>
 
-<Para>
+<para>
     The design goals of PL/pgSQL were to create a loadable procedural
     language that
-    <ItemizedList>
-    <ListItem>
-       <Para>
+    <itemizedlist>
+    <listitem>
+       <para>
         can be used to create functions and trigger procedures,
-       </Para>
-    </ListItem>
-    <ListItem>
-       <Para>
-        adds control structures to the <Acronym>SQL</Acronym> language,
-       </Para>
-    </ListItem>
-    <ListItem>
-       <Para>
+       </para>
+    </listitem>
+    <listitem>
+       <para>
+        adds control structures to the <acronym>SQL</acronym> language,
+       </para>
+    </listitem>
+    <listitem>
+       <para>
         can perform complex computations,
-       </Para>
-    </ListItem>
-    <ListItem>
-       <Para>
+       </para>
+    </listitem>
+    <listitem>
+       <para>
         inherits all user defined types, functions and operators,
-       </Para>
-    </ListItem>
-    <ListItem>
-       <Para>
+       </para>
+    </listitem>
+    <listitem>
+       <para>
         can be defined to be trusted by the server,
-       </Para>
-    </ListItem>
-    <ListItem>
-       <Para>
+       </para>
+    </listitem>
+    <listitem>
+       <para>
         is easy to use.
-       </Para>
-    </ListItem>
-    </ItemizedList>
-</Para>
-<Para>
+       </para>
+    </listitem>
+    </itemizedlist>
+</para>
+<para>
     The PL/pgSQL call handler parses the functions source text and
     produces an internal binary instruction tree on the first time, the
     function is called by a backend. The produced bytecode is identified
     in the call handler by the object ID of the function. This ensures,
     that changing a function by a DROP/CREATE sequence will take effect
     without establishing a new database connection. 
-</Para>
-<Para>
-    For all expressions and <Acronym>SQL</Acronym> statements used in
+</para>
+<para>
+    For all expressions and <acronym>SQL</acronym> statements used in
     the function, the PL/pgSQL bytecode interpreter creates a
     prepared execution plan using the SPI managers SPI_prepare() and
     SPI_saveplan() functions. This is done the first time, the individual
     plans would be required, will only prepare and save those plans
     that are really used during the entire lifetime of the database
     connection.
-</Para>
-<Para>
+</para>
+<para>
     Except for input-/output-conversion and calculation functions
     for user defined types, anything that can be defined in C language
     functions can also be done with PL/pgSQL. It is possible to
     create complex conditional computation functions and later use
     them to define operators or use them in functional indices.
-</Para>
-</Sect2>
+</para>
+</sect2>
 
 <!-- **** PL/pgSQL Description **** -->
 
-<Sect2>
-<Title>Description</Title>
+<sect2>
+<title>Description</title>
 
 <!-- **** PL/pgSQL structure **** -->
 
-<Sect3>
-<Title>Structure of PL/pgSQL</Title>
+<sect3>
+<title>Structure of PL/pgSQL</title>
 
-<Para>
+<para>
     The PL/pgSQL language is case insensitive. All keywords and
     identifiers can be used in mixed upper- and lowercase.
-</Para>
-<Para>
+</para>
+<para>
     PL/pgSQL is a block oriented language. A block is defined as
 
-<ProgramListing>
+<programlisting>
     [&lt;&lt;label&gt;&gt;]
     [DECLARE
         <replaceable>declarations</replaceable>]
     BEGIN
         <replaceable>statements</replaceable>
     END;
-</ProgramListing>
+</programlisting>
 
     There can be any number of subblocks in the statement section
     of a block. Subblocks can be used to hide variables from outside a
     declared in the declarations section preceding a block are
     initialized to their default values every time the block is entered,
     not only once per function call.
-</Para>
+</para>
   
-<Para>
+<para>
     It is important not to misunderstand the meaning of BEGIN/END for
     grouping statements in PL/pgSQL and the database commands for
     transaction control. Functions and trigger procedures cannot
-    start or commit transactions and <ProductName>Postgres</ProductName>
+    start or commit transactions and <productname>Postgres</productname>
     does not have nested transactions.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
 <!-- **** PL/pgSQL comments **** -->
 
-<Sect3>
-<Title>Comments</Title>
+<sect3>
+<title>Comments</title>
 
-<Para>
+<para>
     There are two types of comments in PL/pgSQL. A double dash '--'
     starts a comment that extends to the end of the line. A '/*'
     starts a block comment that extends to the next occurence of '*/'.
     Block comments cannot be nested, but double dash comments can be
     enclosed into a block comment and a double dash can hide
     the block comment delimiters '/*' and '*/'.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
 <!-- **** PL/pgSQL declarations **** -->
 
-<Sect3>
-<Title>Declarations</Title>
+<sect3>
+<title>Declarations</title>
 
-<Para>
+<para>
     All variables, rows and records used in a block or it's
     subblocks must be declared in the declarations section of a block
     except for the loop variable of a FOR loop iterating over a range
     of integer values. Parameters given to a PL/pgSQL function are
     automatically declared with the usual identifiers $n.
     The declarations have the following syntax:
-</Para>
-<VariableList>
-
-<VarListEntry>
-<Term>
-<Replaceable>name</Replaceable> [ CONSTANT ] <Replaceable>type</Replaceable> [ NOT NULL ] [ DEFAULT | := <Replaceable>value</Replaceable> ];
-</Term>
-<ListItem>
-<Para>
+</para>
+<variablelist>
+
+<varlistentry>
+<term>
+<replaceable>name</replaceable> [ CONSTANT ]
+<replaceable>>typ</replaceable>> [ NOT NULL ] [ DEFAULT | :=
+       <replaceable>value</replaceable> ];
+</term>
+<listitem>
+<para>
     Declares a variable of the specified base type. If the variable
     is declared as CONSTANT, the value cannot be changed. If NOT NULL
     is specified, an assignment of a NULL value results in a runtime
     error. Since the default value of all variables is the
-    <Acronym>SQL</Acronym> NULL value, all variables declared as NOT NULL
+    <acronym>SQL</acronym> NULL value, all variables declared as NOT NULL
     must also have a default value specified.
-</Para>
-<Para>
+</para>
+<para>
     The default value is evaluated ever time the function is called. So
-    assigning '<Replaceable>now</Replaceable>' to a variable of type
-    <Replaceable>datetime</Replaceable> causes the variable to have the
+    assigning '<replaceable>now</replaceable>' to a variable of type
+    <replaceable>datetime</replaceable> causes the variable to have the
     time of the actual function call, not when the function was
     precompiled into it's bytecode.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-<Replaceable>name</Replaceable> <Replaceable>class</Replaceable>%ROWTYPE;
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+<replaceable>name</replaceable> <replaceable>class</replaceable>%ROWTYPE;
+</term>
+<listitem>
+<para>
     Declares a row with the structure of the given class. Class must be
     an existing table- or viewname of the database. The fields of the row
     are accessed in the dot notation. Parameters to a function can
     attributes of a table row are accessible in the row, no Oid or other
     system attributes (hence the row could be from a view and view rows
     don't have useful system attributes).
-</Para>
-<Para>
+</para>
+<para>
     The fields of the rowtype inherit the tables fieldsizes 
     or precision for char() etc. data types.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-<Replaceable>name</Replaceable> RECORD;
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+<replaceable>name</replaceable> RECORD;
+</term>
+<listitem>
+<para>
     Records are similar to rowtypes, but they have no predefined structure.
     They are used in selections and FOR loops to hold one actual
     database row from a SELECT operation. One and the same record can be
     used in different selections. Accessing a record or an attempt to assign
     a value to a record field when there is no actual row in it results
     in a runtime error.
-</Para>
-<Para>
+</para>
+<para>
     The NEW and OLD rows in a trigger are given to the procedure as
-    records. This is necessary because in <ProductName>Postgres</ProductName>
+    records. This is necessary because in <productname>Postgres</productname>
     one and the same trigger procedure can handle trigger events for
     different tables.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-<Replaceable>name</Replaceable> ALIAS FOR $n;
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+<replaceable>name</replaceable> ALIAS FOR $n;
+</term>
+<listitem>
+<para>
     For better readability of the code it is possible to define an alias
     for a positional parameter to a function.
-</Para>
-<Para>
+</para>
+<para>
     This aliasing is required for composite types given as arguments to
     a function. The dot notation $1.salary as in SQL functions is not
     allowed in PL/pgSQL.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-RENAME <Replaceable>oldname</Replaceable> TO <Replaceable>newname</Replaceable>;
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+RENAME <replaceable>oldname</replaceable> TO <replaceable>newname</replaceable>;
+</term>
+<listitem>
+<para>
     Change the name of a variable, record or row. This is useful
     if NEW or OLD should be referenced by another name inside a 
     trigger procedure.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-</VariableList>
-</Sect3>
+</variablelist>
+</sect3>
 
 <!-- **** PL/pgSQL data types **** -->
 
-<Sect3>
-<Title>Data Types</Title>
+<sect3>
+<title>Data Types</title>
 
-<Para>
+<para>
     The type of a varible can be any of the existing basetypes of
-    the database. <Replaceable>type</Replaceable> in the declarations
+    the database. <replaceable>type</replaceable> in the declarations
     section above is defined as:
-</Para>
-<Para>
-    <ItemizedList>
-    <ListItem>
-        <Para>
-       <ProductName>Postgres</ProductName>-basetype
-       </Para>
-    </ListItem>
-    <ListItem>
-        <Para>
-       <Replaceable>variable</Replaceable>%TYPE
-       </Para>
-    </ListItem>
-    <ListItem>
-        <Para>
-       <Replaceable>class.field</Replaceable>%TYPE
-       </Para>
-    </ListItem>
-    </ItemizedList>
-</Para>
-<Para>
-    <Replaceable>variable</Replaceable> is the name of a variable,
+</para>
+<para>
+    <itemizedlist>
+    <listitem>
+        <para>
+       <productname>Postgres</productname>-basetype
+       </para>
+    </listitem>
+    <listitem>
+        <para>
+       <replaceable>variable</replaceable>%TYPE
+       </para>
+    </listitem>
+    <listitem>
+        <para>
+       <replaceable>class.field</replaceable>%TYPE
+       </para>
+    </listitem>
+    </itemizedlist>
+</para>
+<para>
+    <replaceable>variable</replaceable> is the name of a variable,
 previously declared in the 
     same function, that is visible at this point.
-</Para>
-<Para>
-    <Replaceable>class</Replaceable> is the name of an existing table
-    or view where <Replaceable>field</Replaceable> is the name of
+</para>
+<para>
+    <replaceable>class</replaceable> is the name of an existing table
+    or view where <replaceable>field</replaceable> is the name of
     an attribute.
-</Para>
-<Para>
-    Using the <Replaceable>class.field</Replaceable>%TYPE
+</para>
+<para>
+    Using the <replaceable>class.field</replaceable>%TYPE
     causes PL/pgSQL to lookup the attributes definitions at the
     first call to the funciton during the lifetime of a backend.
     Have a table with a char(20) attribute and some PL/pgSQL functions
@@ -444,18 +446,18 @@ previously declared in the
     char(40) and restores the data. Ha - he forgot about the
     funcitons. The computations inside them will truncate the values
     to 20 characters. But if they are defined using the
-    <Replaceable>class.field</Replaceable>%TYPE
+    <replaceable>class.field</replaceable>%TYPE
     declarations, they will automagically handle the size change or
     if the new table schema defines the attribute as text type.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
 <!-- **** PL/pgSQL expressions **** -->
 
-<Sect3>
-<Title>Expressions</Title>
+<sect3>
+<title>Expressions</title>
 
-<Para>
+<para>
     All expressions used in PL/pgSQL statements are processed using
     the backends executor. Expressions which appear to contain
 constants may in fact require run-time evaluation (e.g. 'now' for the
@@ -463,22 +465,22 @@ datetime type) so
 it is impossible for the PL/pgSQL parser
     to identify real constant values other than the NULL keyword. All
     expressions are evaluated internally by executing a query
-    <ProgramListing>
-    SELECT <Replaceable>expression</Replaceable>
-    </ProgramListing>
+    <programlisting>
+    SELECT <replaceable>expression</replaceable>
+    </programlisting>
     using the SPI manager. In the expression, occurences of variable
     identifiers are substituted by parameters and the actual values from
     the variables are passed to the executor in the parameter array. All
     expressions used in a PL/pgSQL function are only prepared and
     saved once.
-</Para>
-<Para>
+</para>
+<para>
     The type checking done by the <productname>Postgres</productname>
     main parser has some side
     effects to the interpretation of constant values. In detail there
     is a difference between what the two functions
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION logfunc1 (text) RETURNS datetime AS '
         DECLARE
             logtxt ALIAS FOR $1;
@@ -487,11 +489,11 @@ it is impossible for the PL/pgSQL parser
             RETURN ''now'';
         END;
     ' LANGUAGE 'plpgsql';
-    </ProgramListing>
+    </programlisting>
 
     and
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION logfunc2 (text) RETURNS datetime AS '
         DECLARE
             logtxt ALIAS FOR $1;
@@ -502,9 +504,9 @@ it is impossible for the PL/pgSQL parser
             RETURN curtime;
         END;
     ' LANGUAGE 'plpgsql';
-    </ProgramListing>
+    </programlisting>
 
-    do. In the case of logfunc1(), the <ProductName>Postgres</ProductName>
+    do. In the case of logfunc1(), the <productname>Postgres</productname>
     main parser
     knows when preparing the plan for the INSERT, that the string 'now'
     should be interpreted as datetime because the target field of logtable
@@ -512,389 +514,392 @@ it is impossible for the PL/pgSQL parser
     and this constant value is then used in all invocations of logfunc1()
     during the lifetime of the backend. Needless to say that this isn't what the
     programmer wanted.
-</Para>
-<Para>
-    In the case of logfunc2(), the <ProductName>Postgres</ProductName> 
+</para>
+<para>
+    In the case of logfunc2(), the <productname>Postgres</productname> 
     main parser does not know
     what type 'now' should become and therefor it returns a datatype of
     text containing the string 'now'. During the assignment
     to the local variable curtime, the PL/pgSQL interpreter casts this
     string to the datetime type by calling the text_out() and datetime_in()
     functions for the conversion.
-</Para>
-<Para>
-    This type checking done by the <ProductName>Postgres</ProductName> main
+</para>
+<para>
+    This type checking done by the <productname>Postgres</productname> main
     parser got implemented after PL/pgSQL was nearly done.
     It is a difference between 6.3 and 6.4 and affects all functions
     using the prepared plan feature of the SPI manager.
     Using a local
     variable in the above manner is currently the only way in PL/pgSQL to get
     those values interpreted correctly.
-</Para>
-<Para>
+</para>
+<para>
     If record fields are used in expressions or statements, the data types of
     fields should not change between calls of one and the same expression.
     Keep this in mind when writing trigger procedures that handle events
     for more than one table.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
 <!-- **** PL/pgSQL statements **** -->
 
-<Sect3>
-<Title>Statements</Title>
+<sect3>
+<title>Statements</title>
 
-<Para>
+<para>
     Anything not understood by the PL/pgSQL parser as specified below
     will be put into a query and sent down to the database engine
     to execute. The resulting query should not return any data.
-</Para>
+</para>
 
-<VariableList>
+<variablelist>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Assignment
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     An assignment of a value to a variable or row/record field is
     written as
-    <ProgramListing>
-    <Replaceable>identifier</Replaceable> := <Replaceable>expression</Replaceable>;
-    </ProgramListing>
+    <programlisting>
+    <replaceable>identifier</replaceable> := <replaceable>expression</replaceable>;
+    </programlisting>
     If the expressions result data type doesn't match the variables
     data type, or the variable has a size/precision that is known
     (as for char(20)), the result value will be implicitly casted by
     the PL/pgSQL bytecode interpreter using the result types output- and
     the variables type input-functions. Note that this could potentially
     result in runtime errors generated by the types input functions.
-</Para>
-<Para>
+</para>
+<para>
     An assignment of a complete selection into a record or row can
     be done by
-    <ProgramListing>
-    SELECT <Replaceable>expressions</Replaceable> INTO <Replaceable>target</Replaceable> FROM ...;
-    </ProgramListing>
-    <Replaceable>target</Replaceable> can be a record, a row variable or a
+    <programlisting>
+    SELECT <replaceable>expressions</replaceable> INTO <replaceable>target</replaceable> FROM ...;
+    </programlisting>
+    <replaceable>target</replaceable> can be a record, a row variable or a
     comma separated list of variables and record-/row-fields.
-</Para>
-<Para>
+</para>
+<para>
     if a row or a variable list is used as target, the selected values
     must exactly match the structure of the target(s) or a runtime error
     occurs. The FROM keyword can be followed by any valid qualification,
     grouping, sorting etc. that can be given for a SELECT statement.
-</Para>
-<Para>
+</para>
+<para>
     There is a special variable named FOUND of type bool that can be used
     immediately after a SELECT INTO to check if an assignment had success.
 
-    <ProgramListing>
+    <programlisting>
     SELECT * INTO myrec FROM EMP WHERE empname = myname;
     IF NOT FOUND THEN
         RAISE EXCEPTION ''employee % not found'', myname;
     END IF;
-    </ProgramListing>
+    </programlisting>
 
     If the selection returns multiple rows, only the first is moved
     into the target fields. All others are silently discarded.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Calling another function
-</Term>
-<ListItem>
-<Para>
-    All functions defined in a <ProductName>Prostgres</ProductName>
+</term>
+<listitem>
+<para>
+    All functions defined in a <productname>Prostgres</productname>
     database return a value. Thus, the normal way to call a function
     is to execute a SELECT query or doing an assignment (resulting
     in a PL/pgSQL internal SELECT). But there are cases where someone
     isn't interested int the functions result.
-    <ProgramListing>
-    PERFORM <Replaceable>query</Replaceable>
-    </ProgramListing>
-    executes a 'SELECT <Replaceable>query</Replaceable>' over the
+    <programlisting>
+    PERFORM <replaceable>query</replaceable>
+    </programlisting>
+    executes a 'SELECT <replaceable>query</replaceable>' over the
     SPI manager and discards the result. Identifiers like local
     variables are still substituted into parameters.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Returning from the function
-</Term>
-<ListItem>
-<Para>
-    <ProgramListing>
-    RETURN <Replaceable>expression</Replaceable>
-    </ProgramListing>
-    The function terminates and the value of <Replaceable>expression</Replaceable>
+</term>
+<listitem>
+<para>
+    <programlisting>
+    RETURN <replaceable>expression</replaceable>
+    </programlisting>
+    The function terminates and the value of <replaceable>expression</replaceable>
     will be returned to the upper executor. The return value of a function
     cannot be undefined. If control reaches the end of the toplevel block
     of the function without hitting a RETURN statement, a runtime error
     will occur.
-</Para>
-<Para>
+</para>
+<para>
     The expressions result will be automatically casted into the
     functions return type as described for assignments.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Aborting and messages
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     As indicated in the above examples there is a RAISE statement that
-    can throw messages into the <ProductName>Postgres</ProductName>
+    can throw messages into the <productname>Postgres</productname>
     elog mechanism.
-    <ProgramListing>
-    RAISE <replaceable class="parameter">level</replaceable> ''<replaceable class="parameter">format</replaceable>'' [, <replaceable class="parameter">identifier</replaceable> [...]];
-    </ProgramListing>
+    <programlisting>
+    RAISE <replaceable class="parameter">level</replaceable>
+        <replaceable class="parameter">r">for</replaceable>le>'' [,
+         <replaceable class="parameter">identifier</replaceable> [...]];
+    </programlisting>
     Inside the format, <quote>%</quote> is used as a placeholder for the
     subsequent comma-separated identifiers. Possible levels are
     DEBUG (silently suppressed in production running databases), NOTICE 
     (written into the database log and forwarded to the client application)
     and EXCEPTION (written into the database log and aborting the transaction).
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Conditionals
-</Term>
-<ListItem>
-<Para>
-    <ProgramListing>
-    IF <Replaceable>expression</Replaceable> THEN
+</term>
+<listitem>
+<para>
+    <programlisting>
+    IF <replaceable>expression</replaceable> THEN
         <replaceable>statements</replaceable>
     [ELSE
         <replaceable>statements</replaceable>]
     END IF;
-    </ProgramListing>
-    The <Replaceable>expression</Replaceable> must return a value that
+    </programlisting>
+    The <replaceable>expression</replaceable> must return a value that
     at least can be casted into a boolean type.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Loops
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     There are multiple types of loops.
-    <ProgramListing>
+    <programlisting>
     [&lt;&lt;label&gt;&gt;]
     LOOP
         <replaceable>statements</replaceable>
     END LOOP;
-    </ProgramListing>
+    </programlisting>
     An unconditional loop that must be terminated explicitly
     by an EXIT statement. The optional label can be used by
     EXIT statements of nested loops to specify which level of
     nesting should be terminated.
-    <ProgramListing>
+    <programlisting>
     [&lt;&lt;label&gt;&gt;]
-    WHILE <Replaceable>expression</Replaceable> LOOP
+    WHILE <replaceable>expression</replaceable> LOOP
         <replaceable>statements</replaceable>
     END LOOP;
-    </ProgramListing>
+    </programlisting>
     A conditional loop that is executed as long as the evaluation
-    of <Replaceable>expression</Replaceable> is true.
-    <ProgramListing>
+    of <replaceable>expression</replaceable> is true.
+    <programlisting>
     [&lt;&lt;label&gt;&gt;]
-    FOR <Replaceable>name</Replaceable> IN [ REVERSE ] <Replaceable>expression</Replaceable> .. <Replaceable>expression</Replaceable> LOOP
+    FOR <replaceable>name</replaceable> IN [ REVERSE ]
+<replaceable>le>express</replaceable>le> .. <replaceable>expression</replaceable> LOOP
         <replaceable>statements</replaceable>
     END LOOP;
-    </ProgramListing>
+    </programlisting>
     A loop that iterates over a range of integer values. The variable
-    <Replaceable>name</Replaceable> is automatically created as type
+    <replaceable>name</replaceable> is automatically created as type
     integer and exists only inside the loop. The two expressions giving
     the lower and upper bound of the range are evaluated only when entering
     the loop. The iteration step is always 1.
-    <ProgramListing>
+    <programlisting>
     [&lt;&lt;label&gt;&gt;]
-    FOR <Replaceable>record | row</Replaceable> IN <Replaceable>select_clause</Replaceable> LOOP
+    FOR <replaceable>record | row</replaceable> IN <replaceable>select_clause</replaceable> LOOP
         <replaceable>statements</replaceable>
     END LOOP;
-    </ProgramListing>
+    </programlisting>
     The record or row is assigned all the rows resulting from the select
     clause and the statements executed for each. If the loop is terminated
     with an EXIT statement, the last assigned row is still accessible 
     after the loop.
-    <ProgramListing>
-    EXIT [ <Replaceable>label</Replaceable> ] [ WHEN <Replaceable>expression</Replaceable> ];
-    </ProgramListing>
-    If no <Replaceable>label</Replaceable> given,
+    <programlisting>
+    EXIT [ <replaceable>label</replaceable> ] [ WHEN <replaceable>expression</replaceable> ];
+    </programlisting>
+    If no <replaceable>label</replaceable> given,
  the innermost loop is terminated and the
     statement following END LOOP is executed next.
- If <Replaceable>label</Replaceable> is given, it
+ If <replaceable>label</replaceable> is given, it
     must be the label of the current or an upper level of nested loop
     blocks. Then the named loop or block is terminated and control
     continues with the statement after the loops/blocks corresponding
     END.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-</VariableList>
+</variablelist>
 
-</Sect3>
+</sect3>
 
 <!-- **** PL/pgSQL trigger procedures **** -->
 
-<Sect3>
-<Title>Trigger Procedures</Title>
+<sect3>
+<title>Trigger Procedures</title>
 
-<Para>
+<para>
     PL/pgSQL can be used to define trigger procedures. They are created
     with the usual CREATE FUNCTION command as a function with no
     arguments and a return type of OPAQUE.
-</Para>
-<Para>
-    There are some <ProductName>Postgres</ProductName> specific details
+</para>
+<para>
+    There are some <productname>Postgres</productname> specific details
     in functions used as trigger procedures.
-</Para>
-<Para>
+</para>
+<para>
     First they have some special variables created automatically in the 
     toplevel blocks declaration section. They are
-</Para>
+</para>
 
-<VariableList>
+<variablelist>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     NEW
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype RECORD; variable holding the new database row on INSERT/UPDATE
     operations on ROW level triggers.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     OLD
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype RECORD; variable holding the old database row on UPDATE/DELETE
     operations on ROW level triggers.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_NAME
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype name; variable that contains the name of the trigger actually
     fired.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_WHEN
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype text; a string of either 'BEFORE' or 'AFTER' depending on the
     triggers definition.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_LEVEL
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype text; a string of either 'ROW' or 'STATEMENT' depending on the
     triggers definition.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_OP
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype text; a string of 'INSERT', 'UPDATE' or 'DELETE' telling
     for which operation the trigger is actually fired.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_RELID
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype oid; the object ID of the table that caused the
     trigger invocation.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_RELNAME
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype name; the name of the table that caused the trigger
     invocation.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_NARGS
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype integer; the number of arguments given to the trigger
     procedure in the CREATE TRIGGER statement.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
     TG_ARGV[]
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     Datatype array of text; the arguments from the CREATE TRIGGER statement.
     The index counts from 0 and can be given as an expression. Invalid
     indices (&lt; 0 or &gt;= tg_nargs) result in a NULL value.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-</VariableList>
+</variablelist>
 
-<Para>
+<para>
     Second they must return either NULL or a record/row containing
     exactly the structure of the table the trigger was fired for.
     Triggers fired AFTER might always return a NULL value with no
@@ -904,22 +909,22 @@ Loops
     row in the operation. It is possible to replace single values directly
     in NEW and return that or to build a complete new record/row to
     return.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
 <!-- **** PL/pgSQL exceptions **** -->
 
-<Sect3>
-<Title>Exceptions</Title>
+<sect3>
+<title>Exceptions</title>
 
-<Para>
-    <ProductName>Postgres</ProductName> does not have a very smart
+<para>
+    <productname>Postgres</productname> does not have a very smart
     exception handling model. Whenever the parser, planner/optimizer
     or executor decide that a statement cannot be processed any longer,
     the whole transaction gets aborted and the system jumps back
     into the mainloop to get the next query from the client application.
-</Para>
-<Para>
+</para>
+<para>
     It is possible to hook into the error mechanism to notice that this
     happens. But currently it's impossible to tell what really
     caused the abort (input/output conversion error, floating point
@@ -929,73 +934,73 @@ Loops
     And even if, at this point the information, that the transaction
     is aborted, is already sent to the client application, so resuming
     operation does not make any sense.
-</Para>
-<Para>
+</para>
+<para>
     Thus, the only thing PL/pgSQL currently does when it encounters
     an abort during execution of a function or trigger
     procedure is to write some additional DEBUG level log messages
     telling in which function and where (line number and type of
     statement) this happened.
-</Para>
-</Sect3>
-</Sect2>
+</para>
+</sect3>
+</sect2>
 
 <!-- **** PL/pgSQL Examples **** -->
 
-<Sect2>
-<Title>Examples</Title>
+<sect2>
+<title>Examples</title>
 
-<Para>
+<para>
 Here are only a few functions to demonstrate how easy PL/pgSQL
 functions can be written. For more complex examples the programmer
 might look at the regression test for PL/pgSQL.
-</Para>
+</para>
 
-<Para>
+<para>
 One painful detail of writing functions in PL/pgSQL is the handling
 of single quotes. The functions source text on CREATE FUNCTION must
 be a literal string. Single quotes inside of literal strings must be
 either doubled or quoted with a backslash. We are still looking for
 an elegant alternative. In the meantime, doubling the single qoutes
 as in the examples below should be used. Any solution for this
-in future versions of <ProductName>Postgres</ProductName> will be
+in future versions of <productname>Postgres</productname> will be
 upward compatible.
-</Para>
+</para>
 
-<Sect3>
-<Title>Some Simple PL/pgSQL Functions</Title>
+<sect3>
+<title>Some Simple PL/pgSQL Functions</title>
 
-<Para>
+<para>
     The following two PL/pgSQL functions are identical to their
     counterparts from the C language function discussion.
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION add_one (int4) RETURNS int4 AS '
         BEGIN
             RETURN $1 + 1;
         END;
     ' LANGUAGE 'plpgsql';
-    </ProgramListing>
+    </programlisting>
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION concat_text (text, text) RETURNS text AS '
         BEGIN
             RETURN $1 || $2;
         END;
     ' LANGUAGE 'plpgsql';
-    </ProgramListing>
-</Para>
+    </programlisting>
+</para>
 
-</Sect3>
+</sect3>
 
-<Sect3>
-<Title>PL/pgSQL Function on Composite Type</Title>
+<sect3>
+<title>PL/pgSQL Function on Composite Type</title>
 
-<Para>
+<para>
     Again it is the PL/pgSQL equivalent to the example from
     The C functions.
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION c_overpaid (EMP, int4) RETURNS bool AS '
         DECLARE
             emprec ALIAS FOR $1;
@@ -1007,21 +1012,21 @@ upward compatible.
             RETURN emprec.salary > sallim;
         END;
     ' LANGUAGE 'plpgsql';
-    </ProgramListing>
-</Para>
+    </programlisting>
+</para>
 
-</Sect3>
+</sect3>
 
-<Sect3>
-<Title>PL/pgSQL Trigger Procedure</Title>
+<sect3>
+<title>PL/pgSQL Trigger Procedure</title>
 
-<Para>
+<para>
     This trigger ensures, that any time a row is inserted or updated
     in the table, the current username and time are stamped into the
     row. And it ensures that an employees name is given and that the
     salary is a positive value.
 
-    <ProgramListing>
+    <programlisting>
     CREATE TABLE emp (
         empname text,
         salary int4,
@@ -1052,108 +1057,110 @@ upward compatible.
 
     CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
         FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
-    </ProgramListing>
-</Para>
+    </programlisting>
+</para>
 
-</Sect3>
+</sect3>
 
-</Sect2>
+</sect2>
 
-</Sect1>
+</sect1>
 
 <!-- **********
      * The procedural language PL/Tcl
      **********
 -->
 
-<Sect1>
-<Title>PL/Tcl</Title>
+<sect1>
+<title>PL/Tcl</title>
 
-<Para>
+<para>
     PL/Tcl is a loadable procedural language for the
-    <ProductName>Postgres</ProductName> database system
+    <productname>Postgres</productname> database system
     that enables the Tcl language to be used to create functions and
     trigger-procedures.
-</Para>
+</para>
 
-<Para>
+<para>
     This package was originally written by Jan Wieck.
-</Para>
+</para>
 
 <!-- **** PL/Tcl overview **** -->
 
-<Sect2>
-<Title>Overview</Title>
+<sect2>
+<title>Overview</title>
 
-<Para>
+<para>
     PL/Tcl offers most of the capabilities a function
     writer has in the C language, except for some restrictions.
-</Para>
-<Para>
+</para>
+<para>
     The good restriction is, that everything is executed in a safe
     Tcl-interpreter. In addition to the limited command set of safe Tcl, only
     a few commands are available to access the database over SPI and to raise
     messages via elog(). There is no way to access internals of the
     database backend or gaining OS-level access under the permissions of the
-    <ProductName>Postgres</ProductName> user ID like in C.
+    <productname>Postgres</productname> user ID like in C.
     Thus, any unprivileged database user may be
     permitted to use this language.
-</Para>
-<Para>
+</para>
+<para>
     The other, internal given, restriction is, that Tcl procedures cannot
     be used to create input-/output-functions for new data types.
-</Para>
-<Para>
+</para>
+<para>
     The shared object for the PL/Tcl call handler is automatically built
-    and installed in the <ProductName>Postgres</ProductName>
+    and installed in the <productname>Postgres</productname>
     library directory if the Tcl/Tk support is specified
     in the configuration step of the installation procedure.
-</Para>
-</Sect2>
+</para>
+</sect2>
 
 <!-- **** PL/Tcl description **** -->
 
-<Sect2>
-<Title>Description</Title>
+<sect2>
+<title>Description</title>
 
-<Sect3>
-<Title><ProductName>Postgres</ProductName> Functions and Tcl Procedure Names</Title>
+<sect3>
+<title><productname>Postgres</productname> Functions and Tcl Procedure Names</title>
 
-<Para>
-    In <ProductName>Postgres</ProductName>, one and the 
+<para>
+    In <productname>Postgres</productname>, one and the 
     same function name can be used for
     different functions as long as the number of arguments or their types
     differ. This would collide with Tcl procedure names. To offer the same
     flexibility in PL/Tcl, the internal Tcl procedure names contain the object
     ID of the procedures pg_proc row as part of their name. Thus, different
-    argtype versions of the same <ProductName>Postgres</ProductName> 
+    argtype versions of the same <productname>Postgres</productname> 
     function are different for Tcl too.
-</Para>
+</para>
 
-</Sect3>
+</sect3>
 
-<Sect3>
-<Title>Defining Functions in PL/Tcl</Title>
+<sect3>
+<title>Defining Functions in PL/Tcl</title>
 
-<Para>
+<para>
     To create a function in the PL/Tcl language, use the known syntax
 
-    <ProgramListing>
-    CREATE FUNCTION <Replaceable>funcname</Replaceable> (<Replaceable>argument-types</Replaceable>) RETURNS <Replaceable>returntype</Replaceable> AS '
+    <programlisting>
+    CREATE FUNCTION <replaceable>funcname</replaceable>
+ <replaceable>ceable>argumen</replaceable>ceable>) RETURNS
+       <replaceable>returntype</replaceable> AS '
         # PL/Tcl function body
     ' LANGUAGE 'pltcl';
-    </ProgramListing>
+    </programlisting>
 
     When calling this function in a query, the arguments are given as
     variables $1 ... $n to the Tcl procedure body. So a little max function
     returning the higher of two int4 values would be created as:
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION tcl_max (int4, int4) RETURNS int4 AS '
         if {$1 > $2} {return $1}
        return $2
     ' LANGUAGE 'pltcl';
-    </ProgramListing>
+    </programlisting>
 
     Composite type arguments are given to the procedure as Tcl arrays.
     The element names
@@ -1161,9 +1168,9 @@ upward compatible.
     type. If an attribute in the actual row
     has the NULL value, it will not appear in the array! Here is
     an example that defines the overpaid_2 function (as found in the
-    older <ProductName>Postgres</ProductName> documentation) in PL/Tcl
+    older <productname>Postgres</productname> documentation) in PL/Tcl
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
         if {200000.0 < $1(salary)} {
             return "t"
@@ -1173,15 +1180,15 @@ upward compatible.
         }
         return "f"
     ' LANGUAGE 'pltcl';
-    </ProgramListing>
-</Para>
+    </programlisting>
+</para>
 
-</Sect3>
+</sect3>
 
-<Sect3>
-<Title>Global Data in PL/Tcl</Title>
+<sect3>
+<title>Global Data in PL/Tcl</title>
 
-<Para>
+<para>
     Sometimes (especially when using the SPI functions described later) it
     is useful to have some global status data that is held between two
     calls to a procedure. 
@@ -1191,146 +1198,146 @@ upward compatible.
     an array is made available to each procedure via the upvar
     command. The global name of this variable is the procedures internal
     name and the local name is GD.
-</Para>
-</Sect3>
+</para>
+</sect3>
 
-<Sect3>
-<Title>Trigger Procedures in PL/Tcl</Title>
+<sect3>
+<title>Trigger Procedures in PL/Tcl</title>
 
-<Para>
-    Trigger procedures are defined in <ProductName>Postgres</ProductName>
+<para>
+    Trigger procedures are defined in <productname>Postgres</productname>
     as functions without
     arguments and a return type of opaque. And so are they in the PL/Tcl
     language.
-</Para>
-<Para>
+</para>
+<para>
     The informations from the trigger manager are given to the procedure body
     in the following variables:
-</Para>
-<VariableList>
+</para>
+<variablelist>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_name
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The name of the trigger from the CREATE TRIGGER statement.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_relid
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The object ID of the table that caused the trigger procedure
     to be invoked.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_relatts
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     A Tcl list of the tables field names prefixed with an empty list element.
     So looking up an element name in the list with the lsearch Tcl command
     returns the same positive number starting from 1 as the fields are numbered
     in the pg_attribute system catalog.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_when
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The string BEFORE or AFTER depending on the event of the trigger call.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_level
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The string ROW or STATEMENT depending on the event of the trigger call.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $TG_op
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The string INSERT, UPDATE or DELETE depending on the event of the 
     trigger call.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $NEW
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     An array containing the values of the new table row on INSERT/UPDATE
     actions, or empty on DELETE.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $OLD
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     An array containing the values of the old table row on UPDATE/DELETE
     actions, or empty on INSERT.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $GD
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     The global status data array as described above.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term><Replaceable class="Parameter">
+<varlistentry>
+<term><replaceable class="Parameter">
 $args
-</Replaceable></Term>
-<ListItem>
-<Para>
+</replaceable></term>
+<listitem>
+<para>
     A Tcl list of the arguments to the procedure as given in the
     CREATE TRIGGER statement. The arguments are also accessible as $1 ... $n
     in the procedure body.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-</VariableList>
+</variablelist>
 
-<Para>
+<para>
     The return value from a trigger procedure is one of the strings OK or SKIP,
     or a list as returned by the 'array get' Tcl command. If the return value
     is OK, the normal operation (INSERT/UPDATE/DELETE) that fired this trigger
@@ -1339,14 +1346,14 @@ $args
     to return a modified row to the trigger manager that will be inserted instead
     of the one given in $NEW (INSERT/UPDATE only). Needless to say that all
     this is only meaningful when the trigger is BEFORE and FOR EACH ROW.
-</Para>
-<Para>
+</para>
+<para>
     Here's a little example trigger procedure that forces an integer value
     in a table to keep track of the # of updates that are performed on the
     row. For new row's inserted, the value is initialized to 0 and then
     incremented on every update operation:
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION trigfunc_modcount() RETURNS OPAQUE AS '
         switch $TG_op {
             INSERT {
@@ -1367,161 +1374,163 @@ $args
 
     CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
         FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
-    </ProgramListing>
+    </programlisting>
 
-</Para>
-</Sect3>
+</para>
+</sect3>
 
-<Sect3>
-<Title>Database Access from PL/Tcl</Title>
+<sect3>
+<title>Database Access from PL/Tcl</title>
 
-<Para>
+<para>
     The following commands are available to access the database from
     the body of a PL/Tcl procedure:
-</Para>
+</para>
 
-<VariableList>
+<variablelist>
 
-<VarListEntry>
-<Term>
-elog <Replaceable>level</Replaceable> <Replaceable>msg</Replaceable>
-</Term>
-<ListItem>
-<Para>
+<varlistentry>
+<term>
+elog <replaceable>level</replaceable> <replaceable>msg</replaceable>
+</term>
+<listitem>
+<para>
     Fire a log message. Possible levels are NOTICE, WARN, ERROR,
     FATAL, DEBUG and NOIND
     like for the elog() C function.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-quote <Replaceable>string</Replaceable>
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+quote <replaceable>string</replaceable>
+</term>
+<listitem>
+<para>
     Duplicates all occurences of single quote and backslash characters.
     It should be used when variables are used in the query string given
     to spi_exec or spi_prepare (not for the value list on spi_execp).
     Think about a query string like
 
-    <ProgramListing>
+    <programlisting>
     "SELECT '$val' AS ret"
-    </ProgramListing>
+    </programlisting>
 
     where the Tcl variable val actually contains "doesn't". This would result
     in the final query string
 
-    <ProgramListing>
+    <programlisting>
     "SELECT 'doesn't' AS ret"
-    </ProgramListing>
+    </programlisting>
 
     what would cause a parse error during spi_exec or spi_prepare.
     It should contain
 
-    <ProgramListing>
+    <programlisting>
     "SELECT 'doesn''t' AS ret"
-    </ProgramListing>
+    </programlisting>
 
     and has to be written as
 
-    <ProgramListing>
+    <programlisting>
     "SELECT '[ quote $val ]' AS ret"
-    </ProgramListing>
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replaceable>? <Replaceable>query</Replaceable> ?<Replaceable>loop-body</Replaceable>?
-</Term>
-<ListItem>
-<Para>
+    </programlisting>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+spi_exec ?-count <replaceable>n</replaceable>? ?-array
+<replaceable>>nam</replaceable>>?<replaceable>e>que</replaceable>e> ?<replaceable>loop-body</replaceable>?
+</term>
+<listitem>
+<para>
     Call parser/planner/optimizer/executor for query.
     The optional -count value tells spi_exec the maximum number of rows
     to be processed by the query.
-</Para>
-<Para>
+</para>
+<para>
     If the query is
     a SELECT statement and the optional loop-body (a body of Tcl commands
     like in a foreach statement) is given, it is evaluated for each
     row selected and behaves like expected on continue/break. The values
     of selected fields are put into variables named as the column names. So a
 
-    <ProgramListing>
+    <programlisting>
     spi_exec "SELECT count(*) AS cnt FROM pg_proc"
-    </ProgramListing>
+    </programlisting>
 
     will set the variable $cnt to the number of rows in the pg_proc system
     catalog. If the option -array is given, the column values are stored
     in the associative array named 'name' indexed by the column name
     instead of individual variables.
 
-    <ProgramListing>
+    <programlisting>
     spi_exec -array C "SELECT * FROM pg_class" {
         elog DEBUG "have table $C(relname)"
     }
-    </ProgramListing>
+    </programlisting>
 
     will print a DEBUG log message for every row of pg_class. The return value
     of spi_exec is the number of rows affected by query as found in
     the global variable SPI_processed.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-spi_prepare <Replaceable>query</Replaceable> <Replaceable>typelist</Replaceable>
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+spi_prepare <replaceable>query</replaceable> <replaceable>typelist</replaceable>
+</term>
+<listitem>
+<para>
     Prepares AND SAVES a query plan for later execution. It is a bit different
     from the C level SPI_prepare in that the plan is automatically copied to the
     toplevel memory context. Thus, there is currently no way of preparing a
     plan without saving it.
-</Para>
-<Para>
+</para>
+<para>
     If the query references arguments, the type names must be given as a Tcl
     list. The return value from spi_prepare is a query ID to be used in
     subsequent calls to spi_execp. See spi_execp for a sample.
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>
-spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replaceable>? ?-nulls <Replaceable>str</Replaceable>? <Replaceable>query</Replaceable> ?<Replaceable>valuelist</Replaceable>? ?<Replaceable>loop-body</Replaceable>?
-</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+spi_exec ?-count <replaceable>n</replaceable>? ?-array
+<replaceable>>nam</replaceable>>? ?-nulls<replaceable>e>s</replaceable>e><replaceable>le>qu</replaceable>le<replaceable>ble>value</replaceable>ble>? ?<replaceable>loop-body</replaceable>?
+</term>
+<listitem>
+<para>
     Execute a prepared plan from spi_prepare with variable substitution.
     The optional -count value tells spi_execp the maximum number of rows
     to be processed by the query.
-</Para>
-<Para>
+</para>
+<para>
     The optional value for -nulls is a string of spaces and 'n' characters
     telling spi_execp which of the values are NULL's. If given, it must
     have exactly the length of the number of values.
-</Para>
-<Para>
+</para>
+<para>
     The queryid is the ID returned by the spi_prepare call.
-</Para>
-<Para>
+</para>
+<para>
     If there was a typelist given to spi_prepare, a Tcl list of values of
     exactly the same length must be given to spi_execp after the query. If
     the type list on spi_prepare was empty, this argument must be omitted.
-</Para>
-<Para>
+</para>
+<para>
     If the query is a SELECT statement, the same as described for spi_exec
     happens for the loop-body and the variables for the fields selected.
-</Para>
-<Para>
+</para>
+<para>
     Here's an example for a PL/Tcl function using a prepared plan:
 
-    <ProgramListing>
+    <programlisting>
     CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS '
         if {![ info exists GD(plan) ]} {
             # prepare the saved plan on the first call
@@ -1532,7 +1541,7 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac
         spi_execp -count 1 $GD(plan) [ list $1 $2 ]
         return $cnt
     ' LANGUAGE 'pltcl';
-    </ProgramListing>
+    </programlisting>
 
     Note that each backslash that Tcl should see must be doubled in
     the query creating the function, since the main parser processes
@@ -1540,16 +1549,16 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac
     Inside the query string given to spi_prepare should
     really be dollar signs to mark the parameter positions and to not let
     $1 be substituted by the value given in the first function call.
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
 
-<VarListEntry>
-<Term>
+<varlistentry>
+<term>
 Modules and the unknown command
-</Term>
-<ListItem>
-<Para>
+</term>
+<listitem>
+<para>
     PL/Tcl has a special support for things often used. It recognizes two
     magic tables, pltcl_modules and pltcl_modfuncs.
     If these exist, the module 'unknown' is loaded into the interpreter
@@ -1558,21 +1567,36 @@ Modules and the unknown command
     of the modules. If this is true, the module is loaded on demand.
     To enable this behavior, the PL/Tcl call handler must be compiled
     with -DPLTCL_UNKNOWN_SUPPORT set.
-</Para>
-<Para>
+</para>
+<para>
     There are support scripts to maintain these tables in the modules
     subdirectory of the PL/Tcl source including the source for the
     unknown module that must get installed initially.
-</Para>
-</ListItem>
-</VarListEntry>
-
-</VariableList>
-
-</Sect3>
-
-</Sect2>
-</Sect1>
-
-
-</Chapter>
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+
+</sect3>
+
+</sect2>
+</sect1>
+</chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->