OSDN Git Service

General editing
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 7 Apr 2003 01:29:26 +0000 (01:29 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 7 Apr 2003 01:29:26 +0000 (01:29 +0000)
doc/src/sgml/datetime.sgml
doc/src/sgml/jdbc.sgml
doc/src/sgml/plperl.sgml
doc/src/sgml/plpgsql.sgml
doc/src/sgml/plpython.sgml
doc/src/sgml/pltcl.sgml
doc/src/sgml/pygresql.sgml
doc/src/sgml/xplang.sgml

index f237bde..d7a76da 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.30 2003/03/13 01:30:27 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.31 2003/04/07 01:29:25 petere Exp $
 -->
 
  <appendix id="datetime-appendix">
@@ -210,7 +210,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.30 2003/03/13 01:30:27 pe
   </sect1>
 
 
-  <sect1>
+  <sect1 id="datetime-keywords">
    <title>Date/Time Key Words</title>
 
    <para>
index 817a0a7..525cc07 100644 (file)
@@ -1,18 +1,10 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.43 2003/03/25 16:15:37 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.44 2003/04/07 01:29:25 petere Exp $
 -->
 
  <chapter id="jdbc">
   <title><acronym>JDBC</acronym> Interface</title>
 
-  <note>
-   <title>Author</title>
-   <para>
-    Originally written by Peter T. Mount (<email>peter@retep.org.uk</email>), 
-    the original author of the <acronym>JDBC</acronym> driver.
-   </para>
-  </note>
-
   <para>
    <acronym>JDBC</acronym> is a core <acronym>API</acronym> of Java 1.1 and later.
    It provides a standard set of
@@ -21,7 +13,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.43 2003/03/25 16:15:37
 
   <para>
    <productname>PostgreSQL</> provides a <firstterm>type
-   4</firstterm> <acronym>JDBC</acronym> Driver.  Type 4 indicates
+   4</firstterm> <acronym>JDBC</acronym> driver.  Type 4 indicates
    that the driver is written in Pure Java, and communicates in the
    database system's own network protocol. Because of this, the driver
    is platform independent; once compiled, the driver can be used on
@@ -33,13 +25,17 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.43 2003/03/25 16:15:37
    <acronym>JDBC</acronym> programming, but should help to get you
    started. For more information refer to the standard
    <acronym>JDBC</acronym> <acronym>API</acronym> documentation.
-   Also, take a look at the examples included with the source. The
-   basic example is used here.
+   Also, take a look at the examples included with the source.
   </para>
 
  <sect1 id="jdbc-setup">
   <title>Setting up the <acronym>JDBC</acronym> Driver</title>
 
+  <para>
+   This section describes the steps you need to take before you can
+   write or run programs that use the JDBC interface.
+  </para>
+
   <sect2 id="jdbc-build">
    <title>Getting the Driver</title>
 
@@ -71,8 +67,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.43 2003/03/25 16:15:37
    <para>
     To use the driver, the JAR archive (named
     <filename>postgresql.jar</filename> if you built from source, otherwise
-    it will likely be named <filename>jdbc7.2-1.1.jar</filename> or 
-    <filename>jdbc7.2-1.2.jar</filename> for the JDBC 1 and JDBC 2 versions
+    it will likely be named <filename>jdbc&majorversion;-1.1.jar</filename> or 
+    <filename>jdbc&majorversion;-1.2.jar</filename> for the JDBC 1 and JDBC 2 versions
     respectively)
     needs to be included in the
     class path, either by putting it in the <envar>CLASSPATH</envar>
@@ -80,26 +76,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.43 2003/03/25 16:15:37
     <command>java</command> command line.
    </para>
 
-    <para>
-     For instance, I have an application that uses the
-     <acronym>JDBC</acronym> driver to access a large database
-     containing astronomical objects. I have the application and the
-     <acronym>JDBC</acronym> driver installed in the <filename
-     class="directory">/usr/local/lib</filename> directory, and the
-     Java <acronym>JDK</acronym> installed in
-     <filename>/usr/local/jdk1.3.1</filename>.  To run the
-     application, I would use:
+   <para>
+    For instance, assume we have an application that uses the
+    <acronym>JDBC</acronym> driver to access a database, and that
+    application is installed as
+    <filename>/usr/local/lib/myapp.jar</filename>.  The PostgreSQL
+    JDBC driver installed as
+    <filename>/usr/local/pgsql/share/java/postgresql.jar</>.  To run
+    the application, we would use:
 <programlisting>
-export CLASSPATH=/usr/local/lib/finder.jar<co id="co.jdbc-finder">:/usr/local/pgsql/share/java/postgresql.jar:.
-java Finder
+export CLASSPATH=/usr/local/lib/myapp.jar:/usr/local/pgsql/share/java/postgresql.jar:.
+java MyApp
 </programlisting>
-     <calloutlist>
-      <callout arearefs="co.jdbc-finder">
-       <para>
-        <filename>finder.jar</filename> contains the Finder application.
-       </para>
-      </callout>
-     </calloutlist>
     </para>
 
     <para>
@@ -109,7 +97,7 @@ java Finder
   </sect2>
 
   <sect2 id="jdbc-prepare">
-   <title>Preparing the Database for <acronym>JDBC</acronym></title>
+   <title>Preparing the Database Server for <acronym>JDBC</acronym></title>
 
    <para>
     Because Java only uses TCP/IP connections, the
@@ -125,14 +113,19 @@ java Finder
     Also, the client authentication setup in the
     <filename>pg_hba.conf</filename> file may need to be configured.
     Refer to <xref linkend="client-authentication"> for details.  The
-    <acronym>JDBC</acronym> Driver supports the trust, ident,
+    <acronym>JDBC</acronym> driver supports the trust, ident,
     password, md5, and crypt authentication methods.
    </para>
   </sect2>
  </sect1>
 
  <sect1 id="jdbc-use">
-  <title>Using the Driver</title>
+  <title>Initializing the Driver</title>
+
+  <para>
+   This section describes how to load and initialize the JDBC driver
+   in your programs.
+  </para>
 
   <sect2 id="jdbc-import">
    <title>Importing <acronym>JDBC</acronym></title>
@@ -144,15 +137,15 @@ java Finder
 <programlisting>
 import java.sql.*;
 </programlisting>
+   </para>
 
-    <important>
+    <note>
      <para>
       Do not import the <literal>org.postgresql</literal> package. If
       you do, your source will not compile, as
       <command>javac</command> will get confused.
      </para>
-    </important>
-   </para>
+    </note>
   </sect2>
 
   <sect2 id="jdbc-load">
@@ -175,6 +168,7 @@ Class.forName("org.postgresql.Driver");
 
     This will load the driver, and while loading, the driver will automatically
     register itself with <acronym>JDBC</acronym>.
+   </para>
 
     <note>
      <para>
@@ -183,7 +177,6 @@ Class.forName("org.postgresql.Driver");
       not available.
      </para>
     </note>
-   </para>
 
    <para>
     This is the most common method to use, but restricts your code to
@@ -250,7 +243,7 @@ jdbc:postgresql://<replaceable class="parameter">host</replaceable>:<replaceable
      </listitem>
     </itemizedlist>
 
-    where:
+    The parametes have the following meanings:
 
     <variablelist>
      <varlistentry>
@@ -292,7 +285,7 @@ jdbc:postgresql://<replaceable class="parameter">host</replaceable>:<replaceable
    <para>
     To connect, you need to get a <classname>Connection</classname> instance from 
     <acronym>JDBC</acronym>. To do this,
-    you would use the <function>DriverManager.getConnection()</function> method:
+    you use the <function>DriverManager.getConnection()</function> method:
 
 <programlisting>
 Connection db = DriverManager.getConnection(url, username, password);
@@ -336,8 +329,8 @@ db.close();
      column of each row using a <classname>Statement</classname>.
 <programlisting>
 Statement st = db.createStatement();
-ResultSet rs = st.executeQuery("SELECT * FROM mytable where columnfoo = 500");
-while(rs.next()) {
+ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500");
+while (rs.next()) {
     System.out.print("Column 1 returned ");
     System.out.println(rs.getString(1));
 }
@@ -347,15 +340,15 @@ st.close();
     </para>
 
     <para>
-     This example will issue the same query as before using 
+     This example issues the same query as before but uses
      a <classname>PreparedStatement</classname>
      and a bind value in the query.
 <programlisting>
 int foovalue = 500;
-PreparedStatement st = db.prepareStatement("SELECT * FROM mytable where columnfoo = ?");
+PreparedStatement st = db.prepareStatement("SELECT * FROM mytable WHERE columnfoo = ?");
 st.setInt(1, foovalue);
 ResultSet rs = st.executeQuery();
-while(rs.next()) {
+while (rs.next()) {
     System.out.print("Column 1 returned ");
     System.out.println(rs.getString(1));
 }
@@ -366,8 +359,7 @@ st.close();
    </example>
 
    <sect2>
-    <title>Using the <classname>Statement</classname> or <classname>
-    PreparedStatement</classname> Interface</title>
+    <title>Using the <classname>Statement</classname> or <classname>PreparedStatement</classname> Interface</title>
 
     <para>
      The following must be considered when using the
@@ -463,10 +455,10 @@ st.close();
        <para>
         <classname>ResultSet</classname> is currently read only.
         You can not update data through the <classname>ResultSet</classname>.
-        If you want to update data you need to do it the old fashioned way
-        by issuing a <acronym>SQL</acronym> update statement.  This is 
+        If you want to update data you need to do it the normal way
+        by using the <acronym>SQL</acronym> statement <command>UPDATE</command>.  This is 
         in conformance with the <acronym>JDBC</acronym> specification 
-        which does not require drivers to provide this functionality.
+        which does not require drivers to provide updatable result sets.
        </para>
       </listitem>
      </itemizedlist>
@@ -478,23 +470,25 @@ st.close();
    <title>Performing Updates</title>
 
    <para>
-    To change data (perform an insert, update, or delete) 
-    you use the <function>executeUpdate()</function> method.
-    <function>executeUpdate()</function> is similar to the
-    <function>executeQuery()</function> used to issue a select,
-    however it doesn't return a <classname>ResultSet</classname>,
-    instead it returns the number of records affected by the insert,
-    update, or delete statement.
+    To change data (perform an <command>INSERT</command>,
+    <command>UPDATE</command>, or <command>DELETE</command>) you use
+    the <function>executeUpdate()</function> method.  This method is
+    similar to the method <function>executeQuery()</function> used to
+    issue a <command>SELECT</command> statement, but it doesn't return
+    a <classname>ResultSet</classname>; instead it returns the number
+    of rows affected by the <command>INSERT</command>,
+    <command>UPDATE</command>, or <command>DELETE</command> statement.
+    <xref linkend="jdbc-delete-example"> illustrates the usage.
    </para>
 
   <example id="jdbc-delete-example">
-   <title>Simple Delete Example</title>
+   <title>Deleting Rows in <acronym>JDBC</acronym></title>
    <para>
-     This example will issue a simple delete and print out the number
-     of rows deleted.
+     This example will issue a simple <command>DELETE</command>
+     statement and print out the number of rows deleted.
 <programlisting>
 int foovalue = 500;
-PreparedStatement st = db.prepareStatement("DELETE FROM mytable where columnfoo = ?");
+PreparedStatement st = db.prepareStatement("DELETE FROM mytable WHERE columnfoo = ?");
 st.setInt(1, foovalue);
 int rowsDeleted = st.executeUpdate();
 System.out.println(rowsDeleted + " rows deleted");
@@ -509,19 +503,19 @@ st.close();
 
    <para>
     To create, modify or drop a database object like a table or view
-    you use the <function>execute()</function> method.
-    <function>execute</function> is similar to the
-    <function>executeQuery()</function> used to issue a select,
-    however it doesn't return a result.
+    you use the <function>execute()</function> method.  This method is
+    similar to the method <function>executeQuery()</function>, but it
+    doesn't return a result.  <xref linkend="jdbc-drop-table-example">
+    illustrates the usage.
    </para>
 
   <example id="jdbc-drop-table-example">
-   <title>Drop Table Example</title>
+   <title>Dropping a Table in JDBC</title>
    <para>
      This example will drop a table.
 <programlisting>
 Statement st = db.createStatement();
-ResultSet rs = st.executeQuery("DROP TABLE mytable");
+st.execute("DROP TABLE mytable");
 st.close();
 </programlisting>
    </para>
@@ -534,11 +528,10 @@ st.close();
   <para>
     <application>PostgreSQL</application> provides two distinct ways to 
     store binary data.  Binary data can be stored in a table using 
-    <application>PostgreSQL's</application> binary data type 
-    <type>bytea</type>, or by using the <firstterm>Large Object</firstterm>
+    the data type <type>bytea</type> or by using the Large Object
     feature which stores the binary data in a separate table in a special 
-    format, and refers to that table by storing a value of type 
-    <type>OID</type> in your table.
+    format and refers to that table by storing a value of type 
+    <type>oid</type> in your table.
   </para>
 
   <para>
@@ -547,32 +540,32 @@ st.close();
     <type>bytea</type> data type is not well suited for storing very 
     large amounts of binary data.  While a column of type 
     <type>bytea</type> can hold up to 1 GB of binary data, it would 
-    require a huge amount of memory (<acronym>RAM</acronym>) to 
+    require a huge amount of memory to 
     process such a large value.  The Large Object method for 
     storing binary data is better suited to storing very large values, 
     but it has its own limitations.  Specifically deleting a row 
-    that contains a Large Object does not delete the Large Object.
+    that contains a Large Object reference does not delete the Large Object.
     Deleting the Large Object is a separate operation that needs to
     be performed.  Large Objects also have some security
-    issues since anyone connected to the database case view 
+    issues since anyone connected to the database cann view 
     and/or modify any Large Object, even if they don't have 
-    permissions to view/update the row containing the Large Object.
+    permissions to view/update the row containing the Large Object reference.
   </para>
 
   <para>
-    7.2 is the first release of the <acronym>JDBC</acronym> Driver 
+    Version 7.2 was the first release of the <acronym>JDBC</acronym> driver 
     that supports the <type>bytea</type> data type.  The introduction of 
     this functionality in 7.2 has introduced a change in behavior 
-    as compared to previous releases.  In 7.2 the methods 
+    as compared to previous releases.  Since 7.2, the methods 
     <function>getBytes()</function>, <function>setBytes()</function>, 
     <function>getBinaryStream()</function>, and 
     <function>setBinaryStream()</function> operate on 
-    the <type>bytea</type> data type.  In 7.1 these methods operated 
-    on the <type>OID</type> data type associated with Large Objects.  
+    the <type>bytea</type> data type.  In 7.1 and earlier, these methods operated 
+    on the <type>oid</type> data type associated with Large Objects.  
     It is possible to revert the driver back to the old 7.1 behavior 
-    by setting the <parameter>compatible</parameter> property on 
-    the <classname>Connection</classname> to a value of 
-    <literal>7.1</literal>
+    by setting the property <literal>compatible</literal> on 
+    the <classname>Connection</classname> object to the value
+    <literal>7.1</literal>.
   </para>
 
   <para>
@@ -584,39 +577,44 @@ st.close();
 
   <para>
     To use the Large Object functionality you can use either the 
-    <classname>LargeObject</classname> <acronym>API</acronym>
+    <classname>LargeObject</classname> class
     provided by the <application>PostgreSQL</application> 
-    <acronym>JDBC</acronym> Driver, or by using the 
+    <acronym>JDBC</acronym> driver, or by using the 
     <function>getBLOB()</function> and <function>setBLOB()</function>
     methods.
   </para>
 
   <important>
    <para>
-    For <application>PostgreSQL</application>, you must access Large
-    Objects within an <acronym>SQL</acronym> transaction.  You would
-    open a transaction by using the
-    <function>setAutoCommit()</function> method with an input
-    parameter of <literal>false</literal>.
+    You must access Large Objects within an <acronym>SQL</acronym>
+    transaction block.  You can start a transaction block by calling
+    <function>setAutoCommit(false)</function>.
    </para>
   </important>
 
-  <note><para>In a future release of the
-      <acronym>JDBC</acronym> Driver, the <function>getBLOB()</function>
+  <note>
+   <para>
+      In a future release of the
+      <acronym>JDBC</acronym> driver, the <function>getBLOB()</function>
       and <function>setBLOB()</function> methods may no longer 
-      interact with Large Objects and will instead work on 
-      <type>bytea</type> data types.  So it is recommended that you 
+      interact with Large Objects and will instead work on the data type
+      <type>bytea</type>.  So it is recommended that you 
       use the <classname>LargeObject</classname> <acronym>API</acronym> 
       if you intend to use Large Objects.
-  </para></note>
+   </para>
+  </note>
 
+  <para>
+   <xref linkend="jdbc-binary-data-example"> contains some examples on
+   how to process binary data using the PostgreSQL JDBC driver.
+  </para>
 
   <example id="jdbc-binary-data-example">
-   <title>Binary Data Examples</title>
+   <title>Processing Binary Data in JDBC</title>
 
    <para>
-    For example, suppose you have a table containing the file name of
-    an image and you also want to store the image in a <type>bytea</type>
+    For example, suppose you have a table containing the file names of
+    images and you also want to store the image in a <type>bytea</type>
     column:
 <programlisting>
 CREATE TABLE images (imgname text, img bytea);
@@ -649,13 +647,13 @@ fis.close();
     <classname>Statement</classname> class can equally be used.)
 
 <programlisting>
-PreparedStatement ps = con.prepareStatement("SELECT img FROM images WHERE imgname=?");
+PreparedStatement ps = con.prepareStatement("SELECT img FROM images WHERE imgname = ?");
 ps.setString(1, "myimage.gif");
 ResultSet rs = ps.executeQuery();
 if (rs != null) {
-    while(rs.next()) {
+    while (rs.next()) {
         byte[] imgBytes = rs.getBytes(1);
-        // use the stream in some way here
+        // use the data in some way here
     }
     rs.close();
 }
@@ -674,76 +672,76 @@ ps.close();
     the <classname>LargeObject</classname> <acronym>API</acronym> to 
     store the file:
 <programlisting>
-CREATE TABLE imagesLO (imgname text, imgOID OID);
+CREATE TABLE imageslo (imgname text, imgoid oid);
 </programlisting>
    </para>
 
    <para>
     To insert an image, you would use:
 <programlisting>
-// All LargeObject API calls must be within a transaction
+// All LargeObject API calls must be within a transaction block
 conn.setAutoCommit(false);
 
 // Get the Large Object Manager to perform operations with
 LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
 
-//create a new large object
+// Create a new large object
 int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
 
-//open the large object for write
+// Open the large object for writing
 LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
 
 // Now open the file
 File file = new File("myimage.gif");
 FileInputStream fis = new FileInputStream(file);
 
-// copy the data from the file to the large object
+// Copy the data from the file to the large object
 byte buf[] = new byte[2048];
 int s, tl = 0;
-while ((s = fis.read(buf, 0, 2048)) > 0)
-{
-       obj.write(buf, 0, s);
-       tl += s;
+while ((s = fis.read(buf, 0, 2048)) > 0) {
+    obj.write(buf, 0, s);
+    tl += s;
 }
 
 // Close the large object
 obj.close();
 
-//Now insert the row into imagesLO
-PreparedStatement ps = conn.prepareStatement("INSERT INTO imagesLO VALUES (?, ?)");
+// Now insert the row into imageslo
+PreparedStatement ps = conn.prepareStatement("INSERT INTO imageslo VALUES (?, ?)");
 ps.setString(1, file.getName());
 ps.setInt(2, oid);
 ps.executeUpdate();
 ps.close();
 fis.close();
 </programlisting>
-</para>
+   </para>
+
    <para>
     Retrieving the image from the Large Object:
 
 <programlisting>
-// All LargeObject API calls must be within a transaction
+// All LargeObject API calls must be within a transaction block
 conn.setAutoCommit(false);
 
 // Get the Large Object Manager to perform operations with
 LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
 
-PreparedStatement ps = con.prepareStatement("SELECT imgOID FROM imagesLO WHERE imgname=?");
+PreparedStatement ps = con.prepareStatement("SELECT imgoid FROM imageslo WHERE imgname = ?");
 ps.setString(1, "myimage.gif");
 ResultSet rs = ps.executeQuery();
 if (rs != null) {
-    while(rs.next()) {
-       //open the large object for reading
-       int oid = rs.getInt(1);
-       LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
-
-       //read the data
-       byte buf[] = new byte[obj.size()];
-       obj.read(buf, 0, obj.size());
-       //do something with the data read here
-
-       // Close the object
-       obj.close();
+    while (rs.next()) {
+        // Open the large object for reading
+        int oid = rs.getInt(1);
+        LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
+
+        // Read the data
+        byte buf[] = new byte[obj.size()];
+        obj.read(buf, 0, obj.size());
+        // Do something with the data read here
+
+        // Close the object
+        obj.close();
     }
     rs.close();
 }
@@ -2441,93 +2439,78 @@ public void unlink(int oid) throws SQLException
 
 
  <sect1 id="jdbc-thread">
-  <title>Using the driver in a multithreaded or a servlet environment</title>
+  <title>Using the Driver in a Multithreaded or a Servlet Environment</title>
 
   <para>
    A problem with many <acronym>JDBC</acronym> drivers is that only
    one thread can use a <classname>Connection</classname> at any one
-   time -- otherwise a thread could send a query while another one is
-   receiving results, and this would be a bad thing for the database
-   engine.
+   time --- otherwise a thread could send a query while another one is
+   receiving results, and this could cause severe confusion.
   </para>
 
   <para>
-   The <productname>PostgreSQL</productname> <acronym>JDBC</acronym> Driver
+   The <productname>PostgreSQL</productname> <acronym>JDBC</acronym> driver
    is thread safe.
    Consequently, if your application uses multiple threads then you do
-   not have to worry about complex algorithms to ensure that only one
-   uses the database at any time.
+   not have to worry about complex algorithms to ensure that only one thread
+   uses the database at a time.
   </para>
 
   <para>
    If a thread attempts to use the connection while another one is
    using it, it will wait until the other thread has finished its
-   current operation.  If it is a regular <acronym>SQL</acronym>
+   current operation.  If the operation is a regular <acronym>SQL</acronym>
    statement, then the operation consists of sending the statement and
    retrieving any <classname>ResultSet</classname> (in full).  If it
-   is a <classname>Fastpath</classname> call (e.g., reading a block
-   from a <classname>LargeObject</classname>) then it is the time to
-   send and retrieve that block.
+   is a fast-path call (e.g., reading a block
+   from a large object) then it consists of
+   sending and retrieving the respective data.
   </para>
 
   <para>
    This is fine for applications and applets but can cause a
-   performance problem with servlets.  With servlets you can have a
-   heavy load on the connection. If you have several threads
-   performing queries then each but one will pause, which may not be what
-   you are after.
-  </para>
-
-  <para>
-   To solve this, you would be advised to create a pool of
-   connections.  When ever a thread needs to use the database, it asks
-   a manager class for a <classname>Connection</classname>. The
-   manager hands a free connection to the thread and marks it as
-   busy. If a free connection is not available, it opens one.  Once
-   the thread has finished with it, it returns it to the manager who
-   can then either close it or add it to the pool. The manager would
-   also check that the connection is still alive and remove it from
-   the pool if it is dead.
-  </para>
-
-  <para>
-   So, with servlets, it is up to you to use either a single
-   connection, or a pool. The plus side for a pool is that threads
-   will not be hit by the bottle neck caused by a single network
-   connection. The down side is that it increases the load on the
-   server, as a backend process is created for each
-   <classname>Connection</classname>.  It is up to you and your
-   applications requirements.
+   performance problem with servlets.  If you have several threads
+   performing queries then each but one will pause.
+   To solve this, you are advised to create a pool of connections.
+   When ever a thread needs to use the database, it asks a manager
+   class for a <classname>Connection</classname> object. The manager
+   hands a free connection to the thread and marks it as busy. If a
+   free connection is not available, it opens one.  Once the thread
+   has finished using the connection, it returns it to the manager
+   which can then either close it or add it to the pool. The manager
+   would also check that the connection is still alive and remove it
+   from the pool if it is dead.  The down side of a connection pool is
+   that it increases the load on the server because a new session is
+   created for each <classname>Connection</classname> object.  It is
+   up to you and your applications' requirements.
   </para>
  </sect1>
 
  <sect1 id="jdbc-datasource">
-  <title>Connection Pools And DataSources</title>
-
-  <sect2 id="jdbc-ds-version">
-   <title>JDBC, JDK Version Support</title>
+  <title>Connection Pools and Data Sources</title>
 
-   <para>
+  <para>
     JDBC 2 introduced standard connection pooling features in an
     add-on API known as the <acronym>JDBC</acronym> 2.0 Optional
     Package (also known as the <acronym>JDBC</acronym> 2.0
     Standard Extension).  These features have since been included in
     the core JDBC 3 API.  The <productname>PostgreSQL</productname>
-    <acronym>JDBC</acronym> drivers support these features with
+    <acronym>JDBC</acronym> drivers support these features if it has been compiled with
     <acronym>JDK</acronym> 1.3.x in combination with the
     <acronym>JDBC</acronym> 2.0 Optional Package
-    (<acronym>JDBC</acronym> 2), or with <acronym>JDK</acronym> 1.4+
+    (<acronym>JDBC</acronym> 2), or with <acronym>JDK</acronym> 1.4 or higher
     (<acronym>JDBC</acronym> 3).  Most application servers include
     the <acronym>JDBC</acronym> 2.0 Optional Package, but it is
     also available separately from the Sun
     <ulink
     url="http://java.sun.com/products/jdbc/download.html#spec"><acronym>JDBC</acronym> download site</ulink>.
    </para>
-  </sect2>
 
   <sect2 id="jdbc-ds-intro">
-    <title>JDBC Connection Pooling API</title>
-    <para>The <acronym>JDBC</acronym> API provides a client
+   <title>Overview</title>
+
+    <para>
+     The <acronym>JDBC</acronym> API provides a client
      and a server interface for connection pooling.  The client
      interface is <literal>javax.sql.DataSource</literal>,
      which is what application code will typically use to
@@ -2535,16 +2518,22 @@ public void unlink(int oid) throws SQLException
      is <literal>javax.sql.ConnectionPoolDataSource</literal>,
      which is how most application servers will interface with
      the <productname>PostgreSQL</productname> <acronym>JDBC</acronym>
-     driver.</para>
-    <para>In an application server environment, the
+     driver.
+    </para>
+
+    <para>
+     In an application server environment, the
      application server configuration will typically refer to
      the <productname>PostgreSQL</productname>
      <literal>ConnectionPoolDataSource</literal> implementation,
      while the application component code will typically acquire a
      <literal>DataSource</literal> implementation provided by
      the application server (not by
-     <productname>PostgreSQL</productname>).</para>
-    <para>In an environment without an application server,
+     <productname>PostgreSQL</productname>).
+    </para>
+
+    <para>
+     For an environment without an application server,
      <productname>PostgreSQL</productname> provides two implementations
      of <literal>DataSource</literal> which an application can use
      directly.  One implementation performs connection pooling,
@@ -2553,19 +2542,23 @@ public void unlink(int oid) throws SQLException
      any pooling.  Again, these implementations should not be used
      in an application server environment unless the application
      server does not support the
-     <literal>ConnectionPoolDataSource</literal> interface.</para>
+     <literal>ConnectionPoolDataSource</literal> interface.
+    </para>
   </sect2>
    
   <sect2 id="jdbc-ds-cpds">
-    <title>Application Servers: ConnectionPoolDataSource</title>
-    <para><productname>PostgreSQL</productname> includes one
-     implementation of <literal>ConnectionPoolDataSource</literal>
-     for <acronym>JDBC</acronym> 2, and one for 
-     <acronym>JDBC</acronym> 3:</para>
+   <title>Application Servers: <classname>ConnectionPoolDataSource</classname></title>
+
+   <para>
+    <productname>PostgreSQL</productname> includes one implementation
+    of <classname>ConnectionPoolDataSource</classname> for
+    <acronym>JDBC</acronym> 2 and one for <acronym>JDBC</acronym> 3,
+    as shown in <xref linkend="jdbc-ds-cpds-imp-table">.
+   </para>
 
   
-    <table>
-    <title>ConnectionPoolDataSource Implementations</title>
+   <table id="jdbc-ds-cpds-imp-table">
+    <title><classname>ConnectionPoolDataSource</classname> Implementations</title>
   
     <tgroup cols=2>
      <thead>
@@ -2587,15 +2580,18 @@ public void unlink(int oid) throws SQLException
       </row>
      </tbody>
     </tgroup>
-    </table>
+   </table>
 
-    <para>Both implementations use the same configuration scheme.
-     <acronym>JDBC</acronym> requires that a
-     <literal>ConnectionPoolDataSource</literal> be configured via
-     JavaBean properties, so there are get and set methods for each of
-     these properties:</para>
-    <table>
-    <title>ConnectionPoolDataSource Configuration Properties</title>
+   <para>
+    Both implementations use the same configuration scheme.
+    <acronym>JDBC</acronym> requires that a
+    <classname>ConnectionPoolDataSource</classname> be configured via
+    JavaBean properties, shown in <xref linkend="jdbc-ds-cpds-props">,
+    so there are get and set methods for each of these properties.
+   </para>
+
+   <table id="jdbc-ds-cpds-props">
+    <title><classname>ConnectionPoolDataSource</> Configuration Properties</title>
   
     <tgroup cols=3>
      <thead>
@@ -2608,97 +2604,98 @@ public void unlink(int oid) throws SQLException
  
      <tbody>
       <row>
-       <entry>serverName</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>serverName</literal></entry>
+       <entry><type>String</type></entry>
        <entry><productname>PostgreSQL</productname> database server
-         hostname</entry>
+         host name</entry>
       </row>
  
       <row>
-       <entry>databaseName</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>databaseName</literal></entry>
+       <entry><type>String</type></entry>
        <entry><productname>PostgreSQL</productname> database name</entry>
       </row>
  
       <row>
-       <entry>portNumber</entry>
-       <entry><literal>int</literal></entry>
-       <entry><acronym>TCP/IP</acronym> port which the 
-        <productname>PostgreSQL</productname> database server is
-       listening on (or 0 to use the default port)</entry>
+       <entry><literal>portNumber</literal></entry>
+       <entry><type>int</type></entry>
+       <entry>
+        TCP port which the <productname>PostgreSQL</productname>
+        database server is listening on (or 0 to use the default port)
+       </entry>
       </row>
  
       <row>
-       <entry>user</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>user</literal></entry>
+       <entry><type>String</type></entry>
        <entry>User used to make database connections</entry>
       </row>
  
       <row>
-       <entry>password</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>password</literal></entry>
+       <entry><type>String</type></entry>
        <entry>Password used to make database connections</entry>
       </row>
  
       <row>
-       <entry>defaultAutoCommit</entry>
-       <entry><literal>boolean</literal></entry>
-       <entry>Whether connections should have autoCommit
-       enabled or disabled when they are supplied to the
-       caller.  The default is <literal>false</literal>, to
-       disable autoCommit.</entry>
+       <entry><literal>defaultAutoCommit</literal></entry>
+       <entry><type>boolean</type></entry>
+       <entry>
+        Whether connections should have autocommit enabled or disabled
+        when they are supplied to the caller.  The default is
+        <literal>false</literal>, to disable autocommit.
+       </entry>
       </row>
      </tbody>
     </tgroup>
-    </table>
-
-    <para>Many application servers use a properties-style syntax to
-     configure these properties, so it would not be unusual to
-     enter properties as a block of text.</para>
+   </table>
 
-   <example id="jdbc-cpds-config">
-    <title><literal>ConnectionPoolDataSource</literal> Configuration Example</title>
-
-    <para>
-     If the application server provides a single area to enter all
-      the properties, they might be listed like this:
+   <para>
+    Many application servers use a properties-style syntax to
+    configure these properties, so it would not be unusual to enter
+    properties as a block of text.  If the application server provides
+    a single area to enter all the properties, they might be listed
+    like this:
 <programlisting>
 serverName=localhost
 databaseName=test
 user=testuser
 password=testpassword
 </programlisting>
-      Or, separated by semicolons instead of newlines, like this:
+    Or, if semicolons are used as separators instead of newlines, it
+    could look like this:
 <programlisting>
 serverName=localhost;databaseName=test;user=testuser;password=testpassword
 </programlisting>
-    </para>
-   </example>
+   </para>
 
   </sect2>
 
   <sect2 id="jdbc-ds-ds">
-    <title>Applications: DataSource</title>
+   <title>Applications: <classname>DataSource</></title>
+
     <para><productname>PostgreSQL</productname> includes two
      implementations of <literal>DataSource</literal>
-     for <acronym>JDBC</acronym> 2, and two for <acronym>JDBC</acronym>
-     3.  The pooling implementations do not actually close connections
+     for <acronym>JDBC</acronym> 2 and two for <acronym>JDBC</acronym>
+     3, as shown in <xref linkend="jdbc-ds-ds-imp">.
+     The pooling implementations do not actually close connections
      when the client calls the <literal>close</literal> method, but
      instead return the connections to a pool of available connections
      for other clients to use.  This avoids any overhead of repeatedly
      opening and closing connections, and allows a large number of
      clients to share a small number of database connections.</para>
-    <para>The pooling datasource implementation provided here is not
+    <para>The pooling data-source implementation provided here is not
      the most feature-rich in the world.  Among other things,
      connections are never closed until the pool itself is closed;
      there is no way to shrink the pool.  As well, connections
      requested for users other than the default configured user are
      not pooled.  Many application servers
-     provide more advanced pooling features, and use the
+     provide more advanced pooling features and use the
      <literal>ConnectionPoolDataSource</literal> implementation
      instead.</para>
-    <table>
-    <title>DataSource Implementations</title>
+
+   <table id="jdbc-ds-ds-imp">
+    <title><classname>DataSource</> Implementations</title>
   
     <tgroup cols=3>
      <thead>
@@ -2738,14 +2735,16 @@ serverName=localhost;databaseName=test;user=testuser;password=testpassword
     </tgroup>
     </table>
 
-    <para>All the implementations use the same configuration scheme.
+    <para>
+     All the implementations use the same configuration scheme.
      <acronym>JDBC</acronym> requires that a
-     <literal>DataSource</literal> be configured via
-     JavaBean properties, so there are get and set methods for each of
-     these properties.</para>
+     <literal>DataSource</literal> be configured via JavaBean
+     properties, shown in <xref linkend="jdbc-ds-ds-props">, so there
+     are get and set methods for each of these properties.
+    </para>
 
-    <table>
-    <title>DataSource Configuration Properties</title>
+    <table id="jdbc-ds-ds-props">
+    <title><classname>DataSource</> Configuration Properties</title>
   
     <tgroup cols=3>
      <thead>
@@ -2758,35 +2757,35 @@ serverName=localhost;databaseName=test;user=testuser;password=testpassword
  
      <tbody>
       <row>
-       <entry>serverName</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>serverName</literal></entry>
+       <entry><type>String</type></entry>
        <entry><productname>PostgreSQL</productname> database server
-         hostname</entry>
+         host name</entry>
       </row>
  
       <row>
-       <entry>databaseName</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>databaseName</literal></entry>
+       <entry><type>String</type></entry>
        <entry><productname>PostgreSQL</productname> database name</entry>
       </row>
  
       <row>
-       <entry>portNumber</entry>
-       <entry><literal>int</literal></entry>
-       <entry><acronym>TCP/IP</acronym> port which the 
+       <entry><literal>portNumber</literal></entry>
+       <entry><type>int</type></entry>
+       <entry>TCP port which the 
         <productname>PostgreSQL</productname> database server is
        listening on (or 0 to use the default port)</entry>
       </row>
  
       <row>
-       <entry>user</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>user</literal></entry>
+       <entry><type>String</type></entry>
        <entry>User used to make database connections</entry>
       </row>
  
       <row>
-       <entry>password</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>password</literal></entry>
+       <entry><type>String</type></entry>
        <entry>Password used to make database connections</entry>
       </row>
      </tbody>
@@ -2794,10 +2793,10 @@ serverName=localhost;databaseName=test;user=testuser;password=testpassword
     </table>
 
     <para>The pooling implementations require some additional
-      configuration properties:</para>
+      configuration properties, which are shown in <xref linkend="jdbc-ds-ds-xprops">.</para>
 
-    <table>
-    <title>Additional Pooling DataSource Configuration Properties</title>
+   <table id="jdbc-ds-ds-xprops">
+    <title>Additional Pooling <classname>DataSource</> Configuration Properties</title>
   
     <tgroup cols=3>
      <thead>
@@ -2810,22 +2809,22 @@ serverName=localhost;databaseName=test;user=testuser;password=testpassword
  
      <tbody>
       <row>
-       <entry>dataSourceName</entry>
-       <entry><literal>String</literal></entry>
+       <entry><literal>dataSourceName</literal></entry>
+       <entry><type>String</type></entry>
        <entry>Every pooling <literal>DataSource</literal> must have a
-        unique name</entry>
+        unique name.</entry>
       </row>
  
       <row>
-       <entry>initialConnections</entry>
-       <entry><literal>int</literal></entry>
+       <entry><literal>initialConnections</literal></entry>
+       <entry><type>int</type></entry>
        <entry>The number of database connections to be created
        when the pool is initialized.</entry>
       </row>
  
       <row>
-       <entry>maxConnections</entry>
-       <entry><literal>int</literal></entry>
+       <entry><literal>maxConnections</literal></entry>
+       <entry><type>int</type></entry>
        <entry>The maximum number of open database connections to
        allow.  When more connections are requested, the caller
        will hang until a connection is returned to the pool.</entry>
@@ -2834,14 +2833,14 @@ serverName=localhost;databaseName=test;user=testuser;password=testpassword
     </tgroup>
     </table>
 
-    <para>Here's an example of typical application code using a
-     pooling <literal>DataSource</literal>:</para>
+    <para><xref linkend="jdbc-ds-example"> shows an example of typical application code using a
+     pooling <literal>DataSource</literal>.</para>
  
-   <example id="jdbc-ds-code">
+   <example id="jdbc-ds-example">
     <title><literal>DataSource</literal> Code Example</title>
 
     <para>
-     Code to initialize a pooling DataSource might look like this:
+     Code to initialize a pooling <classname>DataSource</classname> might look like this:
 <programlisting>
 Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
 source.setDataSourceName("A Data Source");
@@ -2853,18 +2852,18 @@ source.setMaxConnections(10);
 </programlisting>
       Then code to use a connection from the pool might look
       like this.  Note that it is critical that the connections
-      are closed, or else the pool will "leak" connections, and
-      eventually lock all the clients out.
+      are eventually closed.  Else the pool will <quote>leak</> connections and
+      will eventually lock all the clients out.
 <programlisting>
 Connection con = null;
 try {
     con = source.getConnection();
     // use connection
-} catch(SQLException e) {
+} catch (SQLException e) {
     // log error
 } finally {
-    if(con != null) {
-        try {con.close();}catch(SQLException e) {}
+    if (con != null) {
+        try { con.close(); } catch (SQLException e) {}
     }
 }
 </programlisting>
@@ -2873,34 +2872,44 @@ try {
   </sect2>
 
   <sect2 id="jdbc-jndi">
-    <title>DataSources and <acronym>JNDI</acronym></title>
-    <para>All the <literal>ConnectionPoolDataSource</literal> and
+    <title>Data Sources and <acronym>JNDI</acronym></title>
+
+    <para>
+     All the <literal>ConnectionPoolDataSource</literal> and
      <literal>DataSource</literal> implementations can be stored
-     in <acronym>JNDI</acronym>.  In the case of the non-pooling
+     in <acronym>JNDI</acronym>.  In the case of the nonpooling
      implementations, a new instance will be created every time the
      object is retrieved from <acronym>JNDI</acronym>, with the
-     same settings as the instance which was stored.  For the
+     same settings as the instance that was stored.  For the
      pooling implementations, the same instance will be retrieved
-     as long as it is available (e.g. not a different
+     as long as it is available (e.g., not a different
      <acronym>JVM</acronym> retrieving the pool from
      <acronym>JNDI</acronym>), or a new instance with the same
-     settings created otherwise.</para>
-    <para>In the application server environment, typically the
+     settings created otherwise.
+    </para>
+
+    <para>
+     In the application server environment, typically the
      application server's <literal>DataSource</literal> instance
      will be stored in <acronym>JNDI</acronym>, instead of the
      <productname>PostgreSQL</productname>
      <literal>ConnectionPoolDataSource</literal> implementation.
-     </para>
-    <para>In an application environment, the application may store
+    </para>
+
+    <para>
+     In an application environment, the application may store
      the <literal>DataSource</literal> in <acronym>JNDI</acronym>
      so that it doesn't have to make a reference to the
      <literal>DataSource</literal> available to all application
-     components that may need to use it:</para>
+     components that may need to use it.  An example of this is
+     shown in <xref linkend="jdbc-ds-jndi">.
+    </para>
+
    <example id="jdbc-ds-jndi">
-    <title><literal>DataSource</literal> <acronym>JNDI</acronym> Code Example</title>
+    <title><classname>DataSource</classname> <acronym>JNDI</acronym> Code Example</title>
 
     <para>
-     Application code to initialize a pooling DataSource and add
+     Application code to initialize a pooling <classname>DataSource</classname> and add
      it to <acronym>JNDI</acronym> might look like this:
 <programlisting>
 Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
@@ -2920,13 +2929,13 @@ try {
     DataSource source = (DataSource)new InitialContext().lookup("DataSource");
     con = source.getConnection();
     // use connection
-} catch(SQLException e) {
+} catch (SQLException e) {
     // log error
-} catch(NamingException e) {
+} catch (NamingException e) {
     // DataSource wasn't found in JNDI
 } finally {
-    if(con != null) {
-        try {con.close();}catch(SQLException e) {}
+    if (con != null) {
+        try { con.close(); } catch (SQLException e) {}
     }
 }
 </programlisting>
@@ -2934,30 +2943,25 @@ try {
    </example>
   </sect2>
 
-  <sect2 id="jdbc-app-servers">
-    <title>Specific Application Server Configurations</title>
-    <para>Configuration examples for specific application servers
-     will be included here.</para>
-  </sect2>
  </sect1>
 
  <sect1 id="jdbc-reading">
   <title>Further Reading</title>
 
   <para>
-   If you have not yet read it, I'd advise you read the
+   If you have not yet read it, you are advised you read the
    <acronym>JDBC</acronym> <acronym>API</acronym> Documentation
-   (supplied with Sun's <acronym>JDK</acronym>), and the
+   (supplied with Sun's <acronym>JDK</acronym>) and the
    <acronym>JDBC</acronym> Specification.  Both are available from
    <ulink
-   url="http://java.sun.com/products/jdbc/index.html">http://java.sun.com/products/jdbc/index.html</ulink>.
+   url="http://java.sun.com/products/jdbc/index.html"></ulink>.
   </para>
 
   <para>
    <ulink
-   url="http://jdbc.postgresql.org">http://jdbc.postgresql.org</ulink>
-   contains updated information not included in this document, and
-   also includes precompiled drivers.
+   url="http://jdbc.postgresql.org"></ulink>
+   contains updated information not included in this chapter and
+   also offers precompiled drivers.
   </para>
  </sect1>
 </chapter>
index b17892a..02d38bc 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.18 2002/09/21 18:32:53 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.19 2003/04/07 01:29:25 petere Exp $
 -->
 
  <chapter id="plperl">
@@ -34,8 +34,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.18 2002/09/21 18:32:53 pete
   <note>
    <para>
     Users of source packages must specially enable the build of
-    PL/Perl during the installation process (refer to the installation
-    instructions for more information).  Users of binary packages
+    PL/Perl during the installation process.  (Refer to the installation
+    instructions for more information.)  Users of binary packages
     might find PL/Perl in a separate subpackage.
    </para>
   </note>
@@ -57,8 +57,12 @@ CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-types
    Arguments and results are handled as in any other Perl subroutine:
    Arguments are passed in <varname>@_</varname>, and a result value
    is returned with <literal>return</> or as the last expression
-   evaluated in the function.  For example, a function returning the
-   greater of two integer values could be defined as:
+   evaluated in the function.
+  </para>
+
+  <para>
+   For example, a function returning the greater of two integer values
+   could be defined as:
 
 <programlisting>
 CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS '
@@ -145,7 +149,7 @@ SELECT name, empcomp(employee) FROM employee;
   <title>Data Values in PL/Perl</title>
 
   <para>
-   The argument values supplied to a PL/Perl function's script are
+   The argument values supplied to a PL/Perl function's code are
    simply the input arguments converted to text form (just as if they
    had been displayed by a <literal>SELECT</literal> statement).
    Conversely, the <literal>return</> command will accept any string
@@ -206,8 +210,8 @@ SELECT name, empcomp(employee) FROM employee;
    environment. This includes file handle operations,
    <literal>require</literal>, and <literal>use</literal> (for
    external modules).  There is no way to access internals of the
-   database backend process or to gain OS-level access with the
-   permissions of the <productname>PostgreSQL</productname> user ID,
+   database server process or to gain OS-level access with the
+   permissions of the server process,
    as a C function can do.  Thus, any unprivileged database user may
    be permitted to use this language.
   </para>
@@ -227,7 +231,7 @@ CREATE FUNCTION badfunc() RETURNS integer AS '
 
   <para>
    Sometimes it is desirable to write Perl functions that are not
-   restricted --- for example, one might want a Perl function that
+   restricted.  For example, one might want a Perl function that
    sends mail.  To handle these cases, PL/Perl can also be installed
    as an <quote>untrusted</> language (usually called
    <application>PL/PerlU</application>).  In this case the full Perl language is
@@ -255,7 +259,7 @@ CREATE FUNCTION badfunc() RETURNS integer AS '
 
   <para>
    The following features are currently missing from PL/Perl, but they
-   would make welcome contributions:
+   would make welcome contributions.
 
    <itemizedlist>
     <listitem>
index 84862b0..38306e1 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.16 2003/03/25 16:15:37 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.17 2003/04/07 01:29:25 petere Exp $
 -->
 
 <chapter id="plpgsql"> 
@@ -10,22 +10,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.16 2003/03/25 16:15:37 pet
  </indexterm>
 
  <para>
-  <application>PL/pgSQL</application> is a loadable procedural language for the
-  <productname>PostgreSQL</productname> database system.
- </para>
-   
- <para>
-  This package was originally written by Jan Wieck. This
-  documentation was in part written 
-  by Roberto Mello (<email>rmello@fslc.usu.edu</email>).
- </para>
+  <application>PL/pgSQL</application> is a loadable procedural
+  language for the <productname>PostgreSQL</productname> database
+  system.  The design goals of <application>PL/pgSQL</> were to create
+  a loadable procedural language that
 
-  <sect1 id="plpgsql-overview">
-   <title>Overview</title>
-
-   <para>
-    The design goals of <application>PL/pgSQL</> were to create a loadable procedural
-    language that
     <itemizedlist>
      <listitem>
       <para>
@@ -44,7 +33,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.16 2003/03/25 16:15:37 pet
      </listitem>
      <listitem>
       <para>
-       inherits all user defined types, functions and operators,
+       inherits all user-defined types, functions, and operators,
       </para>
      </listitem>
      <listitem>
@@ -59,57 +48,61 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.16 2003/03/25 16:15:37 pet
      </listitem>
     </itemizedlist>
    </para>
+
+  <sect1 id="plpgsql-overview">
+   <title>Overview</title>
+
    <para>
     The <application>PL/pgSQL</> call handler parses the function's source text and
     produces an internal binary instruction tree the first time the
-    function is called (within any one backend process).  The instruction tree
+    function is called (within each session).  The instruction tree
     fully translates the 
     <application>PL/pgSQL</> statement structure, but individual
-    <acronym>SQL</acronym> expressions and <acronym>SQL</acronym> queries
+    <acronym>SQL</acronym> expressions and <acronym>SQL</acronym> commands
     used in the function are not translated immediately.
    </para>
 
    <para>
-    As each expression and <acronym>SQL</acronym> query is first used
+    As each expression and <acronym>SQL</acronym> command is first used
        in the function, the <application>PL/pgSQL</> interpreter creates
        a prepared execution plan (using the <acronym>SPI</acronym>
        manager's <function>SPI_prepare</function> and
        <function>SPI_saveplan</function> functions).  Subsequent visits
-       to that expression or query re-use the prepared plan.  Thus, a
+       to that expression or command reuse the prepared plan.  Thus, a
        function with conditional code that contains many statements for
        which execution plans might be required will only prepare and save
        those plans that are really used during the lifetime of the
        database connection.  This can substantially reduce the total
-       amount of time required to parse, and generate query plans for the
-       statements in a procedural language function. A disadvantage is
-       that errors in a specific expression or query may not be detected
+       amount of time required to parse, and generate execution plans for the
+       statements in a <application>PL/pgSQL</> function. A disadvantage is
+       that errors in a specific expression or command may not be detected
        until that part of the function is reached in execution.
    </para>
 
    <para>
-    Once <application>PL/pgSQL</> has made a query plan for a particular
-    query in a function, it will re-use that plan for the life of the
+    Once <application>PL/pgSQL</> has made an execution plan for a particular
+    command in a function, it will reuse that plan for the life of the
     database connection.  This is usually a win for performance, but it
     can cause some problems if you dynamically
     alter your database schema. For example:
 
 <programlisting>
-CREATE FUNCTION populate() RETURNS INTEGER AS '
+CREATE FUNCTION populate() RETURNS integer AS '
 DECLARE
-    -- Declarations
+    -- declarations
 BEGIN
     PERFORM my_function();
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
 
     If you execute the above function, it will reference the OID for
-    <function>my_function()</function> in the query plan produced for
+    <function>my_function()</function> in the execution plan produced for
     the <command>PERFORM</command> statement. Later, if you
-    drop and re-create <function>my_function()</function>, then
+    drop and recreate <function>my_function()</function>, then
     <function>populate()</function> will not be able to find
     <function>my_function()</function> anymore. You would then have to
-    re-create <function>populate()</function>, or at least start a new
+    recreate <function>populate()</function>, or at least start a new
     database session so that it will be compiled afresh. Another way
     to avoid this problem is to use <command>CREATE OR REPLACE
     FUNCTION</command> when updating the definition of
@@ -119,13 +112,13 @@ END;
 
    <para>
     Because <application>PL/pgSQL</application> saves execution plans
-       in this way, queries that appear directly in a
+       in this way, SQL commands that appear directly in a
        <application>PL/pgSQL</application> function must refer to the
-       same tables and fields on every execution; that is, you cannot use
-       a parameter as the name of a table or field in a query.  To get
-       around this restriction, you can construct dynamic queries using
+       same tables and columns on every execution; that is, you cannot use
+       a parameter as the name of a table or column in an SQL command.  To get
+       around this restriction, you can construct dynamic commands using
        the <application>PL/pgSQL</application> <command>EXECUTE</command>
-       statement --- at the price of constructing a new query plan on
+       statement --- at the price of constructing a new execution plan on
        every execution.
    </para>
 
@@ -134,7 +127,7 @@ END;
         The <application>PL/pgSQL</application>
         <command>EXECUTE</command> statement is not related to the
         <command>EXECUTE</command> statement supported by the
-        <productname>PostgreSQL</productname> backend. The backend
+        <productname>PostgreSQL</productname> server. The server's
         <command>EXECUTE</command> statement cannot be used within
         <application>PL/pgSQL</> functions (and is not needed).
        </para>
@@ -142,50 +135,27 @@ END;
 
    <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 <application>PL/pgSQL</application>. It is possible to
+    for user-defined types, anything that can be defined in C language
+    functions can also be done with <application>PL/pgSQL</application>. For example, it is possible to
     create complex conditional computation functions and later use
     them to define operators or use them in functional indexes.
    </para>
+
   <sect2 id="plpgsql-advantages">
    <title>Advantages of Using <application>PL/pgSQL</application></title>
 
-   <itemizedlist>
-    <listitem>
-     <para>
-      Better performance (see <xref linkend="plpgsql-advantages-performance">)
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      SQL support (see <xref linkend="plpgsql-advantages-sqlsupport">)
-     </para>
-    </listitem> 
-
-    <listitem>
-     <para>
-      Portability (see <xref linkend="plpgsql-advantages-portability">)
-     </para>
-    </listitem>
-   </itemizedlist>
-
-   <sect3 id="plpgsql-advantages-performance">
-    <title>Better Performance</title>
-
     <para>
-         <acronym>SQL</acronym> is the language
-         <productname>PostgreSQL</> (and most other relational databases)
-         use as query language. It's portable and easy to learn. But
-         every <acronym>SQL</acronym> statement must be executed
-         individually by the database server.
+     <acronym>SQL</acronym> is the language <productname>PostgreSQL</>
+     (and most other relational databases) use as query language. It's
+     portable and easy to learn. But every <acronym>SQL</acronym>
+     statement must be executed individually by the database server.
     </para>
 
     <para>
      That means that your client application must send each query to
      the database server, wait for it to process it, receive the
      results, do some computation, then send other queries to the
-     server. All this incurs inter-process communication and may also
+     server. All this incurs interprocess communication and may also
      incur network overhead if your client is on a different machine
      than the database server.
     </para>
@@ -199,51 +169,29 @@ END;
      communication overhead. This can make for a
      considerable performance increase.
     </para>
-   </sect3>
-
-   <sect3 id="plpgsql-advantages-sqlsupport">
-    <title>SQL Support</title>
-
-    <para>
-     <application>PL/pgSQL</application> adds the power of a procedural language to the
-     flexibility and ease of <acronym>SQL</acronym>. With
-     <application>PL/pgSQL</application> you can use all the data types, columns, operators
-     and functions of SQL.    
-    </para>
-   </sect3>
-
-   <sect3 id="plpgsql-advantages-portability">
-    <title>Portability</title>
 
     <para>
-         Because <application>PL/pgSQL</application> functions run inside
-         <productname>PostgreSQL</>, these functions will run on any
-         platform where <productname>PostgreSQL</> runs. Thus you can
-         reuse code and reduce development costs.
+     Also, with <application>PL/pgSQL</application> you can use all
+     the data types, operators and functions of SQL.
     </para>
-   </sect3>
   </sect2>
 
   <sect2 id="plpgsql-overview-developing-in-plpgsql">
    <title>Developing in <application>PL/pgSQL</application></title>
 
    <para>
-    Developing in <application>PL/pgSQL</application> is pretty
-    straight forward, especially if you have developed in other
-    database procedural languages, such as <productname>Oracle</>'s
-    <application>PL/SQL</application>.  One good way to develop in
+    One good way to develop in
     <application>PL/pgSQL</> is to simply use the text editor of your
     choice to create your functions, and in another window, use
-    <command>psql</command> (<productname>PostgreSQL</>'s interactive
-    monitor) to load those functions. If you are doing it this way, it
+    <command>psql</command> to load those functions. If you are doing it this way, it
     is a good idea to write the function using <command>CREATE OR
     REPLACE FUNCTION</>. That way you can reload the file to update
     the function definition.  For example:
 <programlisting>
-CREATE OR REPLACE FUNCTION testfunc(INTEGER) RETURNS INTEGER AS '
+CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS '
          ....
 end;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
    </para>
 
@@ -251,7 +199,7 @@ end;
     While running <command>psql</command>, you can load or reload such a
     function definition file with
 <programlisting>
-    \i filename.sql
+\i filename.sql
 </programlisting>
     and then immediately issue SQL commands to test the function.
    </para>
@@ -261,22 +209,123 @@ end;
     GUI database access tool that facilitates development in a
     procedural language. One example of such as a tool is
     <application>PgAccess</>, although others exist. These tools often
-    provide convenient features such as escaping single-quotes, and
+    provide convenient features such as escaping single quotes and
     making it easier to recreate and debug functions.
    </para>
   </sect2>
  </sect1>
 
+ <sect1 id="plpgsql-quote">
+  <title>Handling of Quotations Marks</title>
+
+  <para>
+   Since the code of any procedural language function is specified
+   <command>CREATE FUNCTION</command> as a string literal, single
+   quotes inside the function body must be escaped. This can lead to
+   rather complicated code at times, especially if you are writing a
+   function that generates other functions, as in the example in <xref
+   linkend="plpgsql-statements-executing-dyn">.  The list below gives
+   you an overview over the needed levels of quotation marks in
+   various situations.  Keep this chart handy.
+  </para>
+
+  <variablelist>
+   <varlistentry>
+    <term>1 quotation mark</term>
+    <listitem>
+     <para>
+      To begin/end function bodies, for example:
+<programlisting>
+CREATE FUNCTION foo() RETURNS integer AS '...'
+    LANGUAGE plpgsql;
+</programlisting>
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>2 quotation marks</term>
+    <listitem>
+     <para>
+      For string literals inside the function body, for example:
+<programlisting>
+a_output := ''Blah'';
+SELECT * FROM users WHERE f_name=''foobar'';
+</programlisting>
+      The second line is interpreted as
+<programlisting>
+SELECT * FROM users WHERE f_name='foobar';
+</programlisting>
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>4 quotation marks</term>
+    <listitem>
+     <para>
+      When you need a single quote in a string inside the function
+      body, for example:
+<programlisting>
+a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
+</programlisting>
+      The value of <literal>a_output</literal> would then be: <literal>
+      AND name LIKE 'foobar' AND xyz</literal>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>6 quotation marks</term>
+    <listitem>
+     <para>
+      When a single quote in a string inside the function body is
+      adjacent to the end of that string constant, for example:
+<programlisting>
+a_output := a_output || '' AND name LIKE ''''foobar''''''
+</programlisting>
+      The value of <literal>a_output</literal> would then be:
+      <literal> AND name LIKE 'foobar'</literal>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>10 quotation marks</term>
+    <listitem>
+     <para>
+      When you want two single quotes in a string constant (which
+      accounts for 8 quotes) and this is adjacent to the end of that
+      string constant (2 more).  You will probably only need that if
+      you are writing a function that generates other functions.  For
+      example:
+<programlisting>
+a_output := a_output || '' if v_'' || 
+    referrer_keys.kind || '' like '''''''''' 
+    || referrer_keys.key_string || '''''''''' 
+    then return ''''''  || referrer_keys.referrer_type 
+    || ''''''; end if;''; 
+</programlisting>
+      The value of <literal>a_output</literal> would then be:
+<programlisting>
+if v_... like ''...'' then return ''...''; end if;
+</programlisting>
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </sect1>
+
  <sect1 id="plpgsql-structure">
   <title>Structure of <application>PL/pgSQL</application></title>
 
-    <para>
-     <application>PL/pgSQL</application> is a <emphasis>block
-     structured</emphasis> language.  The complete text of a function
-     definition must be a <firstterm>block</>. A block is defined as:
+  <para>
+   <application>PL/pgSQL</application> is a block-structured language.
+   The complete text of a function definition must be a
+   <firstterm>block</>. A block is defined as:
 
 <synopsis>
-<optional> &lt;&lt;label&gt;&gt; </optional>
+<optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
 <optional> DECLARE
     <replaceable>declarations</replaceable> </optional>
 BEGIN
@@ -286,8 +335,28 @@ END;
     </para>
 
     <para>
-     Any <firstterm>statement</> in the statement section of a block
-     can be a <firstterm>sub-block</>.  Sub-blocks can be used for
+     Each declaration and each statement within a block is terminated
+     by a semicolon.
+    </para>
+
+    <para>
+     All key words and identifiers can be written in mixed upper and
+     lower case.  Identifiers are implicitly converted to lower-case
+     unless double-quoted.
+    </para>
+
+    <para>
+     There are two types of comments in <application>PL/pgSQL</>. A double dash (<literal>--</literal>)
+     starts a comment that extends to the end of the line. A <literal>/*</literal>
+     starts a block comment that extends to the next occurrence of <literal>*/</literal>.
+     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 <literal>/*</literal> and <literal>*/</literal>.
+    </para>
+
+    <para>
+     Any statement in the statement section of a block
+     can be a <firstterm>subblock</>.  Subblocks can be used for
      logical grouping or to localize variables to a small group
      of statements.
     </para>
@@ -297,89 +366,65 @@ END;
      block are initialized to their default values every time the
      block is entered, not only once per function call. For example:
 <programlisting>
-CREATE FUNCTION somefunc() RETURNS INTEGER AS '
+CREATE FUNCTION somefunc() RETURNS integer AS '
 DECLARE
-   quantity INTEGER := 30;
+    quantity integer := 30;
 BEGIN
-   RAISE NOTICE ''Quantity here is %'',quantity;  -- Quantity here is 30
-   quantity := 50;
-   --
-   -- Create a sub-block
-   --
-   DECLARE
-      quantity INTEGER := 80;
-   BEGIN
-      RAISE NOTICE ''Quantity here is %'',quantity;  -- Quantity here is 80
-   END;
-
-   RAISE NOTICE ''Quantity here is %'',quantity;  -- Quantity here is 50
-
-   RETURN quantity;
+    RAISE NOTICE ''Quantity here is %'', quantity;  -- Quantity here is 30
+    quantity := 50;
+    --
+    -- Create a subblock
+    --
+    DECLARE
+        quantity integer := 80;
+    BEGIN
+        RAISE NOTICE ''Quantity here is %'', quantity;  -- Quantity here is 80
+    END;
+
+    RAISE NOTICE ''Quantity here is %'', quantity;  -- Quantity here is 50
+
+    RETURN quantity;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
     </para>
 
     <para>
-     It is important not to confuse the use of BEGIN/END for
+     It is important not to confuse the use of <command>BEGIN</>/<command>END</> for
      grouping statements in <application>PL/pgSQL</> with the database commands for
-     transaction control.  <application>PL/pgSQL</>'s BEGIN/END are only for grouping;
+     transaction control.  <application>PL/pgSQL</>'s <command>BEGIN</>/<command>END</> are only for grouping;
      they do not start or end a transaction.  Functions and trigger procedures
      are always executed within a transaction established by an outer query
      --- they cannot start or commit transactions, since
      <productname>PostgreSQL</productname> does not have nested transactions.
     </para>
-
-   <sect2>
-    <title>Lexical Details</title>
-
-    <para>
-     Each statement and declaration within a block is terminated
-     by a semicolon.
-    </para>
-
-    <para>
-     All keywords and identifiers can be written in mixed upper- and
-     lower-case.  Identifiers are implicitly converted to lower-case
-     unless double-quoted.
-    </para>
-
-    <para>
-     There are two types of comments in <application>PL/pgSQL</>. A double dash <literal>--</literal>
-     starts a comment that extends to the end of the line. A <literal>/*</literal>
-     starts a block comment that extends to the next occurrence of <literal>*/</literal>.
-     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 <literal>/*</literal> and <literal>*/</literal>.
-    </para>
-   </sect2>
   </sect1>
 
   <sect1 id="plpgsql-declarations">
     <title>Declarations</title>
 
     <para>
-     All variables, rows and records used in a block must be declared in the
+     All variables used in a block must be declared in the
      declarations section of the block. 
-     (The only exception is that the loop variable of a FOR loop iterating
+     (The only exception is that the loop variable of a <literal>FOR</> loop iterating
      over a range of integer values is automatically declared as an integer
      variable.)
     </para>
 
     <para>
      <application>PL/pgSQL</> variables can have any SQL data type, such as
-     <type>INTEGER</type>, <type>VARCHAR</type> and
-     <type>CHAR</type>.
+     <type>integer</type>, <type>varchar</type>, and
+     <type>char</type>.
     </para>
 
     <para>
      Here are some examples of variable declarations:
 <programlisting>
-user_id INTEGER;
-quantity NUMERIC(5);
-url VARCHAR;
+user_id integer;
+quantity numeric(5);
+url varchar;
 myrow tablename%ROWTYPE;
-myfield tablename.fieldname%TYPE;
+myfield tablename.columnname%TYPE;
 arow RECORD;
 </programlisting>
     </para>
@@ -389,104 +434,125 @@ arow RECORD;
 <synopsis>
 <replaceable>name</replaceable> <optional> CONSTANT </optional> <replaceable>type</replaceable> <optional> NOT NULL </optional> <optional> { DEFAULT | := } <replaceable>expression</replaceable> </optional>;
 </synopsis>
-     </para>
-
-     <para>
-      The DEFAULT clause, if given, specifies the initial value assigned
-      to the variable when the block is entered.  If the DEFAULT clause
+      The <literal>DEFAULT</> clause, if given, specifies the initial value assigned
+      to the variable when the block is entered.  If the <literal>DEFAULT</> clause
       is not given then the variable is initialized to the
-     <acronym>SQL</acronym> NULL value. 
-     </para>
-
-     <para>
-      The CONSTANT option prevents the variable from being assigned to,
+      <acronym>SQL</acronym> null value. 
+      The <literal>CONSTANT</> option prevents the variable from being assigned to,
       so that its value remains constant for the duration of the block.
-      If NOT NULL
-      is specified, an assignment of a NULL value results in a run-time
-      error. All variables declared as NOT NULL
-      must have a non-NULL default value specified.
+      If <literal>NOT NULL</>
+      is specified, an assignment of a null value results in a run-time
+      error. All variables declared as <literal>NOT NULL</>
+      must have a nonnull default value specified.
      </para>
 
      <para>
       The default value is evaluated every time the block is entered. So,
-      for example, assigning '<literal>now</literal>' to a variable of type
+      for example, assigning <literal>'now'</literal> to a variable of type
       <type>timestamp</type> causes the variable to have the
-      time of the current function call, not when the function was
+      time of the current function call, not the time when the function was
       precompiled.
      </para>
 
      <para>
       Examples:
 <programlisting>
-quantity INTEGER DEFAULT 32;
+quantity integer DEFAULT 32;
 url varchar := ''http://mysite.com'';
-user_id CONSTANT INTEGER := 10;
+user_id CONSTANT integer := 10;
 </programlisting>
      </para>
 
     <sect2 id="plpgsql-declaration-aliases">
      <title>Aliases for Function Parameters</title>
 
-    <para>
 <synopsis>
-<replaceable>name</replaceable> ALIAS FOR <replaceable>$n</replaceable>;
+<replaceable>name</replaceable> ALIAS FOR $<replaceable>n</replaceable>;
 </synopsis>
-    </para>
 
      <para>
       Parameters passed to functions are named with the identifiers
       <literal>$1</literal>, <literal>$2</literal>,
-      etc.  Optionally, aliases can be declared for <literal>$n</literal>
+      etc.  Optionally, aliases can be declared for <literal>$<replaceable>n</replaceable></literal>
       parameter names for increased readability.  Either the alias or the
       numeric identifier can then be used to refer to the parameter value.
       Some examples:
 <programlisting>
-CREATE FUNCTION sales_tax(REAL) RETURNS REAL AS '
+CREATE FUNCTION sales_tax(real) RETURNS real AS '
 DECLARE
     subtotal ALIAS FOR $1;
 BEGIN
-    return subtotal * 0.06;
+    RETURN subtotal * 0.06;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 
-CREATE FUNCTION instr(VARCHAR,INTEGER) RETURNS INTEGER AS '
+CREATE FUNCTION instr(varchar, integer) RETURNS integer AS '
 DECLARE
     v_string ALIAS FOR $1;
     index ALIAS FOR $2;
 BEGIN
-    -- Some computations here
+    -- some computations here
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 
-CREATE FUNCTION use_many_fields(tablename) RETURNS TEXT AS '
+CREATE FUNCTION use_many_fields(tablename) RETURNS text AS '
 DECLARE
     in_t ALIAS FOR $1;
 BEGIN
     RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
      </para>
     </sect2>
 
+  <sect2 id="plpgsql-declaration-type">
+   <title>Copying Types</title>
+
+<synopsis>
+<replaceable>variable</replaceable>%TYPE
+</synopsis>
+
+   <para>
+    <literal>%TYPE</literal> provides the data type of a variable or
+    table column. You can use this to declare variables that will hold
+    database values. For example, let's say you have a column named
+    <literal>user_id</literal> in your <literal>users</literal>
+    table. To declare a variable with the same data type as
+    <literal>users.user_id</> you write:
+<programlisting>
+user_id users.user_id%TYPE;
+</programlisting>
+   </para>
+
+   <para>
+    By using <literal>%TYPE</literal> you don't need to know the data
+    type of the structure you are referencing, and most importantly,
+    if the data type of the referenced item changes in the future (for
+    instance: you change the type of <literal>user_id</>
+    from <type>integer</type> to <type>real</type>), you may not need
+    to change your function definition.
+   </para>
+  </sect2>
+
     <sect2 id="plpgsql-declaration-rowtypes">
      <title>Row Types</title>
 
-    <para>
 <synopsis>
 <replaceable>name</replaceable> <replaceable>tablename</replaceable><literal>%ROWTYPE</literal>;
 </synopsis>
-    </para>
 
    <para>
     A variable of a composite type is called a <firstterm>row</>
-    variable (or <firstterm>row-type</> variable).  Such a variable can hold a
-    whole row of a SELECT or FOR
-    query result, so long as that query's column set matches the declared
-    type of the variable.  The individual fields of the row value are
-    accessed using the usual dot notation, for example
+    variable (or <firstterm>row-type</> variable).  Such a variable
+    can hold a whole row of a <command>SELECT</> or <command>FOR</>
+    query result, so long as that query's column set matches the
+    declared type of the variable.
+    <replaceable>tablename</replaceable> must be an existing table or
+    view name in the database. The individual fields of the row value
+    are accessed using the usual dot notation, for example
     <literal>rowvar.field</literal>.
    </para>
 
@@ -500,18 +566,22 @@ END;
    <para>
     Parameters to a function can be
     composite types (complete table rows). In that case, the
-    corresponding identifier $n will be a row variable, and fields can
+    corresponding identifier <literal>$<replaceable>n</replaceable></> will be a row variable, and fields can
     be selected from it, for example <literal>$1.user_id</literal>.
    </para>
 
    <para>
-    Only the user-defined attributes of a table row are accessible in a
-    row-type variable, not OID or other system attributes (because the
+    Only the user-defined columns of a table row are accessible in a
+    row-type variable, not the OID or other system columns (because the
     row could be from a view).  The fields of the row type inherit the
     table's field size or precision for data types such as
-    <type>char(n)</type>.
+    <type>char(<replaceable>n</>)</type>.
+   </para>
+
+   <para>
+    Here is an example of using composite types:
 <programlisting>
-CREATE FUNCTION use_two_tables(tablename) RETURNS TEXT AS '
+CREATE FUNCTION use_two_tables(tablename) RETURNS text AS '
 DECLARE
     in_t ALIAS FOR $1;
     use_t table2name%ROWTYPE;
@@ -519,13 +589,13 @@ BEGIN
     SELECT * INTO use_t FROM table2name WHERE ... ;
     RETURN in_t.f1 || use_t.f3 || in_t.f5 || use_t.f7;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
    </para>
   </sect2>
 
     <sect2 id="plpgsql-declaration-records">
-     <title>Records</title>
+     <title>Record Types</title>
 
     <para>
 <synopsis>
@@ -536,10 +606,10 @@ END;
    <para>
     Record variables are similar to row-type variables, but they have no
     predefined structure.  They take on the actual row structure of the
-    row they are assigned during a SELECT or FOR command.  The substructure
+    row they are assigned during a <command>SELECT</> or <command>FOR</> command.  The substructure
     of a record variable can change each time it is assigned to.
     A consequence of this is that until a record variable is first assigned
-    to, <emphasis>it has no</> substructure, and any attempt to access a
+    to, it has no substructure, and any attempt to access a
     field in it will draw a run-time error.
    </para>
 
@@ -548,89 +618,8 @@ END;
    </para>
   </sect2>
 
-    <sect2 id="plpgsql-declaration-attributes">
-     <title>Attributes</title>
-
-     <para>
-      Using the <type>%TYPE</type> and <type>%ROWTYPE</type>
-      attributes, you can declare variables with the same
-      data type or structure as another database item (e.g: a
-      table field).
-     </para>
-
-     <variablelist>
-      <varlistentry>
-       <term>
-        <replaceable>variable</replaceable>%TYPE
-       </term>
-       <listitem>
-        <para>
-         <type>%TYPE</type> provides the data type of a
-         variable or database column. You can use this to
-         declare variables that will hold database
-         values. For example, let's say you have a column
-         named <type>user_id</type> in your
-         <type>users</type> table. To declare a variable with
-         the same data type as <structname>users</>.<structfield>user_id</> you write:
-<programlisting>
-user_id   users.user_id%TYPE;
-</programlisting>
-        </para>
-
-        <para>
-         By using <type>%TYPE</type> you do not need to know
-         the data type of the structure you are referencing,
-         and most important, if the data type of the
-         referenced item changes in the future (e.g: you
-         change your table definition of user_id from INTEGER to
-         REAL), you may not need to change your function
-         definition.
-        </para>
-       </listitem>
-      </varlistentry>
-
-      <varlistentry>
-       <term>
-        <literal><replaceable>table</replaceable>%ROWTYPE</literal>
-       </term>
-       <listitem>
-        <para>
-        <type>%ROWTYPE</type> provides the composite data type corresponding
-        to a whole row of the specified table.
-        <replaceable>table</replaceable> must be an existing
-        table or view name of the database.
-        </para>
-
-<programlisting>
-DECLARE
-    users_rec users%ROWTYPE;
-    user_id users.user_id%TYPE;
-BEGIN
-    user_id := users_rec.user_id;
-    ...
-
-CREATE FUNCTION does_view_exist(INTEGER) RETURNS bool AS '
-   DECLARE
-        key ALIAS FOR $1;
-        table_data cs_materialized_views%ROWTYPE;
-   BEGIN
-        SELECT INTO table_data * FROM cs_materialized_views
-               WHERE sort_key=key;
-
-        IF NOT FOUND THEN
-           RETURN false;
-        END IF;
-        RETURN true;
-   END;
-' LANGUAGE 'plpgsql';
-</programlisting>
-       </listitem>
-      </varlistentry>
-     </variablelist>
-    </sect2>
-
     <sect2 id="plpgsql-declaration-renaming-vars">
-     <title>RENAME</title>
+     <title><literal>RENAME</></title>
 
      <para>
 <synopsis>
@@ -669,20 +658,20 @@ RENAME this_var TO that_var;
      statements are processed using the server's regular
      <acronym>SQL</acronym> executor. Expressions that appear to
      contain constants may in fact require run-time evaluation
-     (e.g. <literal>'now'</literal> for the <type>timestamp</type>
+     (e.g., <literal>'now'</literal> for the <type>timestamp</type>
      type) so it is impossible for the
      <application>PL/pgSQL</application> parser to identify real
-     constant values other than the NULL keyword. All expressions are
+     constant values other than the key word <literal>NULL</>. All expressions are
      evaluated internally by executing a query
 <synopsis>
 SELECT <replaceable>expression</replaceable>
 </synopsis>
-     using the <acronym>SPI</acronym> manager. In the expression,
+     using the <acronym>SPI</acronym> manager. For evaluation,
      occurrences of <application>PL/pgSQL</application> variable
-     identifiers are replaced by parameters and the actual values from
+     identifiers are replaced by parameters, and the actual values from
      the variables are passed to the executor in the parameter array.
      This allows the query plan for the <command>SELECT</command> to
-     be prepared just once and then re-used for subsequent
+     be prepared just once and then reused for subsequent
      evaluations.
     </para>
 
@@ -693,20 +682,20 @@ SELECT <replaceable>expression</replaceable>
      is a difference between what these two functions do:
 
 <programlisting>
-CREATE FUNCTION logfunc1 (TEXT) RETURNS TIMESTAMP AS '
+CREATE FUNCTION logfunc1(text) RETURNS timestamp AS '
     DECLARE
         logtxt ALIAS FOR $1;
     BEGIN
         INSERT INTO logtable VALUES (logtxt, ''now'');
         RETURN ''now'';
     END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
 
      and
 
 <programlisting>
-CREATE FUNCTION logfunc2 (TEXT) RETURNS TIMESTAMP AS '
+CREATE FUNCTION logfunc2(text) RETURNS timestamp AS '
     DECLARE
         logtxt ALIAS FOR $1;
         curtime timestamp;
@@ -715,31 +704,33 @@ CREATE FUNCTION logfunc2 (TEXT) RETURNS TIMESTAMP AS '
         INSERT INTO logtable VALUES (logtxt, curtime);
         RETURN curtime;
     END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
+    </para>
 
-     In the case of <function>logfunc1()</function>, the 
+    <para>
+     In the case of <function>logfunc1</function>, the 
      <productname>PostgreSQL</productname> main parser knows when 
-     preparing the plan for the INSERT, that the string 
+     preparing the plan for the <command>INSERT</command>, that the string 
      <literal>'now'</literal> should be interpreted as 
-     <type>timestamp</type> because the target field of <classname>logtable</classname>
+     <type>timestamp</type> because the target column of <classname>logtable</classname>
      is of that type. Thus, it will make a constant from it at this
      time and this constant value is then used in all invocations of 
-     <function>logfunc1()</function> during the lifetime of the
-     backend. Needless to say that this isn't what the
+     <function>logfunc1</function> during the lifetime of the
+     session. Needless to say that this isn't what the
      programmer wanted.
     </para>
 
     <para>
-     In the case of <function>logfunc2()</function>, the 
+     In the case of <function>logfunc2</function>, the 
      <productname>PostgreSQL</productname> main parser does not know
      what type <literal>'now'</literal> should become and therefore 
      it returns a data value of type <type>text</type> containing the string 
-     <literal>'now'</literal>. During the ensuing assignment
+     <literal>now</literal>. During the ensuing assignment
      to the local variable <varname>curtime</varname>, the
      <application>PL/pgSQL</application> interpreter casts this
      string to the <type>timestamp</type> type by calling the
-     <function>text_out()</function> and <function>timestamp_in()</function>
+     <function>text_out</function> and <function>timestamp_in</function>
      functions for the conversion.  So, the computed time stamp is updated
      on each execution as the programmer expects.
     </para>
@@ -765,12 +756,12 @@ CREATE FUNCTION logfunc2 (TEXT) RETURNS TIMESTAMP AS '
     types that are explicitly understood by
     <application>PL/pgSQL</application>.
     Anything not recognized as one of these statement types is presumed
-    to be an SQL query, and is sent to the main database engine to execute
-    (after substitution for any <application>PL/pgSQL</application> variables
+    to be an SQL command and is sent to the main database engine to execute
+    (after substitution of any <application>PL/pgSQL</application> variables
     used in the statement).  Thus,
-    for example, SQL <command>INSERT</>, <command>UPDATE</>, and
-    <command>DELETE</> commands may be considered to be statements of
-    <application>PL/pgSQL</application>.  But they are not specifically
+    for example, the SQL commands <command>INSERT</>, <command>UPDATE</>, and
+    <command>DELETE</> may be considered to be statements of
+    <application>PL/pgSQL</application>, but they are not specifically
     listed here.
    </para>
    
@@ -809,10 +800,10 @@ tax := subtotal * 0.06;
    </sect2>
 
    <sect2 id="plpgsql-select-into">
-    <title>SELECT INTO</title>
+    <title><command>SELECT INTO</command></title>
 
     <para>
-     The result of a SELECT command yielding multiple columns (but
+     The result of a <command>SELECT</command> command yielding multiple columns (but
      only one row) can be assigned to a record variable, row-type
      variable, or list of scalar variables.  This is done by:
 
@@ -822,60 +813,67 @@ SELECT INTO <replaceable>target</replaceable> <replaceable>expressions</replacea
 
      where <replaceable>target</replaceable> can be a record variable, a row
      variable, or a comma-separated list of simple variables and
-     record/row fields. Note that this is quite different from
-     <productname>PostgreSQL</>'s normal interpretation of SELECT INTO, which is that the
-     INTO target is a newly created table.  (If you want to create a
-     table from a SELECT result inside a <application>PL/pgSQL</application> function, use the
-     syntax <command>CREATE TABLE ... AS SELECT</command>.)
+     record/row fields.
+    </para>
+
+    <para>
+     Note that this is quite different from
+     <productname>PostgreSQL</>'s normal interpretation of
+     <command>SELECT INTO</command>, where the <literal>INTO</> target
+     is a newly created table.  If you want to create a table from a
+     <command>SELECT</> result inside a
+     <application>PL/pgSQL</application> function, use the syntax
+     <command>CREATE TABLE ... AS SELECT</command>.
     </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 run-time error
+     must exactly match the structure of the target, or a run-time error
      occurs.  When a record variable is the target, it automatically
      configures itself to the row type of the query result columns.
     </para>
 
     <para>
-     Except for the INTO clause, the SELECT statement is the same as a normal
-     SQL SELECT query and can use the full power of SELECT.
+     Except for the <literal>INTO</> clause, the <command>SELECT</>
+     statement is the same as a normal SQL <command>SELECT</> command
+     and can use its full power.
     </para>
 
     <para>
-     If the SELECT query returns zero rows, null values are assigned to the
-     target(s).  If the SELECT query returns multiple rows, the first
+     If the query returns zero rows, null values are assigned to the
+     target(s).  If the query returns multiple rows, the first
      row is assigned to the target(s) and the rest are discarded.
      (Note that <quote>the first row</> is not well-defined unless you've
-     used ORDER BY.)
+     used <literal>ORDER BY</>.)
     </para>
 
     <para>
-     At present, the INTO clause can appear almost anywhere in the SELECT
-     query, but it is recommended to place it immediately after the SELECT
-     keyword as depicted above.  Future versions of
+     At present, the <literal>INTO</> clause can appear almost anywhere in the <command>SELECT</command>
+     statement, but it is recommended to place it immediately after the <literal>SELECT</literal>
+     key word as depicted above.  Future versions of
      <application>PL/pgSQL</application> may be less forgiving about
-     placement of the INTO clause.
+     placement of the <literal>INTO</literal> clause.
     </para>
 
     <para>
-     You can use <literal>FOUND</literal> immediately after a SELECT
-     INTO statement to determine whether the assignment was successful
-     (that is, at least one row was was returned by the SELECT
-     statement). For example:
+     You can use <literal>FOUND</literal> immediately after a <command>SELECT
+     INTO</command> statement to determine whether the assignment was successful
+     (that is, at least one row was was returned by the query). For example:
   
 <programlisting>
-SELECT INTO myrec * FROM EMP WHERE empname = myname;
+SELECT INTO myrec * FROM emp WHERE empname = myname;
 IF NOT FOUND THEN
     RAISE EXCEPTION ''employee % not found'', myname;
 END IF;
 </programlisting>
-
-     Alternatively, you can use the <literal>IS NULL</literal> (or <literal>ISNULL</>) conditional to
-     test for whether a RECORD/ROW result is null.  Note that there is no
-     way to tell whether any additional rows might have been discarded.
     </para>
 
     <para>
+     To test for whether a record/row result is null, you can use the
+     <literal>IS NULL</literal> conditional.  There is, however, no
+     way to tell whether any additional rows might have been
+     discarded.  Here is an example that handles the case where no
+     rows have been returned:
 <programlisting>
 DECLARE
     users_rec RECORD;
@@ -885,7 +883,6 @@ BEGIN
 
     IF users_rec.homepage IS NULL THEN
         -- user entered no homepage, return "http://"
-
         RETURN ''http://'';
     END IF;
 END;
@@ -894,7 +891,7 @@ END;
    </sect2>
 
    <sect2 id="plpgsql-statements-perform">
-    <title>Executing an expression or query with no result</title>
+    <title>Executing an Expression or Query With No Result</title>
 
     <para>
      Sometimes one wishes to evaluate an expression or query but
@@ -907,21 +904,22 @@ END;
 PERFORM <replaceable>query</replaceable>;
 </synopsis>
 
-     This executes a <command>SELECT</command>
-     <replaceable>query</replaceable> and discards the
+     This executes <replaceable>query</replaceable>, which must be a
+     <command>SELECT</command> statement, and discards the
      result. <application>PL/pgSQL</application> variables are
      substituted in the query as usual.  Also, the special variable
      <literal>FOUND</literal> is set to true if the query produced at
-     least one row, or false if it produced no rows.
+     least one row or false if it produced no rows.
     </para>
 
     <note>
-        <para>
-         One might expect that <command>SELECT</command> with no INTO
-         clause would accomplish this result, but at present the only
-         accepted way to do it is <command>PERFORM</command>.
-        </para>
-       </note>
+     <para>
+      One might expect that <command>SELECT</command> with no
+      <literal>INTO</> clause would accomplish this result, but at
+      present the only accepted way to do it is
+      <command>PERFORM</command>.
+     </para>
+    </note>
 
     <para>
      An example:
@@ -931,109 +929,103 @@ PERFORM create_mv(''cs_session_page_requests_mv'', my_query);
     </para>
    </sect2>
    
-   <sect2 id="plpgsql-statements-executing-dyn-queries">
-    <title>Executing dynamic queries</title>
+   <sect2 id="plpgsql-statements-executing-dyn">
+    <title>Executing Dynamic Commands</title>
     
     <para>
-     Oftentimes you will want to generate dynamic queries inside your
-     <application>PL/pgSQL</application> functions, that is, queries
+     Oftentimes you will want to generate dynamic commands inside your
+     <application>PL/pgSQL</application> functions, that is, commands
      that will involve different tables or different data types each
      time they are executed.  <application>PL/pgSQL</application>'s
-     normal attempts to cache plans for queries will not work in such
+     normal attempts to cache plans for commands will not work in such
      scenarios.  To handle this sort of problem, the
      <command>EXECUTE</command> statement is provided:
 
 <synopsis>
-EXECUTE <replaceable class="command">query-string</replaceable>;
+EXECUTE <replaceable class="command">command-string</replaceable>;
 </synopsis>
 
-     where <replaceable>query-string</replaceable> is an expression
+     where <replaceable>command-string</replaceable> is an expression
      yielding a string (of type
-     <type>text</type>) containing the <replaceable>query</replaceable>
+     <type>text</type>) containing the command
      to be executed.  This string is fed literally to the SQL engine.
     </para>
 
     <para>
      Note in particular that no substitution of <application>PL/pgSQL</>
-     variables is done on the query string.  The values of variables must
-     be inserted in the query string as it is constructed.
+     variables is done on the command string.  The values of variables must
+     be inserted in the command string as it is constructed.
     </para>
 
     <para>
-    When working with dynamic queries you will have to face
+    When working with dynamic commands you will have to face
     escaping of single quotes in <application>PL/pgSQL</>. Please refer to the
-    table in <xref linkend="plpgsql-porting">
-    for a detailed explanation that will save you some effort.
+    overview in <xref linkend="plpgsql-quote">,
+    which can save you some effort.
     </para>
      
     <para>
-     Unlike all other queries in <application>PL/pgSQL</>, a
-     <replaceable>query</replaceable> run by an
-     <command>EXECUTE</command> statement is not prepared and saved
-     just once during the life of the server.  Instead, the
-     <replaceable>query</replaceable> is prepared each time the
-     statement is run. The <replaceable>query-string</replaceable> can
-     be dynamically created within the procedure to perform actions on
-     variable tables and fields.
+     Unlike all other commands in <application>PL/pgSQL</>, a command
+     run by an <command>EXECUTE</command> statement is not prepared
+     and saved just once during the life of the session.  Instead, the
+     command is prepared each time the statement is run. The command
+     string can be dynamically created within the function to perform
+     actions on variable tables and columns.
     </para>
   
     <para>
-     The results from <command>SELECT</command> queries are discarded
+     The results from <command>SELECT</command> commands are discarded
      by <command>EXECUTE</command>, and <command>SELECT INTO</command>
      is not currently supported within <command>EXECUTE</command>.
      So, the only way to extract a result from a dynamically-created
-     <command>SELECT</command> is to use the FOR-IN-EXECUTE form
+     <command>SELECT</command> is to use the <command>FOR-IN-EXECUTE</> form
      described later.
     </para>
 
     <para>
      An example:
-<informalexample>
 <programlisting>
 EXECUTE ''UPDATE tbl SET ''
-        || quote_ident(fieldname)
+        || quote_ident(colname)
         || '' = ''
         || quote_literal(newvalue)
         || '' WHERE ...'';
 </programlisting>
-</informalexample>
     </para>
 
     <para>
      This example shows use of the functions
-     <function>quote_ident</function>(<type>TEXT</type>) and
-     <function>quote_literal</function>(<type>TEXT</type>).
-     Variables containing field and table identifiers should be
-     passed to function <function>quote_ident()</function>.
-     Variables containing literal elements of the dynamic query
+     <function>quote_ident(<type>text</type>)</function> and
+     <function>quote_literal(<type>text</type>)</function>.
+     Variables containing column and table identifiers should be
+     passed to function <function>quote_ident</function>.
+     Variables containing values that act as value literals in the constructed command
      string should be passed to
-     <function>quote_literal()</function>.  Both take the
+     <function>quote_literal</function>.  Both take the
      appropriate steps to return the input text enclosed in single
      or double quotes and with any embedded special characters
      properly escaped.
     </para>
 
     <para>
-     Here is a much larger example of a dynamic query and
+     Here is a much larger example of a dynamic command and
      <command>EXECUTE</command>:
 <programlisting>
-CREATE FUNCTION cs_update_referrer_type_proc() RETURNS INTEGER AS '
+CREATE FUNCTION cs_update_referrer_type_proc() RETURNS integer AS '
 DECLARE
-    referrer_keys RECORD;  -- Declare a generic record to be used in a FOR
+    referrer_keys RECORD;  -- declare a generic record to be used in a FOR
     a_output varchar(4000);
 BEGIN 
-    a_output := ''CREATE FUNCTION cs_find_referrer_type(varchar,varchar,varchar) 
-                  RETURNS VARCHAR AS '''' 
+    a_output := ''CREATE FUNCTION cs_find_referrer_type(varchar, varchar, varchar) 
+                  RETURNS varchar AS '''' 
                      DECLARE 
                          v_host ALIAS FOR $1; 
                          v_domain ALIAS FOR $2; 
                          v_url ALIAS FOR $3;
                      BEGIN ''; 
 
-    -- 
     -- Notice how we scan through the results of a query in a FOR loop
     -- using the FOR &lt;record&gt; construct.
-    --
 
     FOR referrer_keys IN SELECT * FROM cs_referrer_keys ORDER BY try_order LOOP
         a_output := a_output || '' IF v_'' || referrer_keys.kind || '' LIKE '''''''''' 
@@ -1041,24 +1033,21 @@ BEGIN
                  || referrer_keys.referrer_type || ''''''; END IF;''; 
     END LOOP; 
   
-    a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE ''''plpgsql'''';''; 
+    a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE plpgsql;''; 
  
-    -- This works because we are not substituting any variables
-    -- Otherwise it would fail. Look at PERFORM for another way to run functions
-    
     EXECUTE a_output; 
 END; 
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
     </para>
    </sect2>
 
    <sect2 id="plpgsql-statements-diagnostics">
-    <title>Obtaining result status</title>
+    <title>Obtaining the Result Status</title>
 
     <para>
         There are several ways to determine the effect of a command. The
-        first method is to use the <literal>GET DIAGNOSTICS</literal>,
+        first method is to use the <command>GET DIAGNOSTICS</command>,
         which has the form:
 
 <synopsis>
@@ -1066,26 +1055,27 @@ GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replace
 </synopsis>
 
      This command allows retrieval of system status indicators.  Each
-     <replaceable>item</replaceable> is a keyword identifying a state
+     <replaceable>item</replaceable> is a key word identifying a state
      value to be assigned to the specified variable (which should be
      of the right data type to receive it).  The currently available
      status items are <varname>ROW_COUNT</>, the number of rows
-     processed by the last <acronym>SQL</acronym> query sent down to
-     the <acronym>SQL</acronym> engine; and <varname>RESULT_OID</>,
+     processed by the last <acronym>SQL</acronym> command sent down to
+     the <acronym>SQL</acronym> engine, and <varname>RESULT_OID</>,
      the OID of the last row inserted by the most recent
-     <acronym>SQL</acronym> query.  Note that <varname>RESULT_OID</>
-     is only useful after an INSERT query.
+     <acronym>SQL</acronym> command.  Note that <varname>RESULT_OID</>
+     is only useful after an <command>INSERT</command> command.
     </para>
+
     <para>
-<informalexample>
+     An example:
 <programlisting>
-      GET DIAGNOSTICS var_integer = ROW_COUNT;
+GET DIAGNOSTICS var_integer = ROW_COUNT;
 </programlisting>
-</informalexample>
     </para>
 
     <para>
-     There is a special variable named <literal>FOUND</literal> of
+     The second method to determine the effects of a command is the
+     special variable named <literal>FOUND</literal> of
      type <type>boolean</type>.  <literal>FOUND</literal> starts out
      false within each <application>PL/pgSQL</application> function.
      It is set by each of the following types of statements:
@@ -1152,7 +1142,7 @@ GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replace
    </para>
    
    <sect2 id="plpgsql-statements-returning">
-    <title>Returning from a function</title>
+    <title>Returning From a Function</title>
 
     <para>
      There are two commands available that allow you to return data
@@ -1163,23 +1153,24 @@ GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replace
     <sect3>
      <title><command>RETURN</></title>
 
-     <para>
 <synopsis>
 RETURN <replaceable>expression</replaceable>;
 </synopsis>
 
-      <command>RETURN</command> with an expression is used to return
-      from a <application>PL/pgSQL</> function that does not return a
-      set.  The function terminates and the value of
-      <replaceable>expression</replaceable> is returned to the caller.
+     <para>
+      <command>RETURN</command> with an expression terminates the
+      function and returns the value of
+      <replaceable>expression</replaceable> to the caller.  This form
+      is to be used for <application>PL/pgSQL</> functions that does
+      not return a set.
      </para>
 
      <para>
-      To return a composite (row) value, you must write a record or row
-      variable as the <replaceable>expression</replaceable>.  When
-      returning a scalar type, any expression can be used.
-      The expression's result will be automatically cast into the
-      function's return type as described for assignments.
+      When returning a scalar type, any expression can be used. The
+      expression's result will be automatically cast into the
+      function's return type as described for assignments. To return a
+      composite (row) value, you must write a record or row variable
+      as the <replaceable>expression</replaceable>.
      </para>
 
      <para>
@@ -1188,8 +1179,8 @@ RETURN <replaceable>expression</replaceable>;
       without hitting a <command>RETURN</command> statement, a run-time
       error will occur. Note that if you have declared the function to
       return <type>void</type>, a <command>RETURN</command> statement
-      must still be specified; however, the expression following
-      <command>RETURN</command> is optional, and will be ignored in
+      must still be specified; the expression following
+      <command>RETURN</command> is, however, optional and will be ignored in
       any case.
      </para>
     </sect3>
@@ -1203,7 +1194,7 @@ RETURN NEXT <replaceable>expression</replaceable>;
 
      <para>
       When a <application>PL/pgSQL</> function is declared to return
-      <literal>SETOF</literal> <replaceable>sometype</>, the procedure
+      <literal>SETOF <replaceable>sometype</></literal>, the procedure
       to follow is slightly different.  In that case, the individual
       items to return are specified in <command>RETURN NEXT</command>
       commands, and then a final <command>RETURN</command> command
@@ -1211,6 +1202,9 @@ RETURN NEXT <replaceable>expression</replaceable>;
       finished executing.  <command>RETURN NEXT</command> can be used
       with both scalar and composite data types; in the later case, an
       entire <quote>table</quote> of results will be returned.
+     </para>
+
+     <para>
       Functions that use <command>RETURN NEXT</command> should be
       called in the following fashion:
 
@@ -1218,7 +1212,7 @@ RETURN NEXT <replaceable>expression</replaceable>;
 SELECT * FROM some_func();
 </programlisting>
 
-      That is, the function is used as a table source in a FROM
+      That is, the function is used as a table source in a <literal>FROM</literal>
       clause.
      </para>
 
@@ -1233,11 +1227,6 @@ SELECT * FROM some_func();
       have no argument, causes control to exit the function.
      </para>
 
-     <para>
-      For more information on using set-returning functions in
-      <productname>PostgreSQL</productname>, refer to XXX.
-     </para
-
      <note>
       <para>
        The current implementation of <command>RETURN NEXT</command>
@@ -1251,7 +1240,7 @@ SELECT * FROM some_func();
        allow users to allow users to define set-returning functions
        that do not have this limitation.  Currently, the point at
        which data begins being written to disk is controlled by the
-       <varname>SORT_MEM</> configuration variable.  Administrators
+       <varname>sort_mem</> configuration variable.  Administrators
        who have sufficient memory to store larger result sets in
        memory should consider increasing this parameter.
       </para>
@@ -1274,7 +1263,7 @@ SELECT * FROM some_func();
       <para><literal>IF ... THEN ... ELSE</></>
      </listitem>
      <listitem>
-      <para><literal>IF ... THEN ... ELSE IF</> and</>
+      <para><literal>IF ... THEN ... ELSE IF</></>
      </listitem>
      <listitem>
       <para><literal>IF ... THEN ... ELSIF ... THEN ... ELSE</></>
@@ -1285,19 +1274,22 @@ SELECT * FROM some_func();
     <sect3>
      <title><literal>IF-THEN</></title>
 
-       <para>
 <synopsis>
 IF <replaceable>boolean-expression</replaceable> THEN
     <replaceable>statements</replaceable>
 END IF;
 </synopsis>
 
+       <para>
         <literal>IF-THEN</literal> statements are the simplest form of
         <literal>IF</literal>. The statements between
         <literal>THEN</literal> and <literal>END IF</literal> will be
         executed if the condition is true. Otherwise, they are
         skipped.
+       </para>
 
+       <para>
+        Example:
 <programlisting>
 IF v_user_id &lt;&gt; 0 THEN
     UPDATE users SET email = v_email WHERE user_id = v_user_id;
@@ -1309,7 +1301,6 @@ END IF;
      <sect3>
       <title><literal>IF-THEN-ELSE</></title>
 
-       <para>
 <synopsis>
 IF <replaceable>boolean-expression</replaceable> THEN
     <replaceable>statements</replaceable>
@@ -1318,25 +1309,30 @@ ELSE
 END IF;
 </synopsis>
 
+       <para>
         <literal>IF-THEN-ELSE</literal> statements add to
         <literal>IF-THEN</literal> by letting you specify an
         alternative set of statements that should be executed if the
-        condition evaluates to FALSE.
+        condition evaluates to false.
+       </para>
 
+       <para>
+        Examples:
 <programlisting>
-IF parentid IS NULL or parentid = ''''
-THEN 
-    return fullname;
+IF parentid IS NULL OR parentid = ''''
+THEN
+    RETURN fullname;
 ELSE
-    return hp_true_filename(parentid) || ''/'' || fullname;
+    RETURN hp_true_filename(parentid) || ''/'' || fullname;
 END IF;
+</programlisting>
 
-
+<programlisting>
 IF v_count > 0 THEN 
-    INSERT INTO users_count(count) VALUES(v_count);
-    return ''t'';
-ELSE 
-    return ''f'';
+    INSERT INTO users_count (count) VALUES (v_count);
+    RETURN ''t'';
+ELSE
+    RETURN ''f'';
 END IF;
 </programlisting>
      </para>
@@ -1351,11 +1347,11 @@ END IF;
 
 <programlisting>
 IF demo_row.sex = ''m'' THEN
-  pretty_sex := ''man'';
+    pretty_sex := ''man'';
 ELSE
-  IF demo_row.sex = ''f'' THEN
-    pretty_sex := ''woman'';
-  END IF;
+    IF demo_row.sex = ''f'' THEN
+        pretty_sex := ''woman'';
+    END IF;
 END IF;
 </programlisting>
        </para>
@@ -1365,16 +1361,16 @@ END IF;
         <literal>IF</literal> statement inside the
         <literal>ELSE</literal> part of an outer <literal>IF</literal>
         statement. Thus you need one <literal>END IF</literal>
-        statement for each nested IF and one for the parent
+        statement for each nested <literal>IF</literal> and one for the parent
         <literal>IF-ELSE</literal>.  This is workable but grows
         tedious when there are many alternatives to be checked.
+        Hence the next form.
        </para>
      </sect3>
 
      <sect3>
       <title><literal>IF-THEN-ELSIF-ELSE</></title>
 
-       <para>
 <synopsis>
 IF <replaceable>boolean-expression</replaceable> THEN
     <replaceable>statements</replaceable>
@@ -1390,6 +1386,7 @@ IF <replaceable>boolean-expression</replaceable> THEN
 END IF;
 </synopsis>
 
+       <para>
         <literal>IF-THEN-ELSIF-ELSE</> provides a more convenient
         method of checking many alternatives in one statement.
         Formally it is equivalent to nested
@@ -1408,16 +1405,11 @@ ELSIF number &gt; 0 THEN
 ELSIF number &lt; 0 THEN
     result := ''negative'';
 ELSE
-    -- hmm, the only other possibility is that number IS NULL
+    -- hmm, the only other possibility is that number is null
     result := ''NULL'';
 END IF;
 </programlisting>
        </para>
-
-       <para>
-        The final <literal>ELSE</literal> statement is optional.
-       </para>
-
      </sect3>
    </sect2>
 
@@ -1425,51 +1417,52 @@ END IF;
     <title>Simple Loops</title>
 
     <para>
-     With the LOOP, EXIT, WHILE and FOR statements, you can arrange
-     for your <application>PL/pgSQL</application> function to repeat
-     a series of commands.
+     With the <literal>LOOP</>, <literal>EXIT</>, <literal>WHILE</>,
+     and <literal>FOR</> statements, you can arrange for your
+     <application>PL/pgSQL</application> function to repeat a series
+     of commands.
     </para>
 
     <sect3>
-     <title>LOOP</title>
+     <title><literal>LOOP</></title>
 
-     <para>
 <synopsis>
-<optional>&lt;&lt;label&gt;&gt;</optional>
+<optional>&lt;&lt;<replaceable>label</replaceable>&gt;&gt;</optional>
 LOOP
     <replaceable>statements</replaceable>
 END LOOP;
 </synopsis>
 
-      LOOP defines an unconditional loop that is repeated indefinitely
-      until terminated by an EXIT or <command>RETURN</command>
-      statement.  The optional label can be used by EXIT statements in
+     <para>
+      <literal>LOOP</> defines an unconditional loop that is repeated indefinitely
+      until terminated by an <literal>EXIT</> or <command>RETURN</command>
+      statement.  The optional label can be used by <literal>EXIT</> statements in
       nested loops to specify which level of nesting should be
       terminated.
      </para>
     </sect3>
 
      <sect3>
-      <title>EXIT</title>
+      <title><literal>EXIT</></title>
 
-       <para>
 <synopsis>
 EXIT <optional> <replaceable>label</replaceable> </optional> <optional> WHEN <replaceable>expression</replaceable> </optional>;
 </synopsis>
 
+       <para>
         If no <replaceable>label</replaceable> is given,
         the innermost loop is terminated and the
-        statement following END LOOP is executed next.
+        statement following <literal>END LOOP</> is executed next.
         If <replaceable>label</replaceable> is given, it
         must be the label of the current or some outer level of nested loop
         or block. Then the named loop or block is terminated and control
         continues with the statement after the loop's/block's corresponding
-        END.
+        <literal>END</>.
        </para>
 
        <para>
-        If WHEN is present, loop exit occurs only if the specified condition
-       is true, otherwise control passes to the statement after EXIT.
+        If <literal>WHEN</> is present, loop exit occurs only if the specified condition
+       is true, otherwise control passes to the statement after <literal>EXIT</>.
        </para>
 
        <para>
@@ -1490,7 +1483,7 @@ END LOOP;
 BEGIN
     -- some computations
     IF stocks > 100000 THEN
-        EXIT;  -- illegal. Can't use EXIT outside of a LOOP
+        EXIT;  -- invalid; cannot use EXIT outside of LOOP
     END IF;
 END;
 </programlisting>
@@ -1498,17 +1491,17 @@ END;
      </sect3>
 
      <sect3>
-      <title>WHILE</title>
+      <title><literal>WHILE</></title>
 
-       <para>
 <synopsis>
-<optional>&lt;&lt;label&gt;&gt;</optional>
+<optional>&lt;&lt;<replaceable>label</replaceable>&gt;&gt;</optional>
 WHILE <replaceable>expression</replaceable> LOOP
     <replaceable>statements</replaceable>
 END LOOP;
 </synopsis>
 
-        The WHILE statement repeats a
+       <para>
+        The <literal>WHILE</> statement repeats a
         sequence of statements so long as the condition expression
        evaluates to true.  The condition is checked just before
        each entry to the loop body.
@@ -1529,32 +1522,31 @@ END LOOP;
      </sect3>
 
      <sect3>
-      <title>FOR (integer for-loop)</title>
+      <title><literal>FOR</> (integer variant)</title>
 
-       <para>
 <synopsis>
-<optional>&lt;&lt;label&gt;&gt;</optional>
+<optional>&lt;&lt;<replaceable>label</replaceable>&gt;&gt;</optional>
 FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> .. <replaceable>expression</replaceable> LOOP
     <replaceable>statements</replaceable>
 END LOOP;
 </synopsis>
 
-        This form of FOR creates a loop that iterates over a range of integer
+       <para>
+        This form of <literal>FOR</> creates a loop that iterates over a range of integer
        values. The variable 
         <replaceable>name</replaceable> is automatically defined as type
-        integer and exists only inside the loop. The two expressions giving
+        <type>integer</> and exists only inside the loop. The two expressions giving
         the lower and upper bound of the range are evaluated once when entering
-        the loop. The iteration step is normally 1, but is -1 when REVERSE is
+        the loop. The iteration step is normally 1, but is -1 when <literal>REVERSE</> is
        specified.
        </para>
 
        <para>
-        Some examples of integer FOR loops:
+        Some examples of integer <literal>FOR</> loops:
 <programlisting>
 FOR i IN 1..10 LOOP
-  -- some expressions here
-
-    RAISE NOTICE ''i is %'',i;
+    -- some expressions here
+    RAISE NOTICE ''i is %'', i;
 END LOOP;
 
 FOR i IN REVERSE 10..1 LOOP
@@ -1569,73 +1561,70 @@ END LOOP;
     <title>Looping Through Query Results</title>
 
     <para>
-     Using a different type of FOR loop, you can iterate through
+     Using a different type of <literal>FOR</> loop, you can iterate through
      the results of a query and manipulate that data
      accordingly. The syntax is:
 <synopsis>
-<optional>&lt;&lt;label&gt;&gt;</optional>
-FOR <replaceable>record | row</replaceable> IN <replaceable>select_query</replaceable> LOOP
+<optional>&lt;&lt;<replaceable>label</replaceable>&gt;&gt;</optional>
+FOR <replaceable>record_or_row</replaceable> IN <replaceable>query</replaceable> LOOP
     <replaceable>statements</replaceable>
 END LOOP;
 </synopsis>
-     The record or row variable is successively assigned all the rows
-     resulting from the <command>SELECT</command> query and the loop
+     The record or row variable is successively assigned each row
+     resulting from the query (a <command>SELECT</command> command) and the loop
      body is executed for each row. Here is an example:
-    </para>
-
-    <para>
 <programlisting>
-CREATE FUNCTION cs_refresh_mviews () RETURNS INTEGER AS '
+CREATE FUNCTION cs_refresh_mviews() RETURNS integer AS '
 DECLARE
-     mviews RECORD;
+    mviews RECORD;
 BEGIN
-     PERFORM cs_log(''Refreshing materialized views...'');
+    PERFORM cs_log(''Refreshing materialized views...'');
 
-     FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP
+    FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP
 
-         -- Now "mviews" has one record from cs_materialized_views
+        -- Now "mviews" has one record from cs_materialized_views
 
-         PERFORM cs_log(''Refreshing materialized view '' || quote_ident(mviews.mv_name) || ''...'');
-         EXECUTE ''TRUNCATE TABLE  '' || quote_ident(mviews.mv_name);
-         EXECUTE ''INSERT INTO '' || quote_ident(mviews.mv_name) || '' '' || mviews.mv_query;
-     END LOOP;
+        PERFORM cs_log(''Refreshing materialized view '' || quote_ident(mviews.mv_name) || ''...'');
+        EXECUTE ''TRUNCATE TABLE  '' || quote_ident(mviews.mv_name);
+        EXECUTE ''INSERT INTO '' || quote_ident(mviews.mv_name) || '' '' || mviews.mv_query;
+    END LOOP;
 
-     PERFORM cs_log(''Done refreshing materialized views.'');
-     RETURN 1;
-end;
-' LANGUAGE 'plpgsql';
+    PERFORM cs_log(''Done refreshing materialized views.'');
+    RETURN 1;
+END;
+' LANGUAGE plpgsql;
 </programlisting>
 
-     If the loop is terminated by an EXIT statement, the last
+     If the loop is terminated by an <literal>EXIT</> statement, the last
      assigned row value is still accessible after the loop.
     </para>
 
     <para>
-     The FOR-IN-EXECUTE statement is another way to iterate over
+     The <literal>FOR-IN-EXECUTE</> statement is another way to iterate over
      records:
 <synopsis>
-<optional>&lt;&lt;label&gt;&gt;</optional>
-FOR <replaceable>record | row</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP 
+<optional>&lt;&lt;<replaceable>label</replaceable>&gt;&gt;</optional>
+FOR <replaceable>record_or_row</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP 
     <replaceable>statements</replaceable>
 END LOOP;
 </synopsis>
      This is like the previous form, except that the source
      <command>SELECT</command> statement is specified as a string
-     expression, which is evaluated and re-planned on each entry to
-     the FOR loop.  This allows the programmer to choose the speed of
-     a pre-planned query or the flexibility of a dynamic query, just
+     expression, which is evaluated and replanned on each entry to
+     the <literal>FOR</> loop.  This allows the programmer to choose the speed of
+     a preplanned query or the flexibility of a dynamic query, just
      as with a plain <command>EXECUTE</command> statement.
     </para>
 
     <note>
     <para>
      The <application>PL/pgSQL</> parser presently distinguishes the
-     two kinds of FOR loops (integer or record-returning) by checking
-     whether the target variable mentioned just after FOR has been
-     declared as a record/row variable.  If not, it's presumed to be
-     an integer FOR loop.  This can cause rather nonintuitive error
+     two kinds of <literal>FOR</> loops (integer or query result) by checking
+     whether the target variable mentioned just after <literal>FOR</> has been
+     declared as a record or row variable.  If not, it's presumed to be
+     an integer <literal>FOR</> loop.  This can cause rather nonintuitive error
      messages when the true problem is, say, that one has
-     misspelled the FOR variable name.
+     misspelled the variable name after the <literal>FOR</>.
     </para>
     </note>
   </sect2>
@@ -1650,7 +1639,7 @@ END LOOP;
     the query result a few rows at a time. One reason for doing this is
     to avoid memory overrun when the result contains a large number of
     rows. (However, <application>PL/pgSQL</> users do not normally need
-    to worry about that, since FOR loops automatically use a cursor
+    to worry about that, since <literal>FOR</> loops automatically use a cursor
     internally to avoid memory problems.) A more interesting usage is to
     return a reference to a cursor that it has created, allowing the
     caller to read the rows. This provides an efficient way to return
@@ -1668,13 +1657,13 @@ END LOOP;
      Another way is to use the cursor declaration syntax,
      which in general is:
 <synopsis>
-<replaceable>name</replaceable> CURSOR <optional> ( <replaceable>arguments</replaceable> ) </optional> FOR <replaceable>select_query</replaceable> ;
+<replaceable>name</replaceable> CURSOR <optional> ( <replaceable>arguments</replaceable> ) </optional> FOR <replaceable>query</replaceable> ;
 </synopsis>
      (<literal>FOR</> may be replaced by <literal>IS</> for
      <productname>Oracle</productname> compatibility.)
-     <replaceable>arguments</replaceable>, if any, are a
-     comma-separated list of <replaceable>name</replaceable>
-     <replaceable>datatype</replaceable> pairs that define names to be
+     <replaceable>arguments</replaceable>, if specified, is a
+     comma-separated list of pairs <literal><replaceable>name</replaceable>
+     <replaceable>datatype</replaceable></literal> that define names to be
      replaced by parameter values in the given query.  The actual
      values to substitute for these names will be specified later,
      when the cursor is opened.
@@ -1684,8 +1673,8 @@ END LOOP;
 <programlisting>
 DECLARE
     curs1 refcursor;
-    curs2 CURSOR FOR SELECT * from tenk1;
-    curs3 CURSOR (key int) IS SELECT * from tenk1 where unique1 = key;
+    curs2 CURSOR FOR SELECT * FROM tenk1;
+    curs3 CURSOR (key integer) IS SELECT * FROM tenk1 WHERE unique1 = key;
 </programlisting>
      All three of these variables have the data type <type>refcursor</>,
      but the first may be used with any query, while the second has
@@ -1705,18 +1694,18 @@ DECLARE
      Before a cursor can be used to retrieve rows, it must be
      <firstterm>opened</>. (This is the equivalent action to the SQL
      command <command>DECLARE CURSOR</>.) <application>PL/pgSQL</> has
-     four forms of the OPEN statement, two of which use unbound cursor
-     variables and the other two use bound cursor variables.
+     three forms of the <command>OPEN</> statement, two of which use unbound cursor
+     variables and the other uses a bound cursor variable.
     </para>
 
     <sect3>
-     <title>OPEN FOR SELECT</title>
+     <title><command>OPEN FOR SELECT</command></title>
 
-       <para>
 <synopsis>
 OPEN <replaceable>unbound-cursor</replaceable> FOR SELECT ...;
 </synopsis>
 
+       <para>
     The cursor variable is opened and given the specified query to
        execute.  The cursor cannot be open already, and it must have been
        declared as an unbound cursor (that is, as a simple
@@ -1724,8 +1713,11 @@ OPEN <replaceable>unbound-cursor</replaceable> FOR SELECT ...;
        is treated in the same way as other <command>SELECT</command>
        statements in <application>PL/pgSQL</>: <application>PL/pgSQL</>
        variable names are substituted, and the query plan is cached for
-       possible re-use.
+       possible reuse.
+       </para>
 
+       <para>
+        An example:
 <programlisting>
 OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;
 </programlisting>
@@ -1733,13 +1725,13 @@ OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;
      </sect3>
 
     <sect3>
-     <title>OPEN FOR EXECUTE</title>
+     <title><command>OPEN FOR EXECUTE</command></title>
 
-        <para>
 <synopsis>
 OPEN <replaceable>unbound-cursor</replaceable> FOR EXECUTE <replaceable class="command">query-string</replaceable>;
 </synopsis>
 
+        <para>
          The cursor variable is opened and given the specified query to
          execute.  The cursor cannot be open already, and it must have been
          declared as an unbound cursor (that is, as a simple
@@ -1747,7 +1739,10 @@ OPEN <replaceable>unbound-cursor</replaceable> FOR EXECUTE <replaceable class="c
          expression in the same way as in the <command>EXECUTE</command>
          command.  As usual, this gives flexibility so the query can vary
          from one run to the next.
+       </para>
 
+       <para>
+        An example:
 <programlisting>
 OPEN curs1 FOR EXECUTE ''SELECT * FROM '' || quote_ident($1);
 </programlisting>
@@ -1755,21 +1750,24 @@ OPEN curs1 FOR EXECUTE ''SELECT * FROM '' || quote_ident($1);
      </sect3>
 
     <sect3>
-     <title>Opening a bound cursor</title>
+     <title>Opening a Bound Cursor</title>
 
-        <para>
 <synopsis>
 OPEN <replaceable>bound-cursor</replaceable> <optional> ( <replaceable>argument_values</replaceable> ) </optional>;
 </synopsis>
 
+        <para>
          This form of <command>OPEN</command> is used to open a cursor
          variable whose query was bound to it when it was declared.  The
          cursor cannot be open already.  A list of actual argument value
          expressions must appear if and only if the cursor was declared to
          take arguments.  These values will be substituted in the query.
-         The query plan for a bound cursor is always considered cacheable
-         --- there is no equivalent of <command>EXECUTE</command> in this case.
+         The query plan for a bound cursor is always considered cacheable;
+         there is no equivalent of <command>EXECUTE</command> in this case.
+         </para>
 
+    <para>
+     Examples:
 <programlisting>
 OPEN curs2;
 OPEN curs3(42);
@@ -1791,51 +1789,57 @@ OPEN curs3(42);
      opened the cursor to begin with.  You can return a <type>refcursor</>
      value out of a function and let the caller operate on the cursor.
      (Internally, a <type>refcursor</> value is simply the string name
-     of a Portal containing the active query for the cursor.  This name
+     of a so-called portal containing the active query for the cursor.  This name
      can be passed around, assigned to other <type>refcursor</> variables,
-     and so on, without disturbing the Portal.)
+     and so on, without disturbing the portal.)
     </para>
 
     <para>
-     All Portals are implicitly closed at transaction end.  Therefore
-     a <type>refcursor</> value is useful to reference an open cursor
+     All portals are implicitly closed at transaction end.  Therefore
+     a <type>refcursor</> value is usable to reference an open cursor
      only until the end of the transaction.
     </para>
 
     <sect3>
-     <title>FETCH</title>
+     <title><literal>FETCH</></title>
 
-        <para>
 <synopsis>
 FETCH <replaceable>cursor</replaceable> INTO <replaceable>target</replaceable>;
 </synopsis>
 
+        <para>
          <command>FETCH</command> retrieves the next row from the
          cursor into a target, which may be a row variable, a record
          variable, or a comma-separated list of simple variables, just like
          <command>SELECT INTO</command>.  As with <command>SELECT
           INTO</command>, the special variable <literal>FOUND</literal> may
          be checked to see whether a row was obtained or not.
+         </para>
 
+    <para>
+     An example:
 <programlisting>
 FETCH curs1 INTO rowvar;
-FETCH curs2 INTO foo,bar,baz;
+FETCH curs2 INTO foo, bar, baz;
 </programlisting>
        </para>
      </sect3>
 
     <sect3>
-     <title>CLOSE</title>
+     <title><literal>CLOSE</></title>
 
-       <para>
 <synopsis>
 CLOSE <replaceable>cursor</replaceable>;
 </synopsis>
 
+       <para>
     <command>CLOSE</command> closes the Portal underlying an open
        cursor.  This can be used to release resources earlier than end of
        transaction, or to free up the cursor variable to be opened again.
+       </para>
 
+       <para>
+        An example:
 <programlisting>
 CLOSE curs1;
 </programlisting>
@@ -1846,15 +1850,13 @@ CLOSE curs1;
      <title>Returning Cursors</title>
 
        <para>
-
         <application>PL/pgSQL</> functions can return cursors to the
         caller. This is used to return multiple rows or columns from
-        the function. The function opens the cursor and returns the
+        the function. To do this, the function opens the cursor and returns the
         cursor name to the caller. The caller can then
-        <command>FETCH</command> rows from the cursor. The cursor can
+        fetch rows from the cursor. The cursor can
         be closed by the caller, or it will be closed automatically
         when the transaction closes.
-
        </para>
 
        <para>
@@ -1868,10 +1870,10 @@ INSERT INTO test VALUES ('123');
 
 CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '
 BEGIN
-        OPEN $1 FOR SELECT col FROM test;
-        RETURN $1;
+    OPEN $1 FOR SELECT col FROM test;
+    RETURN $1;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 BEGIN;
 SELECT reffunc('funccursor');
@@ -1886,20 +1888,20 @@ COMMIT;
 <programlisting>
 CREATE FUNCTION reffunc2() RETURNS refcursor AS '
 DECLARE
-        ref refcursor;
+    ref refcursor;
 BEGIN
-        OPEN ref FOR SELECT col FROM test;
-        RETURN ref;
+    OPEN ref FOR SELECT col FROM test;
+    RETURN ref;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 BEGIN;
 SELECT reffunc2();
   
-        reffunc2      
-  --------------------
  &lt;unnamed cursor 1&gt;
-  (1 row)
+      reffunc2      
+--------------------
+ &lt;unnamed cursor 1&gt;
+(1 row)
 
 FETCH ALL IN "&lt;unnamed cursor 1&gt;";
 COMMIT;
@@ -1917,7 +1919,7 @@ COMMIT;
     raise errors.
 
 <synopsis>
-RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">variable</replaceable> <optional>...</optional></optional>;
+RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">variable</replaceable> <optional>...</optional></optional>;
 </synopsis>
 
     Possible levels are <literal>DEBUG</literal> (write the message to
@@ -1926,17 +1928,17 @@ RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="pa
     <literal>NOTICE</literal> and <literal>WARNING</literal> (write
     the message to the server log and send it to the client, with
     respectively higher priorities), and <literal>EXCEPTION</literal>
-    (raise an error and abort the current transaction). Whether error
+    (raise an error and abort the current transaction). Whether
     messages of a particular priority are reported to the client,
     written to the server log, or both is controlled by the
-    <option>LOG_MIN_MESSAGES</option> and
-    <option>CLIENT_MIN_MESSAGES</option> configuration variables. See
+    <option>log_min_messages</option> and
+    <option>client_min_messages</option> configuration variables. See
     <xref linkend="runtime-config"> for more information.
    </para>
 
    <para>
     Inside the format string, <literal>%</literal> is replaced by the
-    next optional argument's external representation. Write
+    next optional argument's string representation. Write
     <literal>%%</literal> to emit a literal <literal>%</literal>. Note
     that the optional arguments must presently be simple variables,
     not expressions, and the format must be a simple string literal.
@@ -1949,38 +1951,33 @@ RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="pa
     -->
 
    <para>
-    Examples:
+    In this example, the value of <literal>v_job_id</> will replace the
+    <literal>%</literal> in the string.
 <programlisting>
-RAISE NOTICE ''Calling cs_create_job(%)'',v_job_id;
+RAISE NOTICE ''Calling cs_create_job(%)'', v_job_id;
 </programlisting>
-
-    In this example, the value of v_job_id will replace the
-    <literal>%</literal> in the string.
    </para>
 
    <para>
+    This example will abort the transaction with the given error message.
 <programlisting>
-RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
+RAISE EXCEPTION ''Inexistent ID --> %'', user_id;
 </programlisting>
-    This will abort the transaction with the given error message.
    </para>
 
-  <sect2 id="plpgsql-exceptions">
-   <title>Exceptions</title>
-
     <para>
      <productname>PostgreSQL</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 main loop to get the next query from the client application.
+     into the main loop to get the next command from the client application.
     </para>
 
     <para>
      It is possible to hook into the error mechanism to notice that this
      happens. But currently it is impossible to tell what really
-     caused the abort (input/output conversion error, floating-point
-     error, parse error). And it is possible that the database backend
+     caused the abort (data type format error, floating-point
+     error, parse error, etc.). And it is possible that the database server
      is in an inconsistent state at this point so returning to the upper
      executor or issuing more commands might corrupt the whole database.
     </para>
@@ -1993,7 +1990,6 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
      function and where (line number and type of statement) this
      happened.  The error always stops execution of the function.
     </para>
-  </sect2>
  </sect1>
 
  <sect1 id="plpgsql-trigger">
@@ -2021,8 +2017,8 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
      <listitem>
       <para>
        Data type <type>RECORD</type>; variable holding the new
-       database row for INSERT/UPDATE operations in ROW level
-       triggers. This variable is NULL in STATEMENT level triggers.
+       database row for <command>INSERT</>/<command>UPDATE</> operations in row-level
+       triggers. This variable is null in statement-level triggers.
       </para>
      </listitem>
     </varlistentry>
@@ -2032,8 +2028,8 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
      <listitem>
       <para>
        Data type <type>RECORD</type>; variable holding the old
-       database row for UPDATE/DELETE operations in ROW level
-       triggers. This variable is NULL in STATEMENT level triggers.
+       database row for <command>UPDATE</>/<command>DELETE</> operations in row-level
+       triggers. This variable is null in statement-level triggers.
       </para>
      </listitem>
     </varlistentry>
@@ -2075,9 +2071,9 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
      <listitem>
       <para>
        Data type <type>text</type>; a string of
-       <literal>INSERT</literal>, <literal>UPDATE</literal> or
+       <literal>INSERT</literal>, <literal>UPDATE</literal>, or
        <literal>DELETE</literal> telling for which operation the
-       trigger is fired.
+       trigger was fired.
       </para>
      </listitem>
     </varlistentry>
@@ -2118,8 +2114,8 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
       <para>
        Data type array of <type>text</type>; the arguments from
               the <command>CREATE TRIGGER</command> statement.
-       The index counts from 0 and can be given as an expression. Invalid
-       indices (&lt; 0 or &gt;= <varname>tg_nargs</>) result in a null value.
+       The index counts from 0. Invalid
+       indices (less than 0 or greater than or equal to <varname>tg_nargs</>) result in a null value.
       </para>
      </listitem>
     </varlistentry>
@@ -2127,34 +2123,40 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
   </para>
 
    <para>
-    A trigger function must return either NULL or a record/row value
+    A trigger function must return either null or a record/row value
     having exactly the structure of the table the trigger was fired
-    for. The return value of a BEFORE or AFTER STATEMENT level
-    trigger, or an AFTER ROW level trigger is ignored; it may as well
-    return NULL. However, any of these types of triggers can still
+    for. The return value of a <literal>BEFORE</> or <literal>AFTER</> statement-level
+    trigger or an <literal>AFTER</> row-level trigger is ignored; it may as well
+    be null. However, any of these types of triggers can still
     abort the entire trigger operation by raising an error.
    </para>
 
    <para>
-    ROW level triggers fired BEFORE may return NULL to signal the
+    Row-level triggers fired <literal>BEFORE</> may return null to signal the
     trigger manager to skip the rest of the operation for this row
-    (ie, subsequent triggers are not fired, and the
-    INSERT/UPDATE/DELETE does not occur for this row).  If a non-NULL
+    (i.e., subsequent triggers are not fired, and the
+    <command>INSERT</>/<command>UPDATE</>/<command>DELETE</> does not occur for this row).  If a nonnull
     value is returned then the operation proceeds with that row value.
-    Note that returning a row value different from the original value
-    of NEW alters the row that will be inserted or updated.  It is
-    possible to replace single values directly in NEW and return that,
+    Returning a row value different from the original value
+    of <varname>NEW</> alters the row that will be inserted or updated.  It is
+    possible to replace single values directly in <varname>NEW</> and return <varname>NEW</>,
     or to build a complete new record/row to return.
    </para>
 
-   <example>
-    <title>A <application>PL/pgSQL</application> Trigger Procedure Example</title>
+   <para>
+    <xref linkend="plpgsql-trigger-example"> shows an example of a
+    trigger procedure in <application>PL/pgSQL</application>.
+   </para>
+
+   <example id="plpgsql-trigger-example">
+    <title>A <application>PL/pgSQL</application> Trigger Procedure</title>
 
     <para>
      This example trigger ensures that any time a row is inserted or updated
      in the table, the current user name and time are stamped into the
      row. And it ensures that an employee's name is given and that the
      salary is a positive value.
+    </para>
 
 <programlisting>
 CREATE TABLE emp (
@@ -2164,18 +2166,18 @@ CREATE TABLE emp (
     last_user text
 );
 
-CREATE FUNCTION emp_stamp () RETURNS TRIGGER AS '
+CREATE FUNCTION emp_stamp() RETURNS trigger AS '
     BEGIN
         -- Check that empname and salary are given
-        IF NEW.empname ISNULL THEN
-            RAISE EXCEPTION ''empname cannot be NULL value'';
+        IF NEW.empname IS NULL THEN
+            RAISE EXCEPTION ''empname cannot be null'';
         END IF;
-        IF NEW.salary ISNULL THEN
-            RAISE EXCEPTION ''% cannot have NULL salary'', NEW.empname;
+        IF NEW.salary IS NULL THEN
+            RAISE EXCEPTION ''% cannot have null salary'', NEW.empname;
         END IF;
 
         -- Who works for us when she must pay for it?
-        IF NEW.salary < 0 THEN
+        IF NEW.salary &lt; 0 THEN
             RAISE EXCEPTION ''% cannot have a negative salary'', NEW.empname;
         END IF;
 
@@ -2184,138 +2186,17 @@ CREATE FUNCTION emp_stamp () RETURNS TRIGGER AS '
         NEW.last_user := current_user;
         RETURN NEW;
     END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
     FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
 </programlisting>
-    </para>
-   </example>
-  </sect1>
-
-  <!-- **** PL/pgSQL Examples **** -->
-
-  <sect1 id="plpgsql-examples">
-   <title>Examples</title>
-
-   <para>
-    Here are only a few functions to demonstrate how easy it is to
-    write <application>PL/pgSQL</>
-    functions. For more complex examples the programmer
-    might look at the regression test for <application>PL/pgSQL</>.
-   </para>
-
-   <para>
-    One painful detail in writing functions in
-       <application>PL/pgSQL</application> is the handling of single
-       quotes. The function's source text in <command>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 quotes as in the examples below should be used. Any
-       solution for this in future versions of
-       <productname>PostgreSQL</productname> will be forward compatible.
-   </para>
-
-   <para>
-    For a detailed explanation and examples of how to escape single
-    quotes in different situations, please see <xref linkend="plpgsql-quote">.
-   </para>
-
-   <example>
-    <title>A Simple <application>PL/pgSQL</application> Function to Increment an Integer</title>
-
-    <para>
-     The following two <application>PL/pgSQL</application> functions are identical to their
-     counterparts from the C language function discussion. This
-     function receives an <type>integer</type> and increments it by
-     one, returning the incremented value.
-    </para>
-
-<programlisting>
-CREATE FUNCTION add_one (integer) RETURNS INTEGER AS '
-    BEGIN
-        RETURN $1 + 1;
-    END;
-' LANGUAGE 'plpgsql';
-</programlisting>
-   </example>
-
-   <example>
-    <title>A Simple <application>PL/pgSQL</application> Function to Concatenate Text</title>
-
-    <para>
-     This function receives two <type>text</type> parameters and
-     returns the result of concatenating them.
-    </para>
-
-<programlisting>
-CREATE FUNCTION concat_text (TEXT, TEXT) RETURNS TEXT AS '
-    BEGIN
-        RETURN $1 || $2;
-    END;
-' LANGUAGE 'plpgsql';
-</programlisting>
-   </example>
-
-   <example>
-    <title>A <application>PL/pgSQL</application> Function on Composite Type</title>
-
-    <para>
-     In this example, we take <literal>EMP</> (a table) and an
-     <type>integer</type> as arguments to our function, which returns
-     a <type>boolean</type>. If the <structfield>salary</> field of the <structname>EMP</> table is
-     <literal>NULL</literal>, we return <literal>f</>. Otherwise we compare with
-     that field with the <type>integer</type> passed to the function
-     and return the <type>boolean</type> result of the comparison (t
-     or f). This is the <application>PL/pgSQL</application> equivalent to the example from the C
-     functions.
-    </para>
-
-<programlisting>
-CREATE FUNCTION c_overpaid (EMP, INTEGER) RETURNS BOOLEAN AS '
-    DECLARE
-        emprec ALIAS FOR $1;
-        sallim ALIAS FOR $2;
-    BEGIN
-        IF emprec.salary ISNULL THEN
-            RETURN ''f'';
-        END IF;
-        RETURN emprec.salary > sallim;
-    END;
-' LANGUAGE 'plpgsql';
-</programlisting>
    </example>
   </sect1>
 
   <!-- **** Porting from Oracle PL/SQL **** -->
 
  <sect1 id="plpgsql-porting">
-
-  <sect1info>
-   <date>
-    February 2001
-   </date>
-   <author>
-    <firstname>Roberto</firstname>
-    <surname>Mello</surname>
-    <affiliation>
-     <address>
-      <email>rmello@fslc.usu.edu</email>
-     </address>
-    </affiliation>
-   </author>
-<!--
-  Breaks HTML manifest file
-   <legalnotice>
-    <para>
-     Except for portions of this document quoted from other sources,
-     this document is licensed under the BSD License.
-    </para>
-   </legalnotice>
--->
-  </sect1info> 
-
   <title>Porting from <productname>Oracle</productname> PL/SQL</title>
 
   <indexterm zone="plpgsql-porting">
@@ -2326,43 +2207,26 @@ CREATE FUNCTION c_overpaid (EMP, INTEGER) RETURNS BOOLEAN AS '
    <primary>PL/SQL</primary>
   </indexterm>
 
-  <note>
-   <title>Author</title>
-   <para>
-    Roberto Mello (<email>rmello@fslc.usu.edu</email>)
-   </para>
-  </note>
-
   <para>
-   This section explains differences between <productname>Oracle</>'s PL/SQL and
-   <productname>PostgreSQL</>'s <application>PL/pgSQL</application> languages in the hopes of helping developers
-   port applications from Oracle to <productname>PostgreSQL</>.  Most of the code here
-   is from the <ulink url="http://www.arsdigita.com">ArsDigita</ulink>
-   <ulink url="http://www.arsdigita.com/asj/clickstream">Clickstream
-   module</ulink> that I ported to <productname>PostgreSQL</> when I took an
-   internship with <ulink url="http://www.openforce.net">OpenForce
-   Inc.</ulink> in the Summer of 2000.
+   This section explains differences between
+   <productname>PostgreSQL</>'s <application>PL/pgSQL</application>
+   language and Oracle's <application>PL/SQL</application> language,
+   to help developers that port applications from Oracle to
+   <productname>PostgreSQL</>.
   </para>
 
   <para>
-   <application>PL/pgSQL</application> is similar to PL/SQL in many aspects. It is a block
-   structured, imperative language (all variables have to be
-   declared). PL/SQL has many more features than its <productname>PostgreSQL</>
-   counterpart, but <application>PL/pgSQL</application> allows for a great deal of functionality
-   and it is being improved constantly.
-  </para>
-
-  <sect2>
-   <title>Main Differences</title>
-
-   <para>
-    Some things you should keep in mind when porting from
-    <productname>Oracle</productname> to <productname>PostgreSQL</>:
+   <application>PL/pgSQL</application> is similar to PL/SQL in many
+   aspects. It is a block-structured, imperative language, and all
+   variables have to be declared.  Assignments, loops, conditionals
+   are similar.  The main differences you should keep in mind when
+   porting from <application>PL/SQL</> to
+   <application>PL/pgSQL</application> are:
 
     <itemizedlist>
      <listitem>
       <para>
-       No default parameters in <productname>PostgreSQL</>.
+       There are no default values for parameters in <productname>PostgreSQL</>.
       </para>
      </listitem>
 
@@ -2375,146 +2239,41 @@ CREATE FUNCTION c_overpaid (EMP, INTEGER) RETURNS BOOLEAN AS '
 
      <listitem>
       <para>
-       Assignments, loops and conditionals are similar. 
+       No need for cursors in <application>PL/pgSQL</>, just put the
+       query in the <literal>FOR</literal> statement.  (See <xref
+       linkend="plpgsql-porting-ex2">.)
       </para>
      </listitem>
 
      <listitem>
       <para>
-       No need for cursors in <productname>PostgreSQL</>, just put the query in the FOR 
-       statement (see example below)
+       In <productname>PostgreSQL</> you need to escape single
+       quotes in the function body. See <xref linkend="plpgsql-quote">.
       </para>
      </listitem>
 
      <listitem>
       <para>
-       In <productname>PostgreSQL</> you <emphasis>need</emphasis> to escape single
-       quotes. See <xref linkend="plpgsql-quote">.
+       Instead of packages, use schemas to organize your functions
+       into groups.
       </para>
      </listitem>
     </itemizedlist>
    </para>
 
-   <sect3 id="plpgsql-quote">
-    <title>Quote Me on That: Escaping Single Quotes</title>
-
-    <para>
-     In <productname>PostgreSQL</> you need to escape single quotes inside your
-     function definition. This can lead to quite amusing code at
-     times, especially if you are creating a function that generates
-     other function(s), as in 
-     <xref linkend="plpgsql-porting-nastyquote">.  
-     One thing to keep in mind
-     when escaping lots of single quotes is that, except for the
-     beginning/ending quotes, all the others will come in even
-     quantity.
-    </para>
-
-    <para>
-     <xref linkend="plpgsql-quoting-table"> gives the scoop.  (You'll
-     love this little chart.)
-    </para>
-
-    <table id="plpgsql-quoting-table">
-     <title>Single Quotes Escaping Chart</title>
-
-     <tgroup cols="4">
-      <thead>
-       <row>
-        <entry>No. of Quotes</entry>
-        <entry>Usage</entry>
-        <entry>Example</entry>
-        <entry>Result</entry>
-       </row>
-      </thead>
-
-      <tbody>
-       <row>
-        <entry>1</entry>
-        <entry>To begin/terminate function bodies</entry>
-        <entry><programlisting>
-CREATE FUNCTION foo() RETURNS INTEGER AS '...'
-LANGUAGE 'plpgsql';
-</programlisting></entry>
-        <entry>as is</entry>
-       </row>
-
-       <row>
-        <entry>2</entry>
-        <entry>In assignments, SELECT statements, to delimit strings, etc.</entry>
-        <entry><programlisting>
-a_output := ''Blah'';
-SELECT * FROM users WHERE f_name=''foobar'';
-</programlisting></entry>
-        <entry><literal>SELECT * FROM users WHERE f_name='foobar';</literal></entry>
-       </row>
-
-       <row>
-        <entry>4</entry>
-        <entry>
-         When you need two single quotes in your resulting string
-         without terminating that string.
-        </entry>
-        <entry><programlisting>
-a_output := a_output || '' AND name 
-    LIKE ''''foobar'''' AND ...''
-</programlisting></entry>
-        <entry><literal>AND name LIKE 'foobar' AND ...</literal></entry>
-       </row>
-
-       <row>
-        <entry>6</entry>
-        <entry>
-         When you want double quotes in your resulting string
-         <emphasis>and</emphasis> terminate that string.
-        </entry>
-        <entry><programlisting>
-a_output := a_output || '' AND name 
-    LIKE ''''foobar''''''
-</programlisting></entry>
-        <entry>
-         <literal>AND name LIKE 'foobar'</literal>
-        </entry>
-       </row>
-
-       <row>
-        <entry>10</entry>
-        <entry>
-         When you want two single quotes in the resulting string
-         (which accounts for 8 quotes) <emphasis>and</emphasis>
-         terminate that string (2 more).  You will probably only need
-         that if you were using a function to generate other functions
-         (like in <xref linkend="plpgsql-porting-nastyquote">).
-        </entry>
-        <entry><programlisting>
-a_output := a_output || '' if v_'' || 
-    referrer_keys.kind || '' like '''''''''' 
-    || referrer_keys.key_string || '''''''''' 
-    then return ''''''  || referrer_keys.referrer_type 
-    || ''''''; end if;''; 
-</programlisting></entry>
-        <entry>
-         <literal>if v_<...> like ''<...>'' then return ''<...>''; end if;</literal>
-        </entry>
-       </row>
-      </tbody>
-     </tgroup>
-    </table>
-   </sect3>
-  </sect2>  
+  <sect2>
+   <title>Porting Examples</title>
 
-  <sect2 id="plpgsql-porting-functions">
-   <title>
-    Porting Functions
-   </title>
+   <para>
+    <xref linkend="pgsql-porting-ex1"> shows how to port a simple
+    function from <application>PL/SQL</> to <application>PL/pgSQL</>.
+   </para>
 
-   <example>
-    <title>
-     A Simple Function
-    </title>
+   <example id="pgsql-porting-ex1">
+    <title>Porting a Simple Function from <application>PL/SQL</> to <application>PL/pgSQL</></title>
 
     <para>
-     Here is an <productname>Oracle</productname> function:
+     Here is an <productname>Oracle</productname> <application>PL/SQL</> function:
 <programlisting>
 CREATE OR REPLACE FUNCTION cs_fmt_browser_version(v_name IN varchar, v_version IN varchar)
 RETURN varchar IS
@@ -2525,7 +2284,7 @@ BEGIN
     RETURN v_name || '/' || v_version;
 END;
 /
-SHOW ERRORS;
+show errors;
 </programlisting>
     </para>
 
@@ -2545,11 +2304,11 @@ SHOW ERRORS;
        <para>
         <productname>Oracle</productname> can have
         <literal>IN</literal>, <literal>OUT</literal>, and
-        <literal>INOUT</literal> parameters passed to functions.  The
+        <literal>INOUT</literal> parameters passed to functions.
         <literal>INOUT</literal>, for example, means that the
         parameter will receive a value and return
-        another. <productname>PostgreSQL</> only has <quote>IN</quote>
-        parameters and functions can return only a single value.
+        another. <productname>PostgreSQL</> only has <literal>IN</literal>
+        parameters.
        </para>
       </listitem>
 
@@ -2557,16 +2316,15 @@ SHOW ERRORS;
        <para>
         The <literal>RETURN</literal> key word in the function
         prototype (not the function body) becomes
-        <literal>RETURNS</literal> in <productname>PostgreSQL</>.
+        <literal>RETURNS</literal> in PostgreSQL.
        </para>
       </listitem>
 
       <listitem>
        <para>
-        On <productname>PostgreSQL</> functions are created using single quotes as
-        delimiters, so you have to escape single quotes inside your
-        functions (which can be quite annoying at times; see <xref
-        linkend="plpgsql-quote">).
+        In <productname>PostgreSQL</>, functions are created using
+        single quotes as the delimiters of the function body, so you
+        have to escape single quotes inside the function body.
        </para>
       </listitem>
 
@@ -2580,12 +2338,12 @@ SHOW ERRORS;
     </para>
 
     <para>
-     So let's see how this function would look when ported to
+     This is how this function would look when ported to
      <productname>PostgreSQL</>:
 
 <programlisting>
-CREATE OR REPLACE FUNCTION cs_fmt_browser_version(VARCHAR, VARCHAR)
-RETURNS VARCHAR AS '
+CREATE OR REPLACE FUNCTION cs_fmt_browser_version(varchar, varchar)
+RETURNS varchar AS '
 DECLARE
     v_name ALIAS FOR $1;
     v_version ALIAS FOR $2;
@@ -2595,24 +2353,30 @@ BEGIN
     END IF;
     RETURN v_name || ''/'' || v_version;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
     </para>
    </example>
+
+   <para>
+    <xref linkend="plpgsql-porting-ex2"> shows how to port a
+    function that creates another function and how to handle to
+    ensuing quoting problems.
+   </para>
  
-   <example id="plpgsql-porting-nastyquote">
-    <title>
-     A Function that Creates Another Function
-    </title>
+   <example id="plpgsql-porting-ex2">
+    <title>Porting a Function that Creates Another Function from <application>PL/SQL</> to <application>PL/pgSQL</></title>
 
     <para>
      The following procedure grabs rows from a
      <command>SELECT</command> statement and builds a large function
      with the results in <literal>IF</literal> statements, for the
-     sake of efficiency. Notice particularly the differences in
-     cursors, <literal>FOR</literal> loops, and the need to escape
-     single quotes in <productname>PostgreSQL</>.
+     sake of efficiency. Notice particularly the differences in the
+     cursor and the <literal>FOR</literal> loop,
+    </para>
 
+    <para>
+     This is the Oracle version:
 <programlisting>
 CREATE OR REPLACE PROCEDURE cs_update_referrer_type_proc IS
     CURSOR referrer_keys IS 
@@ -2634,7 +2398,7 @@ referrer_key.key_string || ''' THEN RETURN ''' || referrer_key.referrer_type ||
     EXECUTE IMMEDIATE a_output; 
 END; 
 / 
-show errors
+show errors;
 </programlisting>
     </para>
 
@@ -2642,23 +2406,21 @@ show errors
      Here is how this function would end up in <productname>PostgreSQL</>:
 
 <programlisting>
-CREATE FUNCTION cs_update_referrer_type_proc() RETURNS INTEGER AS '
+CREATE FUNCTION cs_update_referrer_type_proc() RETURNS integer AS '
 DECLARE
     referrer_keys RECORD;  -- Declare a generic record to be used in a FOR
     a_output varchar(4000);
 BEGIN 
-    a_output := ''CREATE FUNCTION cs_find_referrer_type(VARCHAR,VARCHAR,VARCHAR
-                  RETURNS VARCHAR AS '''' 
+    a_output := ''CREATE FUNCTION cs_find_referrer_type(varchar, varchar, varchar
+                  RETURNS varchar AS '''' 
                      DECLARE 
                          v_host ALIAS FOR $1; 
                          v_domain ALIAS FOR $2; 
                          v_url ALIAS FOR $3;
                      BEGIN ''; 
 
-    -- 
     -- Notice how we scan through the results of a query in a FOR loop
     -- using the FOR &lt;record&gt; construct.
-    --
 
     FOR referrer_keys IN SELECT * FROM cs_referrer_keys ORDER BY try_order LOOP
         a_output := a_output || '' IF v_'' || referrer_keys.kind || '' LIKE '''''''''' 
@@ -2666,47 +2428,60 @@ BEGIN
                  || referrer_keys.referrer_type || ''''''; END IF;''; 
     END LOOP; 
   
-    a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE ''''plpgsql'''';''; 
+    a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE plpgsql;''; 
  
-    -- This works because we are not substituting any variables
-    -- Otherwise it would fail. Look at PERFORM for another way to run functions
+    -- EXECUTE will work because we are not substituting any variables.
+    -- Otherwise it would fail.  Look at PERFORM for another way to run functions.
     
     EXECUTE a_output; 
 END; 
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
     </para>
    </example>
  
-   <example>
-    <title>
-     A Procedure with a lot of String Manipulation and <literal>OUT</> Parameters
-    </title>
+   <para>
+    <xref linkend="plpgsql-porting-ex3"> shows how to port a function
+    with <literal>OUT</> parameters and string manipulation.
+    <productname>PostgreSQL</> does not have an
+    <function>instr</function> function, but you can work around it
+    using a combination of other functions.  In <xref
+    linkend="plpgsql-porting-appendix"> there is a
+    <application>PL/pgSQL</application> implementation of
+    <function>instr</function> that you can use to make your porting
+    easier.
+   </para>
+
+   <example id="plpgsql-porting-ex3">
+    <title>Porting a Procedure With String Manipulation and
+    <literal>OUT</> Parameters from <application>PL/SQL</> to
+    <application>PL/pgSQL</></title>
 
     <para>
      The following <productname>Oracle</productname> PL/SQL procedure is used to parse a URL and
-     return several elements (host, path and query). It is an
-     procedure because in <application>PL/pgSQL</application> functions only one value can be returned
-     (see <xref linkend="plpgsql-porting-procedures">).  In
+     return several elements (host, path, and query).
+     <application>PL/pgSQL</application> functions can return only one value.  In
      <productname>PostgreSQL</>, one way to work around this is to split the procedure
      in three different functions: one to return the host, another for
-     the path and another for the query.
+     the path, and another for the query.
     </para>
 
+    <para>
+     This is the Oracle version:
 <programlisting>
 CREATE OR REPLACE PROCEDURE cs_parse_url(
     v_url IN VARCHAR,
     v_host OUT VARCHAR,  -- This will be passed back
     v_path OUT VARCHAR,  -- This one too
     v_query OUT VARCHAR) -- And this one
-is
+IS
     a_pos1 INTEGER;
     a_pos2 INTEGER;
-begin
+BEGIN
     v_host := NULL;
     v_path := NULL;
     v_query := NULL;
-    a_pos1 := instr(v_url, '//'); -- <productname>PostgreSQL</> doesn't have an instr function
+    a_pos1 := instr(v_url, '//');
 
     IF a_pos1 = 0 THEN
         RETURN;
@@ -2732,28 +2507,30 @@ END;
 /
 show errors;
 </programlisting>
+    </para>
 
     <para>
-     Here is how this procedure could be translated for <productname>PostgreSQL</>:
+     Here is how the <application>PL/pgSQL</> function that returns
+     the host part could look like:
 
 <programlisting>
-CREATE OR REPLACE FUNCTION cs_parse_url_host(VARCHAR) RETURNS VARCHAR AS ' 
-DECLARE 
-    v_url ALIAS FOR $1; 
-    v_host VARCHAR; 
-    v_path VARCHAR; 
-    a_pos1 INTEGER; 
-    a_pos2 INTEGER; 
-    a_pos3 INTEGER; 
+CREATE OR REPLACE FUNCTION cs_parse_url_host(varchar) RETURNS varchar AS '
+DECLARE
+    v_url ALIAS FOR $1;
+    v_host varchar;
+    v_path varchar;
+    a_pos1 integer;
+    a_pos2 integer;
+    a_pos3 integer;
 BEGIN 
     v_host := NULL; 
-    a_pos1 := instr(v_url,''//''); 
+    a_pos1 := instr(v_url, ''//'');
 
     IF a_pos1 = 0 THEN 
         RETURN '''';  -- Return a blank
     END IF; 
 
-    a_pos2 := instr(v_url,''/'',a_pos1 + 2); 
+    a_pos2 := instr(v_url,''/'',a_pos1 + 2);
     IF a_pos2 = 0 THEN 
         v_host := substr(v_url, a_pos1 + 2); 
         v_path := ''/''; 
@@ -2763,37 +2540,21 @@ BEGIN
     v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2 ); 
     RETURN v_host; 
 END; 
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
     </para>
    </example>
 
-   <note>
-    <para>
-     <productname>PostgreSQL</> does not have an <function>instr</function> function,
-     so you can work around it using a combination of other functions.
-     I got tired of doing this and created my own
-     <function>instr</function> functions that behave exactly like
-     <productname>Oracle</productname>'s (it makes life easier). See the <xref
-     linkend="plpgsql-porting-appendix"> for the code.
-    </para>
-   </note>
-  </sect2>
-
-  <sect2 id="plpgsql-porting-procedures">
-   <title>
-    Procedures
-   </title>
-
    <para>
-    <productname>Oracle</productname> procedures give a little more
-    flexibility to the developer because nothing needs to be
-    explicitly returned, but it can be through the use of
-    <literal>INOUT</> or <literal>OUT</> parameters.
+    <xref linkend="plpgsql-porting-ex4"> shows how to port a procedure
+    that uses numerous features that are specific to Oracle.
    </para>
 
-   <para>
-    An example:
+   <example id="plpgsql-porting-ex4">
+    <title>Porting a Procedure from <application>PL/SQL</> to <application>PL/pgSQL</></title>
+
+    <para>
+     The Oracle version:
 
 <programlisting>
 CREATE OR REPLACE PROCEDURE cs_create_job(v_job_id IN INTEGER) IS
@@ -2802,9 +2563,7 @@ CREATE OR REPLACE PROCEDURE cs_create_job(v_job_id IN INTEGER) IS
 BEGIN
     LOCK TABLE cs_jobs IN EXCLUSIVE MODE;<co id="co.plpgsql-porting-locktable">
 
-    SELECT count(*) INTO a_running_job_count 
-    FROM cs_jobs
-    WHERE end_stamp IS NULL;
+    SELECT count(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp IS NULL;
 
     IF a_running_job_count > 0 THEN
         COMMIT; -- free lock<co id="co.plpgsql-porting-commit">
@@ -2827,13 +2586,13 @@ show errors
 
    <para>
     Procedures like this can be easily converted into <productname>PostgreSQL</>
-    functions returning an <type>INTEGER</type>. This procedure in
+    functions returning an <type>integer</type>. This procedure in
     particular is interesting because it can teach us some things:
 
     <calloutlist>
      <callout arearefs="co.plpgsql-porting-pragma">
       <para>
-       There is no <literal>pragma</literal> statement in <productname>PostgreSQL</>.
+       There is no <literal>PRAGMA</literal> statement in <productname>PostgreSQL</>.
       </para>
      </callout>
 
@@ -2846,11 +2605,10 @@ show errors
 
      <callout arearefs="co.plpgsql-porting-commit">
       <para>
-       You also cannot have transactions in <application>PL/pgSQL</application> procedures. The
+       You also cannot have transactions in <application>PL/pgSQL</application> functions. The
        entire function (and other functions called from therein) is
-       executed in a transaction and <productname>PostgreSQL</> rolls back the results if
-       something goes wrong. Therefore only one
-       <command>BEGIN</command> statement is allowed.
+       executed in one transaction and <productname>PostgreSQL</> rolls back the transaction if
+       something goes wrong.
       </para>
      </callout>
 
@@ -2864,36 +2622,30 @@ show errors
    </para>
 
    <para>
-    So let's see one of the ways we could port this procedure to <application>PL/pgSQL</>:
+    This is how we could port this procedure to <application>PL/pgSQL</>:
 
 <programlisting>
-CREATE OR REPLACE FUNCTION cs_create_job(INTEGER) RETURNS INTEGER AS '
+CREATE OR REPLACE FUNCTION cs_create_job(integer) RETURNS integer AS '
 DECLARE
     v_job_id ALIAS FOR $1;
-    a_running_job_count INTEGER;
-    a_num INTEGER;
-    -- PRAGMA AUTONOMOUS_TRANSACTION;
+    a_running_job_count integer;
+    a_num integer;
 BEGIN
     LOCK TABLE cs_jobs IN EXCLUSIVE MODE;
-    SELECT count(*) INTO a_running_job_count 
-    FROM cs_jobs 
-    WHERE end_stamp IS NULL;
+    SELECT count(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp IS NULL;
 
     IF a_running_job_count > 0
     THEN
-        -- COMMIT; -- free lock
         RAISE EXCEPTION ''Unable to create a new job: a job is currently running.'';
     END IF;
 
     DELETE FROM cs_active_job;
     INSERT INTO cs_active_job(job_id) VALUES (v_job_id);
 
-    SELECT count(*) into a_num 
-    FROM cs_jobs 
-    WHERE job_id=v_job_id;
+    SELECT count(*) INTO a_num FROM cs_jobs WHERE job_id=v_job_id;
     IF NOT FOUND THEN  -- If nothing was returned in the last query
         -- This job is not in the table so lets insert it.
-        INSERT INTO cs_jobs(job_id, start_stamp) VALUES (v_job_id, sysdate());
+        INSERT INTO cs_jobs(job_id, start_stamp) VALUES (v_job_id, current_timestamp);
         RETURN 1;
     ELSE
         RAISE NOTICE ''Job already running.'';<co id="co.plpgsql-porting-raise">
@@ -2901,7 +2653,7 @@ BEGIN
 
     RETURN 0;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
 
     <calloutlist>
@@ -2912,102 +2664,29 @@ END;
      </callout>
     </calloutlist>
    </para>
+   </example>
   </sect2>
 
-  <sect2 id="plpgsql-porting-packages">
-   <title>
-    Packages
-   </title>
-
-   <note>
-    <para>
-     I haven't done much with packages myself, so if there are
-     mistakes here, please let me know.
-    </para>
-   </note>
-
-   <para>
-    Packages are a way <productname>Oracle</productname> gives you to
-    encapsulate PL/SQL statements and functions into one entity, like
-    Java classes, where you define methods and objects. You can access
-    these objects/methods with a <quote><literal>.</literal></quote>
-    (dot). Here is an example of an <productname>Oracle</productname>
-    package from ACS 4 (the <ulink
-    url="http://www.arsdigita.com/doc/">ArsDigita Community
-    System</ulink>):
-
-<programlisting>
-CREATE OR REPLACE PACKAGE BODY acs
-AS
-  FUNCTION add_user (
-    user_id     IN users.user_id%TYPE DEFAULT NULL,
-    object_type     IN acs_objects.object_type%TYPE DEFAULT 'user',
-    creation_date   IN acs_objects.creation_date%TYPE DEFAULT sysdate,
-    creation_user   IN acs_objects.creation_user%TYPE DEFAULT NULL,
-    creation_ip     IN acs_objects.creation_ip%TYPE DEFAULT NULL,
-  ...
-  ) RETURN users.user_id%TYPE
-  IS
-    v_user_id       users.user_id%TYPE;
-    v_rel_id        membership_rels.rel_id%TYPE;
-  BEGIN
-    v_user_id := acs_user.new (user_id, object_type, creation_date,
-                creation_user, creation_ip, email, ...
-    RETURN v_user_id;
-  END;
-END acs;
-/
-show errors
-</programlisting>
-   </para>
+  <sect2 id="plpgsql-porting-other">
+   <title>Other Things to Watch For</title>
 
    <para>
-    We port this to <productname>PostgreSQL</> by creating the
-    different objects of the <productname>Oracle</productname> package
-    as functions with a standard naming convention. We have to pay
-    attention to some other details, like the lack of default
-    parameters in <productname>PostgreSQL</> functions. The above
-    package would become something like this:
-<programlisting>
-CREATE FUNCTION acs__add_user(INTEGER,INTEGER,VARCHAR,TIMESTAMP,INTEGER,INTEGER,...)
-RETURNS INTEGER AS '
-DECLARE
-    user_id ALIAS FOR $1;
-    object_type ALIAS FOR $2;
-    creation_date ALIAS FOR $3;
-    creation_user ALIAS FOR $4;
-    creation_ip ALIAS FOR $5;
-    ...
-    v_user_id users.user_id%TYPE;
-    v_rel_id membership_rels.rel_id%TYPE;
-BEGIN
-    v_user_id := acs_user__new(user_id,object_type,creation_date,creation_user,creation_ip, ...);
-    ...
-
-    RETURN v_user_id;
-END;
-' LANGUAGE 'plpgsql';
-</programlisting>
+    This section explains a few other things to watch for when porting
+    Oracle <application>PL/SQL</> functions to PostgreSQL.
    </para>
-  </sect2>
-
-  <sect2 id="plpgsql-porting-other">
-   <title>
-    Other Things to Watch For
-   </title>
 
    <sect3>
-    <title>EXECUTE</title>
+    <title><command>EXECUTE</command></title>
 
     <para>
-     The <productname>PostgreSQL</> version of <command>EXECUTE</command> works
-     nicely, but you have to remember to use
-     <function>quote_literal(TEXT)</function> and
-     <function>quote_string(TEXT)</function> as described in <xref
-     linkend="plpgsql-statements-executing-dyn-queries">.  Constructs of the type
-     <literal>EXECUTE ''SELECT * from $1'';</literal> will not work
-     unless you use these functions.
+     The <application>PL/pgSQL</> version of
+     <command>EXECUTE</command> works similar to the
+     <application>PL/SQL</> version, but you have to remember to use
+     <function>quote_literal(text)</function> and
+     <function>quote_string(text)</function> as described in <xref
+     linkend="plpgsql-statements-executing-dyn">.  Constructs of the
+     type <literal>EXECUTE ''SELECT * FROM $1'';</literal> will not
+     work unless you use these functions.
     </para>
    </sect3>
 
@@ -3015,125 +2694,112 @@ END;
     <title>Optimizing <application>PL/pgSQL</application> Functions</title>
 
     <para>
-     <productname>PostgreSQL</> gives you two function creation modifiers to optimize
-     execution: <literal>iscachable</literal> (function always returns
-     the same result when given the same arguments) and
-     <literal>isstrict</literal> (function returns NULL if any
-     argument is NULL).  Consult the <command>CREATE
-     FUNCTION</command> reference for details.
+     <productname>PostgreSQL</> gives you two function creation
+     modifiers to optimize execution: the volatility (whether the
+     function always returns the same result when given the same
+     arguments) and the <quote>strictness</quote> (whether the
+     function returns null if any argument is null).  Consult the description of
+     <command>CREATE FUNCTION</command> for details.
     </para>
 
     <para>
-     To make use of these optimization attributes, you have to use the
-     <literal>WITH</literal> modifier in your <command>CREATE
-     FUNCTION</command> statement.  Something like:
+     To make use of these optimization attributes, your
+     <command>CREATE FUNCTION</command> statement could look something
+     like this:
 
 <programlisting>
-CREATE FUNCTION foo(...) RETURNS INTEGER AS '
+CREATE FUNCTION foo(...) RETURNS integer AS '
 ...
-' LANGUAGE 'plpgsql'
-WITH (isstrict, iscachable);
+' LANGUAGE plpgsql STRICT IMMUTABLE;
 </programlisting>
     </para>
    </sect3>
   </sect2>
 
   <sect2 id="plpgsql-porting-appendix">
-   <title>
-    Appendix
-   </title>
-
-   <sect3>
-    <title>
-     Code for my <function>instr</function> functions
-    </title>
+   <title>Appendix</title>
 
-    <comment>
-     This function should probably be integrated into the core.
-    </comment>
+   <para>
+    This section contains the code for an Oracle-compatible
+    <function>instr</function> function that you can use to simplify
+    your porting efforts.
+   </para>
 
 <programlisting>
 --
 -- instr functions that mimic Oracle's counterpart
--- Syntax: instr(string1,string2,[n],[m]) where [] denotes optional params.
+-- Syntax: instr(string1, string2, [n], [m]) where [] denotes optional parameters.
 -- 
--- Searches string1 beginning at the nth character for the mth
--- occurrence of string2. If n is negative, search backwards. If m is
--- not passed, assume 1 (search starts at first character).
---
--- by Roberto Mello (rmello@fslc.usu.edu)
--- modified by Robert Gaszewski (graszew@poland.com)
--- Licensed under the GPL v2 or later.
+-- Searches string1 beginning at the nth character for the mth occurrence
+-- of string2.  If n is negative, search backwards.  If m is not passed,
+-- assume 1 (search starts at first character).
 --
 
-CREATE FUNCTION instr(VARCHAR,VARCHAR) RETURNS INTEGER AS '
+CREATE FUNCTION instr(varchar, varchar) RETURNS integer AS '
 DECLARE
     pos integer;
 BEGIN
-    pos:= instr($1,$2,1);
+    pos:= instr($1, $2, 1);
     RETURN pos;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
 
-CREATE FUNCTION instr(VARCHAR,VARCHAR,INTEGER) RETURNS INTEGER AS '
+CREATE FUNCTION instr(varchar, varchar, varchar) RETURNS integer AS '
 DECLARE
     string ALIAS FOR $1;
     string_to_search ALIAS FOR $2;
     beg_index ALIAS FOR $3;
     pos integer NOT NULL DEFAULT 0;
-    temp_str VARCHAR;
-    beg INTEGER;
-    length INTEGER;
-    ss_length INTEGER;
+    temp_str varchar;
+    beg integer;
+    length integer;
+    ss_length integer;
 BEGIN
     IF beg_index > 0 THEN
+        temp_str := substring(string FROM beg_index);
+        pos := position(string_to_search IN temp_str);
 
-       temp_str := substring(string FROM beg_index);
-       pos := position(string_to_search IN temp_str);
-
-       IF pos = 0 THEN
-                RETURN 0;
-            ELSE
-                RETURN pos + beg_index - 1;
-            END IF;
+        IF pos = 0 THEN
+            RETURN 0;
+        ELSE
+            RETURN pos + beg_index - 1;
+        END IF;
     ELSE
-       ss_length := char_length(string_to_search);
-       length := char_length(string);
-       beg := length + beg_index - ss_length + 2;
+        ss_length := char_length(string_to_search);
+        length := char_length(string);
+        beg := length + beg_index - ss_length + 2;
 
-       WHILE beg > 0 LOOP
-           temp_str := substring(string FROM beg FOR ss_length);
-                pos := position(string_to_search IN temp_str);
+        WHILE beg > 0 LOOP
+            temp_str := substring(string FROM beg FOR ss_length);
+            pos := position(string_to_search IN temp_str);
+
+            IF pos > 0 THEN
+                RETURN beg;
+            END IF;
 
-                IF pos > 0 THEN
-                          RETURN beg;
-                END IF;
+            beg := beg - 1;
+        END LOOP;
 
-                beg := beg - 1;
-       END LOOP;
-       RETURN 0;
+        RETURN 0;
     END IF;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 
---
--- Written by Robert Gaszewski (graszew@poland.com)
--- Licensed under the GPL v2 or later.
---
-CREATE FUNCTION instr(VARCHAR,VARCHAR,INTEGER,INTEGER) RETURNS INTEGER AS '
+
+CREATE FUNCTION instr(varchar, varchar, integer, integer) RETURNS integer AS '
 DECLARE
     string ALIAS FOR $1;
     string_to_search ALIAS FOR $2;
     beg_index ALIAS FOR $3;
     occur_index ALIAS FOR $4;
     pos integer NOT NULL DEFAULT 0;
-    occur_number INTEGER NOT NULL DEFAULT 0;
-    temp_str VARCHAR;
-    beg INTEGER;
-    i INTEGER;
-    length INTEGER;
-    ss_length INTEGER;
+    occur_number integer NOT NULL DEFAULT 0;
+    temp_str varchar;
+    beg integer;
+    i integer;
+    length integer;
+    ss_length integer;
 BEGIN
     IF beg_index > 0 THEN
         beg := beg_index;
@@ -3179,9 +2845,8 @@ BEGIN
         RETURN 0;
     END IF;
 END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE plpgsql;
 </programlisting>
-   </sect3>
   </sect2>
   
  </sect1>
index 7a36c07..6ec19c6 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.15 2002/10/21 20:34:09 momjian Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.16 2003/04/07 01:29:25 petere Exp $ -->
 
 <chapter id="plpython">
  <title>PL/Python - Python Procedural Language</title>
   <literal>createlang plpython <replaceable>dbname</></literal>.
  </para>
 
+  <tip>
+   <para>
+    If a language is installed into <literal>template1</>, all subsequently
+    created databases will have the language installed automatically.
+   </para>
+  </tip>
+
  <note>
   <para>
    Users of source packages must specially enable the build of
-   PL/Python during the installation process (refer to the
-   installation instructions for more information).  Users of binary
+   PL/Python during the installation process.  (Refer to the
+   installation instructions for more information.)  Users of binary
    packages might find PL/Python in a separate subpackage.
   </para>
  </note>
   <title>PL/Python Functions</title>
 
   <para>
-   The Python code you write gets transformed into a function.  E.g.,
+   The Python code you write gets transformed into a Python function.  E.g.,
 <programlisting>
 CREATE FUNCTION myfunc(text) RETURNS text
     AS 'return args[0]'
-    LANGUAGE 'plpython';
+    LANGUAGE plpython;
 </programlisting>
 
    gets transformed into
@@ -49,7 +56,7 @@ def __plpython_procedure_myfunc_23456():
 
   <para>
    If you do not provide a return value, Python returns the default
-   <symbol>None</symbol> which may or may not be what you want.  The
+   <symbol>None</symbol>. The
    language module translates Python's <symbol>None</symbol> into the
    SQL null value.
   </para>
@@ -60,8 +67,8 @@ def __plpython_procedure_myfunc_23456():
    <function>myfunc</function> example, <varname>args[0]</> contains
    whatever was passed in as the text argument.  For
    <literal>myfunc2(text, integer)</literal>, <varname>args[0]</>
-   would contain the <type>text</type> variable and
-   <varname>args[1]</varname> the <type>integer</type> variable.
+   would contain the <type>text</type> argument and
+   <varname>args[1]</varname> the <type>integer</type> argument.
   </para>
 
   <para>
@@ -95,14 +102,14 @@ def __plpython_procedure_myfunc_23456():
    <literal>TD["level"]</> contains one of <literal>ROW</>,
    <literal>STATEMENT</>, and <literal>UNKNOWN</>.
    <literal>TD["name"]</> contains the trigger name, and
-   <literal>TD["relid"]</> contains the relation ID of the table on
+   <literal>TD["relid"]</> contains the OID of the table on
    which the trigger occurred.  If the trigger was called with
    arguments they are available in <literal>TD["args"][0]</> to
    <literal>TD["args"][(n-1)]</>.
   </para>
 
   <para>
-   If the <literal>TD["when"]</literal> is <literal>BEFORE</>, you may
+   If <literal>TD["when"]</literal> is <literal>BEFORE</>, you may
    return <literal>None</literal> or <literal>"OK"</literal> from the
    Python function to indicate the row is unmodified,
    <literal>"SKIP"</> to abort the event, or <literal>"MODIFY"</> to
@@ -147,10 +154,10 @@ def __plpython_procedure_myfunc_23456():
    optional limit argument causes that query to be run and the result
    to be returned in a result object.  The result object emulates a
    list or dictionary object.  The result object can be accessed by
-   row number and field name.  It has these additional methods:
-   <function>nrows()</function> which returns the number of rows
+   row number and column name.  It has these additional methods:
+   <function>nrows</function> which returns the number of rows
    returned by the query, and <function>status</function> which is the
-   <function>SPI_exec</function> return variable.  The result object
+   <function>SPI_exec()</function> return value.  The result object
    can be modified.
   </para>
 
@@ -161,27 +168,27 @@ rv = plpy.execute("SELECT * FROM my_table", 5)
 </programlisting>
    returns up to 5 rows from <literal>my_table</literal>.  If
    <literal>my_table</literal> has a column
-   <literal>my_field</literal>, it would be accessed as
+   <literal>my_column</literal>, it would be accessed as
 <programlisting>
-foo = rv[i]["my_field"]
+foo = rv[i]["my_column"]
 </programlisting>
   </para>
 
   <para>
-   The second function <function>plpy.prepare</function> is called
-   with a query string and a list of argument types if you have bind
-   variables in the query.  For example:
+   The second function, <function>plpy.prepare</function>, prepares the
+   execution plan for a query.  It is called with a query string and a
+   list of parameter types, if you have parameter references in the
+   query.  For example:
 <programlisting>
 plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ])
 </programlisting>
    <literal>text</literal> is the type of the variable you will be
-   passing as <literal>$1</literal>.  After preparing a statement, you
+   passing for <literal>$1</literal>.  After preparing a statement, you
    use the function <function>plpy.execute</function> to run it:
 <programlisting>
 rv = plpy.execute(plan, [ "name" ], 5)
 </programlisting>
-   The limit argument is optional in the call to
-   <function>plpy.execute</function>.
+   The third argument is the limit and is optional.
   </para>
 
   <para>
@@ -190,7 +197,7 @@ rv = plpy.execute(plan, [ "name" ], 5)
    in the immediate termination of that function by the server; it is
    not possible to trap error conditions using Python <literal>try
    ... catch</literal> constructs.  For example, a syntax error in an
-   SQL statement passed to the <literal>plpy.execute()</literal> call
+   SQL statement passed to the <literal>plpy.execute</literal> call
    will terminate the function.  This behavior may be changed in a
    future release.
   </para>
@@ -199,22 +206,19 @@ rv = plpy.execute(plan, [ "name" ], 5)
    When you prepare a plan using the PL/Python module it is
    automatically saved.  Read the SPI documentation (<xref
    linkend="spi">) for a description of what this means.
-  </para>
-
-  <para>
    In order to make effective use of this across function calls
    one needs to use one of the persistent storage dictionaries
-   <literal>SD</literal> or <literal>GD</literal>see
-   <xref linkend="plpython-funcs">. For example:
+   <literal>SD</literal> or <literal>GD</literal> (see
+   <xref linkend="plpython-funcs">). For example:
 <programlisting>
-CREATE FUNCTION usesavedplan ( ) RETURNS TRIGGER AS '
-   if SD.has_key("plan"):
-      plan = SD["plan"]
-   else:
-      plan = plpy.prepare("SELECT 1")
-      SD["plan"] = plan
-   # rest of function
-' LANGUAGE 'plpython';
+CREATE FUNCTION usesavedplan() RETURNS trigger AS '
+    if SD.has_key("plan"):
+        plan = SD["plan"]
+    else:
+        plan = plpy.prepare("SELECT 1")
+        SD["plan"] = plan
+    # rest of function
+' LANGUAGE plpython;
 </programlisting>
   </para>
  </sect1>
index ed72415..f3b8595 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.22 2002/09/21 18:32:53 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.23 2003/04/07 01:29:25 petere Exp $
 -->
 
  <chapter id="pltcl">
@@ -20,10 +20,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.22 2002/09/21 18:32:53 peter
    trigger procedures.
   </para>
 
-  <para>
-   This package was originally written by Jan Wieck.
-  </para>
-
   <!-- **** PL/Tcl overview **** -->
 
   <sect1 id="pltcl-overview">
@@ -38,19 +34,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.22 2002/09/21 18:32:53 peter
     Tcl interpreter. In addition to the limited command set of safe Tcl, only
     a few commands are available to access the database via SPI and to raise
     messages via <function>elog()</>. There is no way to access internals of the
-    database backend or to gain OS-level access under the permissions of the
-    <productname>PostgreSQL</productname> user ID, as a C function can do.
+    database server or to gain OS-level access under the permissions of the
+    <productname>PostgreSQL</productname> server process, as a C function can do.
     Thus, any unprivileged database user may be
     permitted to use this language.
    </para>
    <para>
-    The other, implementation restriction is that Tcl procedures cannot
+    The other, implementation restriction is that Tcl functions cannot
     be used to create input/output functions for new data types.
    </para>
    <para>
     Sometimes it is desirable to write Tcl functions that are not restricted
-    to safe Tcl --- for example, one might want a Tcl function that sends
-    mail.  To handle these cases, there is a variant of <application>PL/Tcl</> called <literal>PL/TclU</>
+    to safe Tcl.  For example, one might want a Tcl function that sends
+    email.  To handle these cases, there is a variant of <application>PL/Tcl</> called <literal>PL/TclU</>
     (for untrusted Tcl).  This is the exact same language except that a full
     Tcl interpreter is used.  <emphasis>If <application>PL/TclU</> is used, it must be
     installed as an untrusted procedural language</emphasis> so that only
@@ -66,7 +62,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.22 2002/09/21 18:32:53 peter
     library directory if Tcl/Tk support is specified
     in the configuration step of the installation procedure.  To install
     <application>PL/Tcl</> and/or <application>PL/TclU</> in a particular database, use the
-    <filename>createlang</filename> script, for example
+    <command>createlang</command> program, for example
     <literal>createlang pltcl <replaceable>dbname</></literal> or
     <literal>createlang pltclu <replaceable>dbname</></literal>.
    </para>
@@ -74,58 +70,59 @@ $Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.22 2002/09/21 18:32:53 peter
 
   <!-- **** PL/Tcl description **** -->
 
-  <sect1 id="pltcl-description">
-   <title>Description</title>
-
-   <sect2>
+   <sect1 id="pltcl-functions">
     <title>PL/Tcl Functions and Arguments</title>
 
     <para>
-     To create a function in the <application>PL/Tcl</> language, use the standard syntax
+     To create a function in the <application>PL/Tcl</> language, use the standard syntax:
 
-     <programlisting>
+<programlisting>
 CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-types</replaceable>) RETURNS <replaceable>return-type</replaceable> AS '
     # PL/Tcl function body
-' LANGUAGE 'pltcl';
-     </programlisting>
+' LANGUAGE pltcl;
+</programlisting>
 
-     <application>PL/TclU</> is the same, except that the language should be specified as
+     <application>PL/TclU</> is the same, except that the language has to be specified as
      <literal>pltclu</>.
     </para>
 
     <para>
      The body of the function is simply a piece of Tcl script.
      When the function is called, the argument values are passed as
-     variables <literal>$1</literal> ... <literal>$n</literal> to the
+     variables <literal>$1</literal> ... <literal>$<replaceable>n</replaceable></literal> to the
      Tcl script.  The result is returned
      from the Tcl code in the usual way, with a <literal>return</literal>
-     statement.  For example, a function
+     statement.
+    </para>
+
+    <para>
+     For example, a function
      returning the greater of two integer values could be defined as:
 
-     <programlisting>
-CREATE FUNCTION tcl_max (integer, integer) RETURNS integer AS '
+<programlisting>
+CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS '
     if {$1 > $2} {return $1}
     return $2
-' LANGUAGE 'pltcl' WITH (isStrict);
-     </programlisting>
+' LANGUAGE pltcl STRICT;
+</programlisting>
 
-     Note the clause <literal>WITH (isStrict)</>, which saves us from
-     having to think about NULL input values: if a NULL is passed, the
-     function will not be called at all, but will just return a NULL
+     Note the clause <literal>STRICT</>, which saves us from
+     having to think about null input values: if a null value is passed, the
+     function will not be called at all, but will just return a null
      result automatically.
     </para>
 
     <para>
-     In a non-strict function,
-     if the actual value of an argument is NULL, the corresponding
-     <literal>$n</literal> variable will be set to an empty string.
-     To detect whether a particular argument is NULL, use the function
+     In a nonstrict function,
+     if the actual value of an argument is null, the corresponding
+     <literal>$<replaceable>n</replaceable></literal> variable will be set to an empty string.
+     To detect whether a particular argument is null, use the function
      <literal>argisnull</>.  For example, suppose that we wanted <function>tcl_max</function>
-     with one null and one non-null argument to return the non-null
-     argument, rather than NULL:
+     with one null and one nonnull argument to return the nonnull
+     argument, rather than null:
 
-     <programlisting>
-CREATE FUNCTION tcl_max (integer, integer) RETURNS integer AS '
+<programlisting>
+CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS '
     if {[argisnull 1]} {
         if {[argisnull 2]} { return_null }
         return $2
@@ -133,8 +130,8 @@ CREATE FUNCTION tcl_max (integer, integer) RETURNS integer AS '
     if {[argisnull 2]} { return $1 }
     if {$1 > $2} {return $1}
     return $2
-' LANGUAGE 'pltcl';
-     </programlisting>
+' LANGUAGE pltcl;
+</programlisting>
     </para>
 
     <para>
@@ -145,15 +142,19 @@ CREATE FUNCTION tcl_max (integer, integer) RETURNS integer AS '
     </para>
 
     <para>
-     Composite-type arguments are passed to the procedure as Tcl arrays.
-     The element names of the array are the attribute names of the composite
-     type. If an attribute in the passed 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>PostgreSQL</productname> documentation) in PL/Tcl:
-
-     <programlisting>
-CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
+     Composite-type arguments are passed to the function as Tcl
+     arrays.  The element names of the array are the attribute names
+     of the composite type. If an attribute in the passed row has the
+     null value, it will not appear in the array. Here is an example:
+
+<programlisting>
+CREATE TABLE employee (
+    name text,
+    salary integer,
+    age integer
+);
+
+CREATE FUNCTION overpaid(employee) RETURNS boolean AS '
     if {200000.0 < $1(salary)} {
         return "t"
     }
@@ -161,110 +162,109 @@ CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
         return "t"
     }
     return "f"
-' LANGUAGE 'pltcl';
-     </programlisting>
+' LANGUAGE pltcl;
+</programlisting>
     </para>
 
     <para>
-     There is not currently any support for returning a composite-type
+     There is currently no support for returning a composite-type
      result value.
     </para>
 
-   </sect2>
+   </sect1>
 
-   <sect2>
+   <sect1 id="pltcl-data">
     <title>Data Values in PL/Tcl</title>
 
     <para>
-     The argument values supplied to a PL/Tcl function's script are simply
+     The argument values supplied to a PL/Tcl function's code are simply
      the input arguments converted to text form (just as if they had been
-     displayed by a SELECT statement).  Conversely, the <literal>return</>
+     displayed by a <command>SELECT</> statement).  Conversely, the <literal>return</>
      command will accept any string that is acceptable input format for
      the function's declared return type.  So, the PL/Tcl programmer can
      manipulate data values as if they were just text.
     </para>
 
-   </sect2>
+   </sect1>
 
-   <sect2>
+   <sect1 id="pltcl-global">
     <title>Global Data in PL/Tcl</title>
 
     <para>
      Sometimes it
-     is useful to have some global status data that is held between two
-     calls to a procedure or is shared between different procedures.
+     is useful to have some global data that is held between two
+     calls to a function or is shared between different functions.
      This is easily done since
-     all PL/Tcl procedures executed in one backend share the same
+     all PL/Tcl functions executed in one session share the same
      safe Tcl interpreter.  So, any global Tcl variable is accessible to
-     all PL/Tcl procedure calls, and will persist for the duration of the
-     SQL client connection.  (Note that <application>PL/TclU</> functions likewise share
+     all PL/Tcl function calls and will persist for the duration of the
+     SQL session.  (Note that <application>PL/TclU</> functions likewise share
      global data, but they are in a different Tcl interpreter and cannot
      communicate with PL/Tcl functions.)
     </para>
     <para>
-     To help protect PL/Tcl procedures from unintentionally interfering
+     To help protect PL/Tcl functions from unintentionally interfering
      with each other, a global
-     array is made available to each procedure via the <function>upvar</>
-     command. The global name of this variable is the procedure's internal
-     name and the local name is <literal>GD</>.  It is recommended that
+     array is made available to each function via the <function>upvar</>
+     command. The global name of this variable is the function's internal
+     name, and the local name is <literal>GD</>.  It is recommended that
      <literal>GD</> be used
-     for private status data of a procedure.  Use regular Tcl global variables
+     for private data of a function.  Use regular Tcl global variables
      only for values that you specifically intend to be shared among multiple
-     procedures.
+     functions.
     </para>
 
     <para>
      An example of using <literal>GD</> appears in the
      <function>spi_execp</function> example below.
     </para>
-   </sect2>
+   </sect1>
 
-   <sect2>
+   <sect1 id="pltcl-dbaccess">
     <title>Database Access from PL/Tcl</title>
 
     <para>
      The following commands are available to access the database from
-     the body of a PL/Tcl procedure:
-    </para>
+     the body of a PL/Tcl function:
 
     <variablelist>
 
      <varlistentry>
-      <term><function>spi_exec</function> <literal>?-count <replaceable>n</replaceable>? ?-array <replaceable>name</replaceable>? <replaceable>query</replaceable> ?<replaceable>loop-body</replaceable>?</literal></term>
+      <term><function>spi_exec</function> <literal>?-count <replaceable>n</replaceable>? ?-array <replaceable>name</replaceable>? <replaceable>command</replaceable> ?<replaceable>loop-body</replaceable>?</literal></term>
       <listitem>
        <para>
-       Execute an SQL query given as a string.  An error in the query
-       causes an error to be raised.  Otherwise, the command's return value
+       Executes an SQL command given as a string.  An error in the command
+       causes an error to be raised.  Otherwise, the return value of <function>spi_exec</function>
        is the number of rows processed (selected, inserted, updated, or
-       deleted) by the query, or zero if the query is a utility
-       statement.  In addition, if the query is a SELECT statement, the
+       deleted) by the command, or zero if the command is a utility
+       statement.  In addition, if the command is a <command>SELECT</> statement, the
        values of the selected columns are placed in Tcl variables as
        described below.
        </para>
        <para>
        The optional <literal>-count</> value tells
        <function>spi_exec</function> the maximum number of rows
-       to process in the query.  The effect of this is comparable to
-       setting up the query as a cursor and then saying <literal>FETCH n</>.
+       to process in the command.  The effect of this is comparable to
+       setting up a query as a cursor and then saying <literal>FETCH <replaceable>n</></>.
        </para>
        <para>
-       If the query is a <literal>SELECT</> statement, the values of the statement's
+       If the command is a <command>SELECT</> statement, the values of the
        result columns are placed into Tcl variables named after the columns.
         If the <literal>-array</> option is given, the column values are
-       instead stored into the named associative array, with the SELECT
+       instead stored into the named associative array, with the
        column names used as array indexes.
        </para>
        <para>
-        If the query is a SELECT statement and no <replaceable>loop-body</>
+        If the command is a <command>SELECT</> statement and no <replaceable>loop-body</>
        script is given, then only the first row of results are stored into
-       Tcl variables; remaining rows, if any, are ignored.  No store occurs
+       Tcl variables; remaining rows, if any, are ignored.  No storing occurs
        if the 
-       SELECT returns no rows (this case can be detected by checking the
-       result of <function>spi_exec</function>).  For example,
+       query returns no rows.  (This case can be detected by checking the
+       result of <function>spi_exec</function>.)  For example,
 
-       <programlisting>
+<programlisting>
 spi_exec "SELECT count(*) AS cnt FROM pg_proc"
-       </programlisting>
+</programlisting>
 
        will set the Tcl variable <literal>$cnt</> to the number of rows in
        the <structname>pg_proc</> system catalog.
@@ -272,23 +272,23 @@ spi_exec "SELECT count(*) AS cnt FROM pg_proc"
        <para>
         If the optional <replaceable>loop-body</> argument is given, it is
        a piece of Tcl script that is executed once for each row in the
-       SELECT result (note: <replaceable>loop-body</> is ignored if the given
-       query is not a SELECT).  The values of the current row's fields
+       query result.  (<replaceable>loop-body</> is ignored if the given
+       command is not a <command>SELECT</>.)  The values of the current row's columns
        are stored into Tcl variables before each iteration.  For example,
 
-       <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.  This
+       will print a log message for every row of <literal>pg_class</>.  This
        feature works similarly to other Tcl looping constructs; in
        particular <literal>continue</> and <literal>break</> work in the
        usual way inside the loop body.
        </para>
        <para>
-        If a field of a SELECT result is NULL, the target
+        If a column of a query result is null, the target
        variable for it is <quote>unset</> rather than being set.
        </para>
       </listitem>
@@ -299,18 +299,18 @@ spi_exec -array C "SELECT * FROM pg_class" {
       <listitem>
        <para>
        Prepares and saves a query plan for later execution.  The saved plan
-       will be retained for the life of the current backend.
+       will be retained for the life of the current session.
        </para>
        <para>
-        The query may use <firstterm>arguments</>, which are placeholders for
+        The query may use parameters, that is, placeholders for
        values to be supplied whenever the plan is actually executed.
-       In the query string, refer to arguments
-       by the symbols <literal>$1</literal> ... <literal>$n</literal>.
-       If the query uses arguments, the names of the argument types
+       In the query string, refer to parameters
+       by the symbols <literal>$1</literal> ... <literal>$<replaceable>n</replaceable></literal>.
+       If the query uses parameters, the names of the parameter types
        must be given as a Tcl list.  (Write an empty list for
-       <replaceable>typelist</replaceable> if no arguments are used.)
-       Presently, the argument types must be identified by the internal
-       type names shown in pg_type; for example <literal>int4</> not
+       <replaceable>typelist</replaceable> if no parameters are used.)
+       Presently, the parameter types must be identified by the internal
+       type names shown in the system table <literal>pg_type</>; for example <literal>int4</> not
        <literal>integer</>.
        </para>
        <para>
@@ -325,24 +325,24 @@ spi_exec -array C "SELECT * FROM pg_class" {
       <term><function>spi_execp</> <literal>?-count <replaceable>n</replaceable>? ?-array <replaceable>name</replaceable>? ?-nulls <replaceable>string</replaceable>? <replaceable>queryid</replaceable> ?<replaceable>value-list</replaceable>? ?<replaceable>loop-body</replaceable>?</literal></term>
       <listitem>
        <para>
-       Execute a query previously prepared with <function>spi_prepare</>.
+       Executes a query previously prepared with <function>spi_prepare</>.
        <replaceable>queryid</replaceable> is the ID returned by
-       <function>spi_prepare</>.  If the query references arguments,
-       a <replaceable>value-list</replaceable> must be supplied: this
-       is a Tcl list of actual values for the arguments.  This must be
-       the same length as the argument type list previously given to
+       <function>spi_prepare</>.  If the query references parameters,
+       a <replaceable>value-list</replaceable> must be supplied.  This
+       is a Tcl list of actual values for the parameters.  The list must be
+       the same length as the parameter type list previously given to
        <function>spi_prepare</>.  Omit <replaceable>value-list</replaceable>
-       if the query has no arguments.
+       if the query has no parameters.
        </para>
        <para>
        The optional value for <literal>-nulls</> is a string of spaces and
        <literal>'n'</> characters telling <function>spi_execp</function>
-       which of the arguments are null values. If given, it must have exactly the
+       which of the parameters are null values. If given, it must have exactly the
        same length as the <replaceable>value-list</replaceable>.  If it
-       is not given, all the argument values are non-NULL.
+       is not given, all the parameter values are nonnull.
        </para>
        <para>
-        Except for the way in which the query and its arguments are specified,
+        Except for the way in which the query and its parameters are specified,
        <function>spi_execp</> works just like <function>spi_exec</>.
         The <literal>-count</>, <literal>-array</>, and
        <replaceable>loop-body</replaceable> options are the same,
@@ -351,7 +351,7 @@ spi_exec -array C "SELECT * FROM pg_class" {
        <para>
        Here's an example of a PL/Tcl function using a prepared plan:
 
-       <programlisting>
+<programlisting>
 CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS '
     if {![ info exists GD(plan) ]} {
         # prepare the saved plan on the first call
@@ -361,14 +361,14 @@ CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS '
     }
     spi_execp -count 1 $GD(plan) [ list $1 $2 ]
     return $cnt
-' LANGUAGE 'pltcl';
-       </programlisting>
+' LANGUAGE pltcl;
+</programlisting>
 
        Note that each backslash that Tcl should see must be doubled when
        we type in the function, since the main parser processes
-       backslashes too in CREATE FUNCTION.  We need backslashes inside
+       backslashes, too, in <command>CREATE FUNCTION</>.  We need backslashes inside
        the query string given to <function>spi_prepare</> to ensure that
-       the <literal>$n</> markers will be passed through to
+       the <literal>$<replaceable>n</replaceable></> markers will be passed through to
        <function>spi_prepare</> as-is, and not
        replaced by Tcl variable substitution.
        </para>
@@ -383,8 +383,8 @@ CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS '
       <listitem>
        <para>
        Returns the OID of the row inserted by the last
-       <function>spi_exec</>'d or <function>spi_execp</>'d query,
-       if that query was a single-row INSERT.  (If not, you get zero.)
+       <function>spi_exec</> or <function>spi_execp</>,
+       if the command was a single-row <command>INSERT</>.  (If not, you get zero.)
        </para>
       </listitem>
      </varlistentry>
@@ -395,18 +395,18 @@ CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS '
        <para>
        Duplicates all occurrences of single quote and backslash characters
        in the given string.  This may be used to safely quote strings
-       that are to be inserted into SQL queries given
+       that are to be inserted into SQL commands given
        to <function>spi_exec</function> or
        <function>spi_prepare</function>.
-       For example, think about a query string like
+       For example, think about an SQL command string like
 
 <programlisting>
 "SELECT '$val' AS ret"
 </programlisting>
 
-       where the Tcl variable val actually contains
+       where the Tcl variable <literal>val</> actually contains
        <literal>doesn't</literal>. This would result
-       in the final query string
+       in the final command string
 
 <programlisting>
 SELECT 'doesn't' AS ret
@@ -415,21 +415,21 @@ SELECT 'doesn't' AS ret
        which would cause a parse error during
        <function>spi_exec</function> or
        <function>spi_prepare</function>.
-       The submitted query should contain
+       The submitted command should contain
 
 <programlisting>
 SELECT 'doesn''t' AS ret
 </programlisting>
 
-       which can be formed in PL/Tcl as
+       which can be formed in PL/Tcl using
 
 <programlisting>
 "SELECT '[ quote $val ]' AS ret"
 </programlisting>
 
         One advantage of <function>spi_execp</function> is that you don't
-       have to quote argument values like this, since the arguments are never
-       parsed as part of an SQL query string.
+       have to quote parameter values like this, since the parameters are never
+       parsed as part of an SQL command string.
        </para>
       </listitem>
      </varlistentry>
@@ -441,26 +441,27 @@ SELECT 'doesn''t' AS ret
       <term><function>elog</> <replaceable>level</replaceable> <replaceable>msg</replaceable></term>
       <listitem>
        <para>
-       Emit a log or error message. Possible levels are
+       Emits a log or error message. Possible levels are
        <literal>DEBUG</>, <literal>LOG</>, <literal>INFO</>,
        <literal>NOTICE</>, <literal>WARNING</>, <literal>ERROR</>, and
        <literal>FATAL</>. Most simply emit the given message just like
-       the <literal>elog</> backend C function. <literal>ERROR</>
+       the <literal>elog</> C function. <literal>ERROR</>
        raises an error condition: further execution of the function is
        abandoned, and the current transaction is aborted.
        <literal>FATAL</> aborts the transaction and causes the current
-       backend to shut down (there is probably no good reason to use
+       session to shut down.  (There is probably no good reason to use
        this error level in PL/Tcl functions, but it's provided for
-       completeness).
+       completeness.)
        </para>
       </listitem>
      </varlistentry>
 
     </variablelist>
+    </para>
 
-   </sect2>
+   </sect1>
 
-   <sect2>
+   <sect1 id="pltcl-trigger">
     <title>Trigger Procedures in PL/Tcl</title>
 
     <indexterm>
@@ -469,8 +470,8 @@ SELECT 'doesn''t' AS ret
     </indexterm>
 
     <para>
-     Trigger procedures can be written in PL/Tcl.  As is customary in
-     <productname>PostgreSQL</productname>, a procedure that's to be called
+     Trigger procedures can be written in PL/Tcl.
+     <productname>PostgreSQL</productname> requires that a procedure that is to be called
      as a trigger must be declared as a function with no arguments
      and a return type of <literal>trigger</>.
     </para>
@@ -481,16 +482,16 @@ SELECT 'doesn''t' AS ret
      <variablelist>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_name</replaceable></term>
+       <term><varname>$TG_name</varname></term>
        <listitem>
        <para>
-        The name of the trigger from the CREATE TRIGGER statement.
+        The name of the trigger from the <command>CREATE TRIGGER</command> statement.
        </para>
        </listitem>
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_relid</replaceable></term>
+       <term><varname>$TG_relid</varname></term>
        <listitem>
        <para>
         The object ID of the table that caused the trigger procedure
@@ -500,20 +501,20 @@ SELECT 'doesn''t' AS ret
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_relatts</replaceable></term>
+       <term><varname>$TG_relatts</varname></term>
        <listitem>
        <para>
-        A Tcl list of the table field names, prefixed with an empty list
-         element. So looking up an element name in the list with <application>Tcl</>'s
+        A Tcl list of the table column names, prefixed with an empty list
+         element. So looking up a column name in the list with <application>Tcl</>'s
          <function>lsearch</> command returns the element's number starting
-        with 1 for the first column, the same way the fields are customarily
+        with 1 for the first column, the same way the columns are customarily
         numbered in <productname>PostgreSQL</productname>.
        </para>
        </listitem>
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_when</replaceable></term>
+       <term><varname>$TG_when</varname></term>
        <listitem>
        <para>
         The string <literal>BEFORE</> or <literal>AFTER</> depending on the
@@ -523,7 +524,7 @@ SELECT 'doesn''t' AS ret
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_level</replaceable></term>
+       <term><varname>$TG_level</varname></term>
        <listitem>
        <para>
         The string <literal>ROW</> or <literal>STATEMENT</> depending on the
@@ -533,44 +534,46 @@ SELECT 'doesn''t' AS ret
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$TG_op</replaceable></term>
+       <term><varname>$TG_op</varname></term>
        <listitem>
        <para>
-        The string <literal>INSERT</>, <literal>UPDATE</> or
+        The string <literal>INSERT</>, <literal>UPDATE</>, or
         <literal>DELETE</> depending on the type of trigger call.
        </para>
        </listitem>
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$NEW</replaceable></term>
+       <term><varname>$NEW</varname></term>
        <listitem>
        <para>
-        An associative array containing the values of the new table row for
-        INSERT/UPDATE actions, or empty for DELETE.  The array is indexed
-        by field name.  Fields that are NULL will not appear in the array!
+        An associative array containing the values of the new table
+        row for <command>INSERT</> or <command>UPDATE</> actions, or
+        empty for <command>DELETE</>.  The array is indexed by column
+        name.  Columns that are null will not appear in the array.
        </para>
        </listitem>
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$OLD</replaceable></term>
+       <term><varname>$OLD</varname></term>
        <listitem>
        <para>
-        An associative array containing the values of the old table row for
-        UPDATE/DELETE actions, or empty for INSERT.  The array is indexed
-        by field name.  Fields that are NULL will not appear in the array!
+        An associative array containing the values of the old table
+        row for <command>UPDATE</> or <command>DELETE</> actions, or
+        empty for <command>INSERT</>.  The array is indexed by column
+        name.  Columns that are null will not appear in the array.
        </para>
        </listitem>
       </varlistentry>
 
       <varlistentry>
-       <term><replaceable class="Parameter">$args</replaceable></term>
+       <term><varname>$args</varname></term>
        <listitem>
        <para>
         A Tcl list of the arguments to the procedure as given in the
-        CREATE TRIGGER statement. These arguments are also accessible as
-        <literal>$1</literal> ... <literal>$n</literal> in the procedure body.
+        <command>CREATE TRIGGER</command> statement. These arguments are also accessible as
+        <literal>$1</literal> ... <literal>$<replaceable>n</replaceable></literal> in the procedure body.
        </para>
        </listitem>
       </varlistentry>
@@ -582,22 +585,22 @@ SELECT 'doesn''t' AS ret
      The return value from a trigger procedure can be one of the strings
      <literal>OK</> or <literal>SKIP</>, or a list as returned by the
      <literal>array get</> Tcl command. If the return value is <literal>OK</>,
-     the operation (INSERT/UPDATE/DELETE) that fired the trigger will proceed
+     the operation (<command>INSERT</>/<command>UPDATE</>/<command>DELETE</>) that fired the trigger will proceed
      normally. <literal>SKIP</> tells the trigger manager to silently suppress
      the operation for this row. If a list is returned, it tells PL/Tcl to
      return a modified row to the trigger manager that will be inserted
-     instead of the one given in $NEW (this works for INSERT/UPDATE
-     only). Needless to say that all this is only meaningful when the trigger
-     is BEFORE and FOR EACH ROW; otherwise the return value is ignored.
+     instead of the one given in <varname>$NEW</>.  (This works for <command>INSERT</> and <command>UPDATE</>
+     only.) Needless to say that all this is only meaningful when the trigger
+     is <literal>BEFORE</> and <command>FOR EACH ROW</>; otherwise the return value is ignored.
     </para>
     <para>
      Here's a little example trigger procedure that forces an integer value
      in a table to keep track of the number of updates that are performed on the
      row. For new rows inserted, the value is initialized to 0 and then
-     incremented on every update operation:
+     incremented on every update operation.
 
-     <programlisting>
-CREATE FUNCTION trigfunc_modcount() RETURNS TRIGGER AS '
+<programlisting>
+CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS '
     switch $TG_op {
         INSERT {
             set NEW($1) 0
@@ -611,24 +614,24 @@ CREATE FUNCTION trigfunc_modcount() RETURNS TRIGGER AS '
         }
     }
     return [array get NEW]
-' LANGUAGE 'pltcl';
+' LANGUAGE pltcl;
 
 CREATE TABLE mytab (num integer, description text, modcnt integer);
 
 CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
     FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
-     </programlisting>
+</programlisting>
 
      Notice that the trigger procedure itself does not know the column
      name; that's supplied from the trigger arguments.  This lets the
-     trigger procedure be re-used with different tables.
+     trigger procedure be reused with different tables.
     </para>
-   </sect2>
+   </sect1>
 
-   <sect2>
-       <title> Modules and the <function>unknown</> command</title>
+   <sect1 id="pltcl-unknown">
+       <title>Modules and the <function>unknown</> command</title>
        <para>
-       PL/Tcl has support for auto-loading Tcl code when used.
+       PL/Tcl has support for autoloading Tcl code when used.
        It recognizes a special table, <literal>pltcl_modules</>, which
        is presumed to contain modules of Tcl code.  If this table
        exists, the module <literal>unknown</> is fetched from the table
@@ -638,7 +641,7 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
        <para>
         While the <literal>unknown</> module could actually contain any
        initialization script you need, it normally defines a Tcl
-       <quote>unknown</> procedure that is invoked whenever Tcl does
+       <function>unknown</> procedure that is invoked whenever Tcl does
        not recognize an invoked procedure name.  <application>PL/Tcl</>'s standard version
        of this procedure tries to find a module in <literal>pltcl_modules</>
        that will define the required procedure.  If one is found, it is
@@ -653,7 +656,7 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
        support scripts to maintain these tables:
        <command>pltcl_loadmod</>, <command>pltcl_listmod</>,
        <command>pltcl_delmod</>, as well as source for the standard
-       unknown module <filename>share/unknown.pltcl</>.  This module
+       <literal>unknown</> module in <filename>share/unknown.pltcl</>.  This module
        must be loaded
        into each database initially to support the autoloading mechanism.
        </para>
@@ -662,9 +665,9 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
        must be readable by all, but it is wise to make them owned and
        writable only by the database administrator.
        </para>
-   </sect2>
+   </sect1>
 
-   <sect2>
+   <sect1 id="pltcl-procnames">
     <title>Tcl Procedure Names</title>
 
     <para>
@@ -674,16 +677,14 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
      differ. Tcl, however, requires all procedure names to be distinct.
      PL/Tcl deals with this by making the internal Tcl procedure names contain
      the object 
-     ID of the procedure's <structname>pg_proc</> row as part of their name. Thus,
+     ID of the function from the system table <structname>pg_proc</> as part of their name. Thus,
      <productname>PostgreSQL</productname> functions with the same name
-     and different argument types will be different Tcl procedures too.  This
+     and different argument types will be different Tcl procedures, too.  This
      is not normally a concern for a PL/Tcl programmer, but it might be visible
      when debugging.
     </para>
 
-   </sect2>
-
-  </sect1>
+   </sect1>
  </chapter>
 
 <!-- Keep this comment at the end of the file
index 3b854d4..391e833 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/Attic/pygresql.sgml,v 1.9 2002/12/12 22:49:27 momjian Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/Attic/pygresql.sgml,v 1.10 2003/04/07 01:29:25 petere Exp $ -->
 
 <chapter id="pygresql">
  <title><application>PyGreSQL</application> - <application>Python</application> Interface</title>
@@ -334,13 +334,10 @@ make && make install
   <acronym>API</acronym> at <ulink
   url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
   >http://www.python.org/topics/database/DatabaseAPI-2.0.html</ulink>.
- </para>
-
- <para>
   A tutorial-like introduction to the <acronym>DB-API</acronym> can be
   found at <ulink
   url="http://www2.linuxjournal.com/lj-issues/issue49/2605.html"
-  >http://www2.linuxjournal.com/lj-issues/issue49/2605.html</ulink>
+  >http://www2.linuxjournal.com/lj-issues/issue49/2605.html</ulink>.
  </para>
 
  <sect1 id="pygresql-pg">
@@ -365,16 +362,15 @@ make && make install
 
     <listitem>
      <para>
-      <classname>pgqueryobject</classname> that handles query results.
+      <classname>pgqueryobject</classname>, which handles query results.
      </para>
     </listitem>
    </itemizedlist>
   </para>
 
   <para>
-   If you want to see a simple example of the use of some of these
-   functions, see <ulink url="http://www.druid.net/rides"
-   >http://www.druid.net/rides</ulink> where you can find a link at the
+   If you want to see a simple example of the use this module,
+   see <ulink url="http://www.druid.net/rides"></ulink> where you can find a link at the
    bottom to the actual <application>Python</application> code for the
    page.
   </para>
@@ -395,9 +391,9 @@ make && make install
       <term><varname>INV_WRITE</varname></term>
       <listitem>
        <para>
-        large objects access modes, used by
+        Large objects access modes, used by
         <function>(pgobject.)locreate</function> and
-        <function>(pglarge.)open</function>.
+        <function>(pglarge.)open</function>
        </para>
       </listitem>
      </varlistentry>
@@ -408,7 +404,7 @@ make && make install
       <term><varname>SEEK_END</varname></term>
       <listitem>
        <para>
-        positional flags, used by <function>(pglarge.)seek</function>.
+        Positional flags, used by <function>(pglarge.)seek</function>
        </para>
       </listitem>
      </varlistentry>
@@ -418,7 +414,7 @@ make && make install
       <term><varname>__version__</varname></term>
       <listitem>
        <para>
-        constants that give the current version
+        Constants that give the current version
        </para>
       </listitem>
      </varlistentry>
@@ -443,13 +439,13 @@ make && make install
    to handle general connection parameters without heavy code in your
    programs. You can prompt the user for a value, put it in the
    default variable, and forget it, without having to modify your
-   environment. The support for default variables can be disabled by
+   environment. The support for default variables can be disabled at build time by
    setting the <option>-DNO_DEF_VAR</option> option in the Python
    <filename>Setup</> file. Methods relative to this are specified by the tag [DV].
   </para>
 
   <para>
-   All variables are set to <symbol>None</symbol> at module
+   All default values are set to <symbol>None</symbol> at module
    initialization, specifying that standard environment variables
    should be used.
   </para>
@@ -478,7 +474,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
        <term><parameter>dbname</parameter></term>
 
        <listitem>
-        <para>Name of connected database (string/<symbol>None</>).</para>
+        <para>Name of connected database (string/<symbol>None</>)</para>
        </listitem>
       </varlistentry>
 
@@ -486,7 +482,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
        <term><parameter>host</parameter></term>
 
        <listitem>
-        <para>Name of the server host (string/<symbol>None</>).</para>
+        <para>Name of the server host (string/<symbol>None</>)</para>
        </listitem>
       </varlistentry>
 
@@ -494,7 +490,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
        <term><parameter>port</parameter></term>
 
        <listitem>
-        <para>Port used by the database server (integer/-1).</para>
+        <para>Port used by the database server (integer/-1)</para>
        </listitem>
       </varlistentry>
 
@@ -503,7 +499,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
 
        <listitem>
         <para>
-         Options for the server (string/<symbol>None</>).
+         Options for the server (string/<symbol>None</>)
         </para>
        </listitem>
       </varlistentry>
@@ -513,8 +509,8 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
 
        <listitem>
         <para>
-         File or tty for optional debug output from backend
-         (string/<symbol>None</>).
+         File or TTY for optional debug output from server
+         (string/<symbol>None</>)
         </para>
        </listitem>
       </varlistentry>
@@ -524,7 +520,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
 
        <listitem>
         <para>
-         <productname>PostgreSQL</productname> user (string/<symbol>None</>).
+         <productname>PostgreSQL</productname> user (string/<symbol>None</>)
         </para>
        </listitem>
       </varlistentry>
@@ -533,7 +529,7 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
        <term><parameter>passwd</parameter></term>
 
        <listitem>
-        <para>Password for user (string/<symbol>None</>).</para>
+        <para>Password for user (string/<symbol>None</>)</para>
        </listitem>
       </varlistentry>
      </variablelist>
@@ -601,12 +597,11 @@ connect(<optional><parameter>dbname</parameter></optional>, <optional><parameter
 
     <para>
      This method opens a connection to a specified database on a given
-     <productname>PostgreSQL</productname> server. You can use
-     key words here, as described in the
-     <application>Python</application> tutorial.  The names of the
+     <productname>PostgreSQL</productname> server. The arguments can be
+     given using key words here.  The names of the
      key words are the name of the parameters given in the syntax
      line. For a precise description of the parameters, please refer
-     to the <productname>PostgreSQL</productname> user manual.
+     to <xref linkend="libpq">.
     </para>
    </refsect1>
       
index 6e9e81c..26e0552 100644 (file)
@@ -1,13 +1,10 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.20 2003/01/31 00:10:51 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.21 2003/04/07 01:29:26 petere Exp $
 -->
 
  <chapter id="xplang">
   <title id="xplang-title">Procedural Languages</title>
 
-  <sect1 id="xplang-intro">
-   <title>Introduction</title>
-
   <para>
    <productname>PostgreSQL</productname> allows users to add new
    programming languages to be available for writing functions and
@@ -21,7 +18,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.20 2003/01/31 00:10:51 tgl
    could serve as <quote>glue</quote> between
    <productname>PostgreSQL</productname> and an existing implementation
    of a programming language.  The handler itself is a special
-   programming language function compiled into a shared object and
+   C language function compiled into a shared object and
    loaded on demand.
   </para>
 
@@ -31,7 +28,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.20 2003/01/31 00:10:51 tgl
    available in the standard <productname>PostgreSQL</productname>
    distribution, which can serve as examples.
   </para>
-  </sect1>
 
   <sect1 id="xplang-install">
    <title>Installing Procedural Languages</title>
@@ -39,22 +35,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.20 2003/01/31 00:10:51 tgl
    <para>
     A procedural language must be <quote>installed</quote> into each
     database where it is to be used.  But procedural languages installed in
-    the template1 database are automatically available in all
+    the database <literal>template1</> are automatically available in all
     subsequently created databases. So the database administrator can
-    decide which languages are available in which databases, and can make
+    decide which languages are available in which databases and can make
     some languages available by default if he chooses.
    </para>
 
    <para>
     For the languages supplied with the standard distribution, the
-    shell script <filename>createlang</filename> may be used instead
-    of carrying out the details by hand.  For example, to install <application>PL/pgSQL</application>
-    into the template1 database, use
+    program <command>createlang</command> may be used to install the
+    language instead of carrying out the details by hand.  For
+    example, to install the language
+    <application>PL/pgSQL</application> into the database
+    <literal>template1</>, use
 <programlisting>
 createlang plpgsql template1
 </programlisting>
     The manual procedure described below is only recommended for
-    installing custom languages that <filename>createlang</filename>
+    installing custom languages that <command>createlang</command>
     does not know about.
    </para>
 
@@ -64,8 +62,11 @@ createlang plpgsql template1
     </title>
 
     <para>
-     A procedural language is installed in the database in three
-     steps, which must be carried out by a database superuser.
+     A procedural language is installed in a database in three steps,
+     which must be carried out by a database superuser.  The
+     <command>createlang</command> programm automates <xref
+     linkend="xplang-install-cr1"> and <xref
+     linkend="xplang-install-cr2">.
     </para>
 
     <step performance="required">
@@ -81,12 +82,13 @@ createlang plpgsql template1
      <para>
       The handler must be declared with the command
 <synopsis>
-CREATE FUNCTION <replaceable>handler_function_name</replaceable> ()
-    RETURNS LANGUAGE_HANDLER AS
-    '<replaceable>path-to-shared-object</replaceable>' LANGUAGE C;
+CREATE FUNCTION <replaceable>handler_function_name</replaceable>()
+    RETURNS language_handler
+    AS '<replaceable>path-to-shared-object</replaceable>'
+    LANGUAGE C;
 </synopsis>
-      The special return type of <type>LANGUAGE_HANDLER</type> tells
-      the database that this function does not return one of
+      The special return type of <type>language_handler</type> tells
+      the database system that this function does not return one of
       the defined <acronym>SQL</acronym> data types and is not directly usable
       in <acronym>SQL</acronym> statements.
      </para>
@@ -99,7 +101,7 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable> ()
 CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable>
     HANDLER <replaceable>handler_function_name</replaceable>;
 </synopsis>
-      The optional key word <literal>TRUSTED</literal> tells whether
+      The optional key word <literal>TRUSTED</literal> specifies that
       ordinary database users that have no superuser privileges should
       be allowed to use this language to create functions and trigger
       procedures. Since PL functions are executed inside the database
@@ -119,20 +121,12 @@ CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <re
    </procedure>
 
    <para>
-    In a default <productname>PostgreSQL</productname> installation,
-    the handler for the <application>PL/pgSQL</application> language
-    is built and installed into the <quote>library</quote>
-    directory. If <application>Tcl/Tk</> support is configured in, the handlers for
-    <application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same
-    location.  Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built
-    and installed if Perl support is configured, and <application>PL/Python</> is
-    installed if Python support is configured.  The
-    <filename>createlang</filename> script automates <xref
-    linkend="xplang-install-cr1"> and <xref
-    linkend="xplang-install-cr2"> described above.
+    <xref linkend="xplang-install-example"> shows how the manual
+    installation procedure would work with the language
+    <application>PL/pgSQL</application>.
    </para>
 
-   <example>
+   <example id="xplang-install-example">
     <title>Manual Installation of <application>PL/pgSQL</application></title>
 
      <para>
@@ -140,7 +134,7 @@ CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <re
       shared object for the <application>PL/pgSQL</application> language's call handler function.
 
 <programlisting>
-CREATE FUNCTION plpgsql_call_handler () RETURNS LANGUAGE_HANDLER AS
+CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS
     '$libdir/plpgsql' LANGUAGE C;
 </programlisting>
      </para>
@@ -157,6 +151,17 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
      </para>
   </example>
 
+   <para>
+    In a default <productname>PostgreSQL</productname> installation,
+    the handler for the <application>PL/pgSQL</application> language
+    is built and installed into the <quote>library</quote>
+    directory. If <application>Tcl/Tk</> support is configured in, the handlers for
+    <application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same
+    location.  Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built
+    and installed if Perl support is configured, and <application>PL/Python</> is
+    installed if Python support is configured.
+   </para>
+
   </sect1>
 
 </chapter>