diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index 3ee6deea0a5d4ba95e95a23e783c6ea7004da6ea..54f067542de446718e9e16f0c6baf07abf5e0e7d 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -11,7 +11,7 @@ import org.postgresql.util.*;
 import org.postgresql.core.*;
 
 /*
- * $Id: Connection.java,v 1.44 2002/03/21 02:39:06 davec Exp $
+ * $Id: Connection.java,v 1.45 2002/03/26 05:52:48 barry Exp $
  *
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -59,10 +59,6 @@ public abstract class Connection
 	private static final int AUTH_REQ_CRYPT = 4;
 	private static final int AUTH_REQ_MD5 = 5;
 
-  	public final static int PGASYNC_IDLE = 0;				/* nothing's happening, dude */
-	public final static int PGASYNC_BUSY = 1;				/* query in progress */
-	public final static int PGASYNC_READY = 2;			/* result ready for PQgetResult */
-
 
 	// These are used to cache oids, PGTypes and SQLTypes
 	private static Hashtable sqlTypeCache = new Hashtable();  // oid -> SQLType
@@ -81,7 +77,6 @@ public abstract class Connection
 	public int pid;
 	public int ckey;
 
-  public int asyncStatus = PGASYNC_READY;
 	/*
 	 * This is called by Class.forName() from within org.postgresql.Driver
 	 */
@@ -427,7 +422,7 @@ public abstract class Connection
 	 */
 	public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
 	{
-		return new QueryExecutor2(sql, stat, pg_stream, this).execute();
+		return new QueryExecutor(sql, stat, pg_stream, this).execute();
 	}
 
 	/*
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index a6d0fb03a257332a819443545e0f8ae9cfcabd6e..bc1925efe56bd9b86c5e6b3a12abfe26f7a2bf23 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java.in
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -419,7 +419,7 @@ public class Driver implements java.sql.Driver
 	 */
 	public String database()
 	{
-		return props.getProperty("PGDBNAME");
+		return props.getProperty("PGDBNAME", "");
 	}
 
 	/*
diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
index 237aa49684f653ee0991dedd119f2e9780613069..bfa6af3572380fef41cae2f54c3edc634d73b7ea 100644
--- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
+++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
@@ -13,212 +13,199 @@ import org.postgresql.util.PSQLException;
  * <p>The lifetime of a QueryExecutor object is from sending the query
  * until the response has been received from the backend.
  *
- * $Id: QueryExecutor.java,v 1.11 2002/03/21 03:20:30 davec Exp $
+ * $Id: QueryExecutor.java,v 1.12 2002/03/26 05:52:49 barry Exp $
  */
 
 public class QueryExecutor
 {
 
-	private final String sql;
-	private final java.sql.Statement statement;
-	private final PG_Stream pg_stream;
-	private final org.postgresql.Connection connection;
-
-	public QueryExecutor(String sql,
-						 java.sql.Statement statement,
-						 PG_Stream pg_stream,
-						 org.postgresql.Connection connection)
-	throws SQLException
-	{
-		this.sql = sql;
-		this.statement = statement;
-		this.pg_stream = pg_stream;
-		this.connection = connection;
-
-		if (statement != null)
-			maxRows = statement.getMaxRows();
-		else
-			maxRows = 0;
-	}
-
-	private Field[] fields = null;
-	private Vector tuples = new Vector();
-	private boolean binaryCursor = false;
-	private String status = null;
-	private int update_count = 1;
-	private long insert_oid = 0;
-	private int maxRows;
-
-	/*
-	 * Execute a query on the backend.
-	 */
-	public java.sql.ResultSet execute() throws SQLException
-	{
-
-		int fqp = 0;
-		boolean hfr = false;
-
-		StringBuffer errorMessage = null;
-
-		synchronized (pg_stream)
-		{
-
-			sendQuery(sql);
-
-			while (!hfr || fqp > 0)
-			{
-				int c = pg_stream.ReceiveChar();
-
-				switch (c)
-				{
-					case 'A':	// Asynchronous Notify
-						int pid = pg_stream.ReceiveInteger(4);
-						String msg = pg_stream.ReceiveString(connection.getEncoding());
-						break;
-					case 'B':	// Binary Data Transfer
-						receiveTuple(true);
-						break;
-					case 'C':	// Command Status
-						receiveCommandStatus();
-
-						if (fields != null)
-							hfr = true;
-						else
-						{
-							sendQuery(" ");
-							fqp++;
-						}
-						break;
-					case 'D':	// Text Data Transfer
-						receiveTuple(false);
-						break;
-					case 'E':	// Error Message
-
-						// it's possible to get more than one error message for a query
-						// see libpq comments wrt backend closing a connection 
-						// so, append messages to a string buffer and keep processing
-						// check at the bottom to see if we need to throw an exception
-						
-						if ( errorMessage == null )
-							errorMessage = new StringBuffer();
-
-						errorMessage.append(pg_stream.ReceiveString(connection.getEncoding()));
-						// keep processing
-						break;
-
-					case 'I':	// Empty Query
-						int t = pg_stream.ReceiveChar();
-						if (t != 0)
-							throw new PSQLException("postgresql.con.garbled");
-
-						if (fqp > 0)
-							fqp--;
-						if (fqp == 0)
-							hfr = true;
-						break;
-					case 'N':	// Error Notification
-						connection.addWarning(pg_stream.ReceiveString(connection.getEncoding()));
-						break;
-					case 'P':	// Portal Name
-						String pname = pg_stream.ReceiveString(connection.getEncoding());
-						break;
-					case 'T':	// MetaData Field Description
-						receiveFields();
-						break;
-					case 'Z':		 // backend ready for query, ignore for now :-)
-						break;
-					default:
-						throw new PSQLException("postgresql.con.type",
-												new Character((char) c));
-				}
-
-				// did we get an error during this query?
-				if ( errorMessage != null )
-					throw new SQLException( errorMessage.toString() );
-			}
-			return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
-		}
-	}
-
-	/*
-	 * Send a query to the backend.
-	 */
-	private void sendQuery(String query) throws SQLException
-	{
-		try
-		{
-			pg_stream.SendChar('Q');
-			pg_stream.Send(connection.getEncoding().encode(query));
-			pg_stream.SendChar(0);
-			pg_stream.flush();
-
-		}
-		catch (IOException e)
-		{
-			throw new PSQLException("postgresql.con.ioerror", e);
-		}
-	}
-
-	/*
-	 * Receive a tuple from the backend.
-	 *
-	 * @param isBinary set if the tuple should be treated as binary data
-	 */
-	private void receiveTuple(boolean isBinary) throws SQLException
-	{
-		if (fields == null)
-			throw new PSQLException("postgresql.con.tuple");
-		Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
-		if (isBinary)
-			binaryCursor = true;
-		if (maxRows == 0 || tuples.size() < maxRows)
-			tuples.addElement(tuple);
-	}
-
-	/*
-	 * Receive command status from the backend.
-	 */
-	private void receiveCommandStatus() throws SQLException
-	{
-		status = pg_stream.ReceiveString(connection.getEncoding());
-
-		try
-		{
-			// Now handle the update count correctly.
-			if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
-			{
-				update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
-			}
-			if (status.startsWith("INSERT"))
-			{
-				insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),
-											  status.lastIndexOf(' ')));
-			}
-		}
-		catch (NumberFormatException nfe)
-		{
-			throw new PSQLException("postgresql.con.fathom", status);
-		}
-	}
-
-	/*
-	 * Receive the field descriptions from the back end.
-	 */
-	private void receiveFields() throws SQLException
-	{
-		if (fields != null)
-			throw new PSQLException("postgresql.con.multres");
-
-		int size = pg_stream.ReceiveIntegerR(2);
-		fields = new Field[size];
-
-		for (int i = 0; i < fields.length; i++)
-		{
-			String typeName = pg_stream.ReceiveString(connection.getEncoding());
-			int typeOid = pg_stream.ReceiveIntegerR(4);
-			int typeLength = pg_stream.ReceiveIntegerR(2);
-			int typeModifier = pg_stream.ReceiveIntegerR(4);
-			fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
-		}
-	}
+        private final String sql;
+        private final java.sql.Statement statement;
+        private final PG_Stream pg_stream;
+        private final org.postgresql.Connection connection;
+
+        public QueryExecutor(String sql,
+                                                 java.sql.Statement statement,
+                                                 PG_Stream pg_stream,
+                                                 org.postgresql.Connection connection)
+        throws SQLException
+        {
+                this.sql = sql;
+                this.statement = statement;
+                this.pg_stream = pg_stream;
+                this.connection = connection;
+
+                if (statement != null)
+                        maxRows = statement.getMaxRows();
+                else
+                        maxRows = 0;
+        }
+
+        private Field[] fields = null;
+        private Vector tuples = new Vector();
+        private boolean binaryCursor = false;
+        private String status = null;
+        private int update_count = 1;
+        private long insert_oid = 0;
+        private int maxRows;
+
+        /*
+         * Execute a query on the backend.
+         */
+        public java.sql.ResultSet execute() throws SQLException
+        {
+
+                StringBuffer errorMessage = null;
+
+                synchronized (pg_stream)
+                {
+
+                        sendQuery(sql);
+
+                        int c;
+                        boolean l_endQuery = false;
+                        while (!l_endQuery) 
+                        {
+                                c = pg_stream.ReceiveChar();
+
+                                switch (c)
+                                {
+                                        case 'A':	// Asynchronous Notify
+                                                int pid = pg_stream.ReceiveInteger(4);
+                                                String msg = pg_stream.ReceiveString(connection.getEncoding());
+                                                break;
+                                        case 'B':	// Binary Data Transfer
+                                                receiveTuple(true);
+                                                break;
+                                        case 'C':	// Command Status
+                                                receiveCommandStatus();
+                                                break;
+                                        case 'D':	// Text Data Transfer
+                                                receiveTuple(false);
+                                                break;
+                                        case 'E':	// Error Message
+
+                                                // it's possible to get more than one error message for a query
+                                                // see libpq comments wrt backend closing a connection
+                                                // so, append messages to a string buffer and keep processing
+                                                // check at the bottom to see if we need to throw an exception
+
+                                                if ( errorMessage == null )
+                                                        errorMessage = new StringBuffer();
+
+                                                errorMessage.append(pg_stream.ReceiveString(connection.getEncoding()));
+                                                // keep processing
+                                                break;
+                                        case 'I':	// Empty Query
+                                                int t = pg_stream.ReceiveChar();
+                                                break;
+                                        case 'N':	// Error Notification
+                                                connection.addWarning(pg_stream.ReceiveString(connection.getEncoding()));
+                                                break;
+                                        case 'P':	// Portal Name
+                                                String pname = pg_stream.ReceiveString(connection.getEncoding());
+                                                break;
+                                        case 'T':	// MetaData Field Description
+                                                receiveFields();
+                                                break;
+                                        case 'Z':
+					        l_endQuery = true;
+                                                break;
+                                        default:
+                                                throw new PSQLException("postgresql.con.type",
+                                                                                                new Character((char) c));
+                                }
+
+                        }
+
+                        // did we get an error during this query?
+                        if ( errorMessage != null )
+                                throw new SQLException( errorMessage.toString() );
+
+                        return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
+                }
+        }
+
+        /*
+         * Send a query to the backend.
+         */
+        private void sendQuery(String query) throws SQLException
+        {
+                try
+                {
+                        pg_stream.SendChar('Q');
+                        pg_stream.Send(connection.getEncoding().encode(query));
+                        pg_stream.SendChar(0);
+                        pg_stream.flush();
+
+                }
+                catch (IOException e)
+                {
+                        throw new PSQLException("postgresql.con.ioerror", e);
+                }
+        }
+
+        /*
+         * Receive a tuple from the backend.
+         *
+         * @param isBinary set if the tuple should be treated as binary data
+         */
+        private void receiveTuple(boolean isBinary) throws SQLException
+        {
+                if (fields == null)
+                        throw new PSQLException("postgresql.con.tuple");
+                Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
+                if (isBinary)
+                        binaryCursor = true;
+                if (maxRows == 0 || tuples.size() < maxRows)
+                        tuples.addElement(tuple);
+        }
+
+        /*
+         * Receive command status from the backend.
+         */
+        private void receiveCommandStatus() throws SQLException
+        {
+
+                status = pg_stream.ReceiveString(connection.getEncoding());
+
+                try
+                {
+                        // Now handle the update count correctly.
+                        if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
+                        {
+                                update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
+                        }
+                        if (status.startsWith("INSERT"))
+                        {
+                                insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),
+                                                                                          status.lastIndexOf(' ')));
+                        }
+                }
+                catch (NumberFormatException nfe)
+                {
+                        throw new PSQLException("postgresql.con.fathom", status);
+                }
+        }
+
+        /*
+         * Receive the field descriptions from the back end.
+         */
+        private void receiveFields() throws SQLException
+        {
+                if (fields != null)
+                        throw new PSQLException("postgresql.con.multres");
+
+                int size = pg_stream.ReceiveIntegerR(2);
+                fields = new Field[size];
+
+                for (int i = 0; i < fields.length; i++)
+                {
+                        String typeName = pg_stream.ReceiveString(connection.getEncoding());
+                        int typeOid = pg_stream.ReceiveIntegerR(4);
+                        int typeLength = pg_stream.ReceiveIntegerR(2);
+                        int typeModifier = pg_stream.ReceiveIntegerR(4);
+                        fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
+                }
+        }
 }
diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor2.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor2.java
deleted file mode 100644
index f48c95cc3095c0e544c852ff46e10ecdfaedb8ee..0000000000000000000000000000000000000000
--- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor2.java
+++ /dev/null
@@ -1,259 +0,0 @@
-
-package org.postgresql.core;
-
-import java.util.Vector;
-import java.io.IOException;
-import java.sql.*;
-import org.postgresql.*;
-import org.postgresql.util.PSQLException;
-
-/*
- * Executes a query on the backend.
- *
- * <p>The lifetime of a QueryExecutor object is from sending the query
- * until the response has been received from the backend.
- *
- * $Id: QueryExecutor2.java,v 1.1 2002/03/21 03:20:29 davec Exp $
- */
-
-public class QueryExecutor2
-{
-
-	private final String sql;
-	private final java.sql.Statement statement;
-	private final PG_Stream pg_stream;
-	private final org.postgresql.Connection connection;
-
-	public QueryExecutor2(String sql,
-						 java.sql.Statement statement,
-						 PG_Stream pg_stream,
-						 org.postgresql.Connection connection)
-	throws SQLException
-	{
-		this.sql = sql;
-		this.statement = statement;
-		this.pg_stream = pg_stream;
-		this.connection = connection;
-
-		if (statement != null)
-			maxRows = statement.getMaxRows();
-		else
-			maxRows = 0;
-	}
-
-	private Field[] fields = null;
-	private Vector tuples = new Vector();
-	private boolean binaryCursor = false;
-	private String status = null;
-	private int update_count = 1;
-	private long insert_oid = 0;
-	private int maxRows;
-
-	/*
-	 * Execute a query on the backend.
-	 */
-	public java.sql.ResultSet execute() throws SQLException
-	{
-
-    StringBuffer errorMessage = null;
-
-		synchronized (pg_stream)
-		{
-
-			sendQuery(sql);
-      connection.asyncStatus = org.postgresql.Connection.PGASYNC_BUSY;
-
-			while ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_IDLE )
-			{
-				int c = pg_stream.ReceiveChar();
-
-        if ( c == 'A' )
-        {
-
-          int pid = pg_stream.ReceiveIntegerR(4);
-          String msg = pg_stream.ReceiveString(connection.getEncoding());
-
-          org.postgresql.Driver.debug(msg);
-          continue;
-        }
-        else if ( c == 'N' )
-        {
-          String notification = pg_stream.ReceiveString(connection.getEncoding());
-          org.postgresql.Driver.debug(notification);
-          connection.addWarning(notification);
-          continue;
-        }
-        else if ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_BUSY )
-        {
-          if ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_IDLE )
-          {
-            // only one possibility left which is PGASYNC_READY, so let's get out
-            break;
-          }
-          if ( c == 'E' ) {
-            String error = pg_stream.ReceiveString(connection.getEncoding());
-            org.postgresql.Driver.debug(error);
-
-            // no sense in creating this object until we really need it
-            if ( errorMessage == null ) {
-              errorMessage = new StringBuffer();
-            }
-
-            errorMessage.append(error);
-            break;
-          }
-        }else{
-
-          switch (c)
-          {
-            case 'C':	// Command Status
-              receiveCommandStatus();
-              break;
-
-            case 'E':	// Error Message
-
-              // it's possible to get multiple error messages from one query
-              // see libpq, there are some comments about a connection being closed
-              // by the backend after real error occurs, so append error messages here
-              // so append them and just remember that an error occured
-              // throw the exception at the end of processing
-
-              String error = pg_stream.ReceiveString(connection.getEncoding());
-              org.postgresql.Driver.debug(error);
-
-              // no sense in creating this object until we really need it
-              if ( errorMessage == null ) {
-                errorMessage = new StringBuffer();
-              }
-
-              errorMessage.append(error);
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_READY;
-              break;
-
-            case 'Z':		 // backend ready for query, ignore for now :-)
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_IDLE;
-              break;
-
-            case 'I':	// Empty Query
-              int t = pg_stream.ReceiveChar();
-              if (t != 0)
-                throw new PSQLException("postgresql.con.garbled");
-
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_READY;
-              break;
-
-            case 'P':	// Portal Name
-              String pname = pg_stream.ReceiveString(connection.getEncoding());
-              org.postgresql.Driver.debug(pname);
-              break;
-
-            case 'T':	// MetaData Field Description
-              receiveFields();
-              break;
-
-            case 'B':	// Binary Data Transfer
-              receiveTuple(true);
-              break;
-
-            case 'D':	// Text Data Transfer
-              receiveTuple(false);
-              break;
-
-           default:
-              throw new PSQLException("postgresql.con.type",
-                          new Character((char) c));
-          }
-        }
-			}
-      // did we get an error message?
-
-      if ( errorMessage != null ) {
-        // yes, throw an exception
-        throw new SQLException(errorMessage.toString());
-      }
-			return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
-		}
-	}
-
-	/*
-	 * Send a query to the backend.
-	 */
-	private void sendQuery(String query) throws SQLException
-	{
-		try
-		{
-			pg_stream.SendChar('Q');
-			pg_stream.Send(connection.getEncoding().encode(query));
-			pg_stream.SendChar(0);
-			pg_stream.flush();
-
-		}
-		catch (IOException e)
-		{
-			throw new PSQLException("postgresql.con.ioerror", e);
-		}
-	}
-
-	/*
-	 * Receive a tuple from the backend.
-	 *
-	 * @param isBinary set if the tuple should be treated as binary data
-	 */
-	private void receiveTuple(boolean isBinary) throws SQLException
-	{
-		if (fields == null)
-			throw new PSQLException("postgresql.con.tuple");
-		Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
-		if (isBinary)
-			binaryCursor = true;
-		if (maxRows == 0 || tuples.size() < maxRows)
-			tuples.addElement(tuple);
-	}
-
-	/*
-	 * Receive command status from the backend.
-	 */
-	private void receiveCommandStatus() throws SQLException
-	{
-		status = pg_stream.ReceiveString(connection.getEncoding());
-
-		try
-		{
-			// Now handle the update count correctly.
-			if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
-			{
-				update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
-			}
-			if (status.startsWith("INSERT"))
-			{
-				insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),
-											  status.lastIndexOf(' ')));
-			}
-		}
-		catch (NumberFormatException nfe)
-		{
-			throw new PSQLException("postgresql.con.fathom", status);
-		}
-	}
-
-	/*
-	 * Receive the field descriptions from the back end.
-	 */
-	private void receiveFields() throws SQLException
-	{
-		if (fields != null)
-			throw new PSQLException("postgresql.con.multres");
-
-		int size = pg_stream.ReceiveIntegerR(2);
-		fields = new Field[size];
-
-		for (int i = 0; i < fields.length; i++)
-		{
-			String typeName = pg_stream.ReceiveString(connection.getEncoding());
-			int typeOid = pg_stream.ReceiveIntegerR(4);
-			int typeLength = pg_stream.ReceiveIntegerR(2);
-			int typeModifier = pg_stream.ReceiveIntegerR(4);
-			fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
-		}
-	}
-}
diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
index 2581f59b52c79cf5e619d5e4612010e0771bbfa8..a74645015a87b2e9764d53d44efa81155b2dcaae 100644
--- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
+++ b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
@@ -23,283 +23,269 @@ import org.postgresql.util.*;
  */
 public class Fastpath
 {
-	// This maps the functions names to their id's (possible unique just
-	// to a connection).
-	protected Hashtable func = new Hashtable();
+        // This maps the functions names to their id's (possible unique just
+        // to a connection).
+        protected Hashtable func = new Hashtable();
 
-	protected org.postgresql.Connection conn;		// our connection
-	protected org.postgresql.PG_Stream stream;	// the network stream
+        protected org.postgresql.Connection conn;		// our connection
+        protected org.postgresql.PG_Stream stream;	// the network stream
 
-	/*
-	 * Initialises the fastpath system
-	 *
-	 * <p><b>Important Notice</b>
-	 * <br>This is called from org.postgresql.Connection, and should not be called
-	 * from client code.
-	 *
-	 * @param conn org.postgresql.Connection to attach to
-	 * @param stream The network stream to the backend
-	 */
-	public Fastpath(org.postgresql.Connection conn, org.postgresql.PG_Stream stream)
-	{
-		this.conn = conn;
-		this.stream = stream;
-		//DriverManager.println("Fastpath initialised");
-	}
+        /*
+         * Initialises the fastpath system
+         *
+         * <p><b>Important Notice</b>
+         * <br>This is called from org.postgresql.Connection, and should not be called
+         * from client code.
+         *
+         * @param conn org.postgresql.Connection to attach to
+         * @param stream The network stream to the backend
+         */
+        public Fastpath(org.postgresql.Connection conn, org.postgresql.PG_Stream stream)
+        {
+                this.conn = conn;
+                this.stream = stream;
+                //DriverManager.println("Fastpath initialised");
+        }
 
-	/*
-	 * Send a function call to the PostgreSQL backend
-	 *
-	 * @param fnid Function id
-	 * @param resulttype True if the result is an integer, false for other results
-	 * @param args FastpathArguments to pass to fastpath
-	 * @return null if no data, Integer if an integer result, or byte[] otherwise
-	 * @exception SQLException if a database-access error occurs.
-	 */
-	public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
-	{
-		// added Oct 7 1998 to give us thread safety
-		synchronized (stream)
-		{
-			// send the function call
-			try
-			{
-				// 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
-				// that confuses the backend. The 0 terminates the command line.
-				stream.SendInteger(70, 1);
-				stream.SendInteger(0, 1);
+        /*
+         * Send a function call to the PostgreSQL backend
+         *
+         * @param fnid Function id
+         * @param resulttype True if the result is an integer, false for other results
+         * @param args FastpathArguments to pass to fastpath
+         * @return null if no data, Integer if an integer result, or byte[] otherwise
+         * @exception SQLException if a database-access error occurs.
+         */
+        public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
+        {
+                // added Oct 7 1998 to give us thread safety
+                synchronized (stream)
+                {
+                        // send the function call
+                        try
+                        {
+                                // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
+                                // that confuses the backend. The 0 terminates the command line.
+                                stream.SendInteger(70, 1);
+                                stream.SendInteger(0, 1);
 
-				stream.SendInteger(fnid, 4);
-				stream.SendInteger(args.length, 4);
+                                stream.SendInteger(fnid, 4);
+                                stream.SendInteger(args.length, 4);
 
-				for (int i = 0;i < args.length;i++)
-					args[i].send(stream);
+                                for (int i = 0;i < args.length;i++)
+                                        args[i].send(stream);
 
-				// This is needed, otherwise data can be lost
-				stream.flush();
+                                // This is needed, otherwise data can be lost
+                                stream.flush();
 
-			}
-			catch (IOException ioe)
-			{
-				throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
-			}
+                        }
+                        catch (IOException ioe)
+                        {
+                                throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
+                        }
 
-			// Now handle the result
+                        // Now handle the result
 
-			// We should get 'V' on sucess or 'E' on error. Anything else is treated
-			// as an error.
-			//int in = stream.ReceiveChar();
-			//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
-			//if (in!='V') {
-			//if (in=='E')
-			//throw new SQLException(stream.ReceiveString(conn.getEncoding()));
-			//throw new SQLException("Fastpath: expected 'V' from backend, got "+((char)in));
-			//}
+                        // Now loop, reading the results
+                        Object result = null; // our result
+                        StringBuffer errorMessage = null;
+                        int c;
+                        boolean l_endQuery = false;
+                        while (!l_endQuery)
+                        {
+                                c = stream.ReceiveChar();
 
-			// Now loop, reading the results
-			Object result = null; // our result
-			StringBuffer errorMessage = null;
-			boolean loop = true;
-			while (loop)
-			{
-				int in = stream.ReceiveChar();
-				//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
-				switch (in)
-				{
-					case 'V':
-						break;
+                                switch (c)
+                                {
+                                        case 'A':	// Asynchronous Notify
+                                                int pid = stream.ReceiveInteger(4);
+                                                String msg = stream.ReceiveString(conn.getEncoding());
+                                                break;
 
-						//------------------------------
-						// Function returned properly
-						//
-					case 'G':
-						int sz = stream.ReceiveIntegerR(4);
-						//DriverManager.println("G: size="+sz);  //debug
+                                                //------------------------------
+                                                // Error message returned
+                                        case 'E':
+                                                if ( errorMessage == null )
+                                                         errorMessage = new StringBuffer();
+                                                 errorMessage.append(stream.ReceiveString(conn.getEncoding()));
+                                                break;
 
-						// Return an Integer if
-						if (resulttype)
-							result = new Integer(stream.ReceiveIntegerR(sz));
-						else
-						{
-							byte buf[] = new byte[sz];
-							stream.Receive(buf, 0, sz);
-							result = buf;
-						}
-						break;
+                                                //------------------------------
+                                                // Notice from backend
+                                        case 'N':
+                                                conn.addWarning(stream.ReceiveString(conn.getEncoding()));
+                                                break;
 
-						//------------------------------
-						// Error message returned
-					case 'E':
-						if ( errorMessage == null )
-							errorMessage = new StringBuffer();
-						errorMessage.append(stream.ReceiveString(conn.getEncoding()));
-						break;
-						//------------------------------
-						// Notice from backend
-					case 'N':
-						conn.addWarning(stream.ReceiveString(conn.getEncoding()));
-						break;
+                                        case 'V':
+                                                int l_nextChar = stream.ReceiveChar();
+                                                if (l_nextChar == 'G') {
+                                                  int sz = stream.ReceiveIntegerR(4);
+                                                  // Return an Integer if
+                                                  if (resulttype)
+                                                        result = new Integer(stream.ReceiveIntegerR(sz));
+                                                  else
+                                                  {
+                                                        byte buf[] = new byte[sz];
+                                                        stream.Receive(buf, 0, sz);
+                                                        result = buf;
+                                                  }
+                                                  //There should be a trailing '0'
+                                                  int l_endChar = stream.ReceiveChar();
+                                                } else {
+                                                  //it must have been a '0', thus no results
+                                                }
+                                                break;
 
-						//------------------------------
-						// End of results
-						//
-						// Here we simply return res, which would contain the result
-						// processed earlier. If no result, this already contains null
-					case '0':
-						//DriverManager.println("returning "+result);
-						// return result;
-						break;
-					case 'Z':
-						// cause the loop to exit
-						loop = false;
-						break;
+                                        case 'Z':
+                                                l_endQuery = true;
+                                                break;
 
-					default:
-						throw new PSQLException("postgresql.fp.protocol", new Character((char)in));
-				}
-			}
-			
-			if ( errorMessage != null )
-				throw new PSQLException("postgresql.fp.error", errorMessage.toString());
+                                        default:
+                                                throw new PSQLException("postgresql.fp.protocol", new Character((char)c));
+                                }
+                        }
 
-			return result;
-		}
-	}
+                        if ( errorMessage != null )
+                                   throw new PSQLException("postgresql.fp.error", errorMessage.toString());
 
-	/*
-	 * Send a function call to the PostgreSQL backend by name.
-	 *
-	 * Note: the mapping for the procedure name to function id needs to exist,
-	 * usually to an earlier call to addfunction().
-	 *
-	 * This is the prefered method to call, as function id's can/may change
-	 * between versions of the backend.
-	 *
-	 * For an example of how this works, refer to org.postgresql.LargeObject
-	 *
-	 * @param name Function name
-	 * @param resulttype True if the result is an integer, false for other
-	 * results
-	 * @param args FastpathArguments to pass to fastpath
-	 * @return null if no data, Integer if an integer result, or byte[] otherwise
-	 * @exception SQLException if name is unknown or if a database-access error
-	 * occurs.
-	 * @see org.postgresql.LargeObject
-	 */
-	public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException
-	{
-		//DriverManager.println("Fastpath: calling "+name);
-		return fastpath(getID(name), resulttype, args);
-	}
+                        return result;
+                }
+        }
 
-	/*
-	 * This convenience method assumes that the return value is an Integer
-	 * @param name Function name
-	 * @param args Function arguments
-	 * @return integer result
-	 * @exception SQLException if a database-access error occurs or no result
-	 */
-	public int getInteger(String name, FastpathArg[] args) throws SQLException
-	{
-		Integer i = (Integer)fastpath(name, true, args);
-		if (i == null)
-			throw new PSQLException("postgresql.fp.expint", name);
-		return i.intValue();
-	}
+        /*
+         * Send a function call to the PostgreSQL backend by name.
+         *
+         * Note: the mapping for the procedure name to function id needs to exist,
+         * usually to an earlier call to addfunction().
+         *
+         * This is the prefered method to call, as function id's can/may change
+         * between versions of the backend.
+         *
+         * For an example of how this works, refer to org.postgresql.LargeObject
+         *
+         * @param name Function name
+         * @param resulttype True if the result is an integer, false for other
+         * results
+         * @param args FastpathArguments to pass to fastpath
+         * @return null if no data, Integer if an integer result, or byte[] otherwise
+         * @exception SQLException if name is unknown or if a database-access error
+         * occurs.
+         * @see org.postgresql.LargeObject
+         */
+        public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException
+        {
+                //DriverManager.println("Fastpath: calling "+name);
+                return fastpath(getID(name), resulttype, args);
+        }
 
-	/*
-	 * This convenience method assumes that the return value is an Integer
-	 * @param name Function name
-	 * @param args Function arguments
-	 * @return byte[] array containing result
-	 * @exception SQLException if a database-access error occurs or no result
-	 */
-	public byte[] getData(String name, FastpathArg[] args) throws SQLException
-	{
-		return (byte[])fastpath(name, false, args);
-	}
+        /*
+         * This convenience method assumes that the return value is an Integer
+         * @param name Function name
+         * @param args Function arguments
+         * @return integer result
+         * @exception SQLException if a database-access error occurs or no result
+         */
+        public int getInteger(String name, FastpathArg[] args) throws SQLException
+        {
+                Integer i = (Integer)fastpath(name, true, args);
+                if (i == null)
+                        throw new PSQLException("postgresql.fp.expint", name);
+                return i.intValue();
+        }
 
-	/*
-	 * This adds a function to our lookup table.
-	 *
-	 * <p>User code should use the addFunctions method, which is based upon a
-	 * query, rather than hard coding the oid. The oid for a function is not
-	 * guaranteed to remain static, even on different servers of the same
-	 * version.
-	 *
-	 * @param name Function name
-	 * @param fnid Function id
-	 */
-	public void addFunction(String name, int fnid)
-	{
-		func.put(name, new Integer(fnid));
-	}
+        /*
+         * This convenience method assumes that the return value is an Integer
+         * @param name Function name
+         * @param args Function arguments
+         * @return byte[] array containing result
+         * @exception SQLException if a database-access error occurs or no result
+         */
+        public byte[] getData(String name, FastpathArg[] args) throws SQLException
+        {
+                return (byte[])fastpath(name, false, args);
+        }
 
-	/*
-	 * This takes a ResultSet containing two columns. Column 1 contains the
-	 * function name, Column 2 the oid.
-	 *
-	 * <p>It reads the entire ResultSet, loading the values into the function
-	 * table.
-	 *
-	 * <p><b>REMEMBER</b> to close() the resultset after calling this!!
-	 *
-	 * <p><b><em>Implementation note about function name lookups:</em></b>
-	 *
-	 * <p>PostgreSQL stores the function id's and their corresponding names in
-	 * the pg_proc table. To speed things up locally, instead of querying each
-	 * function from that table when required, a Hashtable is used. Also, only
-	 * the function's required are entered into this table, keeping connection
-	 * times as fast as possible.
-	 *
-	 * <p>The org.postgresql.LargeObject class performs a query upon it's startup,
-	 * and passes the returned ResultSet to the addFunctions() method here.
-	 *
-	 * <p>Once this has been done, the LargeObject api refers to the functions by
-	 * name.
-	 *
-	 * <p>Dont think that manually converting them to the oid's will work. Ok,
-	 * they will for now, but they can change during development (there was some
-	 * discussion about this for V7.0), so this is implemented to prevent any
-	 * unwarranted headaches in the future.
-	 *
-	 * @param rs ResultSet
-	 * @exception SQLException if a database-access error occurs.
-	 * @see org.postgresql.LargeObjectManager
-	 */
-	public void addFunctions(ResultSet rs) throws SQLException
-	{
-		while (rs.next())
-		{
-			func.put(rs.getString(1), new Integer(rs.getInt(2)));
-		}
-	}
+        /*
+         * This adds a function to our lookup table.
+         *
+         * <p>User code should use the addFunctions method, which is based upon a
+         * query, rather than hard coding the oid. The oid for a function is not
+         * guaranteed to remain static, even on different servers of the same
+         * version.
+         *
+         * @param name Function name
+         * @param fnid Function id
+         */
+        public void addFunction(String name, int fnid)
+        {
+                func.put(name, new Integer(fnid));
+        }
 
-	/*
-	 * This returns the function id associated by its name
-	 *
-	 * <p>If addFunction() or addFunctions() have not been called for this name,
-	 * then an SQLException is thrown.
-	 *
-	 * @param name Function name to lookup
-	 * @return Function ID for fastpath call
-	 * @exception SQLException is function is unknown.
-	 */
-	public int getID(String name) throws SQLException
-	{
-		Integer id = (Integer)func.get(name);
+        /*
+         * This takes a ResultSet containing two columns. Column 1 contains the
+         * function name, Column 2 the oid.
+         *
+         * <p>It reads the entire ResultSet, loading the values into the function
+         * table.
+         *
+         * <p><b>REMEMBER</b> to close() the resultset after calling this!!
+         *
+         * <p><b><em>Implementation note about function name lookups:</em></b>
+         *
+         * <p>PostgreSQL stores the function id's and their corresponding names in
+         * the pg_proc table. To speed things up locally, instead of querying each
+         * function from that table when required, a Hashtable is used. Also, only
+         * the function's required are entered into this table, keeping connection
+         * times as fast as possible.
+         *
+         * <p>The org.postgresql.LargeObject class performs a query upon it's startup,
+         * and passes the returned ResultSet to the addFunctions() method here.
+         *
+         * <p>Once this has been done, the LargeObject api refers to the functions by
+         * name.
+         *
+         * <p>Dont think that manually converting them to the oid's will work. Ok,
+         * they will for now, but they can change during development (there was some
+         * discussion about this for V7.0), so this is implemented to prevent any
+         * unwarranted headaches in the future.
+         *
+         * @param rs ResultSet
+         * @exception SQLException if a database-access error occurs.
+         * @see org.postgresql.LargeObjectManager
+         */
+        public void addFunctions(ResultSet rs) throws SQLException
+        {
+                while (rs.next())
+                {
+                        func.put(rs.getString(1), new Integer(rs.getInt(2)));
+                }
+        }
 
-		// may be we could add a lookup to the database here, and store the result
-		// in our lookup table, throwing the exception if that fails.
-		// We must, however, ensure that if we do, any existing ResultSet is
-		// unaffected, otherwise we could break user code.
-		//
-		// so, until we know we can do this (needs testing, on the TODO list)
-		// for now, we throw the exception and do no lookups.
-		if (id == null)
-			throw new PSQLException("postgresql.fp.unknown", name);
+        /*
+         * This returns the function id associated by its name
+         *
+         * <p>If addFunction() or addFunctions() have not been called for this name,
+         * then an SQLException is thrown.
+         *
+         * @param name Function name to lookup
+         * @return Function ID for fastpath call
+         * @exception SQLException is function is unknown.
+         */
+        public int getID(String name) throws SQLException
+        {
+                Integer id = (Integer)func.get(name);
 
-		return id.intValue();
-	}
+                // may be we could add a lookup to the database here, and store the result
+                // in our lookup table, throwing the exception if that fails.
+                // We must, however, ensure that if we do, any existing ResultSet is
+                // unaffected, otherwise we could break user code.
+                //
+                // so, until we know we can do this (needs testing, on the TODO list)
+                // for now, we throw the exception and do no lookups.
+                if (id == null)
+                        throw new PSQLException("postgresql.fp.unknown", name);
+
+                return id.intValue();
+        }
 }
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
index e3ff6393940c9ec52162eac95414bb373b119579..0d62c74c9ad779f3b79b773520aead7e508cad4a 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /*
- * $Id: Connection.java,v 1.17 2002/01/15 06:55:13 barry Exp $
+ * $Id: Connection.java,v 1.18 2002/03/26 05:52:50 barry Exp $
  *
  * A Connection represents a session with a specific database.	Within the
  * context of a Connection, SQL statements are executed and results are
@@ -36,307 +36,287 @@ import org.postgresql.util.*;
  */
 public class Connection extends org.postgresql.Connection implements java.sql.Connection
 {
-	// This is a cache of the DatabaseMetaData instance for this connection
-	protected DatabaseMetaData metadata;
+        // This is a cache of the DatabaseMetaData instance for this connection
+        protected DatabaseMetaData metadata;
 
-	/*
-	 * The current type mappings
-	 */
-	protected java.util.Map typemap;
+        /*
+         * The current type mappings
+         */
+        protected java.util.Map typemap;
 
-	/*
-	 * SQL statements without parameters are normally executed using
-	 * Statement objects.  If the same SQL statement is executed many
-	 * times, it is more efficient to use a PreparedStatement
-	 *
-	 * @return a new Statement object
-	 * @exception SQLException passed through from the constructor
-	 */
-	public java.sql.Statement createStatement() throws SQLException
-	{
-		// The spec says default of TYPE_FORWARD_ONLY but everyone is used to
-		// using TYPE_SCROLL_INSENSITIVE
-		return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-	}
+        /*
+         * SQL statements without parameters are normally executed using
+         * Statement objects.  If the same SQL statement is executed many
+         * times, it is more efficient to use a PreparedStatement
+         *
+         * @return a new Statement object
+         * @exception SQLException passed through from the constructor
+         */
+        public java.sql.Statement createStatement() throws SQLException
+        {
+                // The spec says default of TYPE_FORWARD_ONLY but everyone is used to
+                // using TYPE_SCROLL_INSENSITIVE
+                return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
 
-	/*
-	 * SQL statements without parameters are normally executed using
-	 * Statement objects.  If the same SQL statement is executed many
-	 * times, it is more efficient to use a PreparedStatement
-	 *
-	 * @param resultSetType to use
-	 * @param resultSetCuncurrency to use
-	 * @return a new Statement object
-	 * @exception SQLException passed through from the constructor
-	 */
-	public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
-	{
-		Statement s = new Statement(this);
-		s.setResultSetType(resultSetType);
-		s.setResultSetConcurrency(resultSetConcurrency);
-		return s;
-	}
+        /*
+         * SQL statements without parameters are normally executed using
+         * Statement objects.  If the same SQL statement is executed many
+         * times, it is more efficient to use a PreparedStatement
+         *
+         * @param resultSetType to use
+         * @param resultSetCuncurrency to use
+         * @return a new Statement object
+         * @exception SQLException passed through from the constructor
+         */
+        public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
+        {
+                Statement s = new Statement(this);
+                s.setResultSetType(resultSetType);
+                s.setResultSetConcurrency(resultSetConcurrency);
+                return s;
+        }
 
 
-	/*
-	 * A SQL statement with or without IN parameters can be pre-compiled
-	 * and stored in a PreparedStatement object.  This object can then
-	 * be used to efficiently execute this statement multiple times.
-	 *
-	 * <B>Note:</B> This method is optimized for handling parametric
-	 * SQL statements that benefit from precompilation if the drivers
-	 * supports precompilation.  PostgreSQL does not support precompilation.
-	 * In this case, the statement is not sent to the database until the
-	 * PreparedStatement is executed.  This has no direct effect on users;
-	 * however it does affect which method throws certain SQLExceptions
-	 *
-	 * @param sql a SQL statement that may contain one or more '?' IN
-	 *	parameter placeholders
-	 * @return a new PreparedStatement object containing the pre-compiled
-	 *	statement.
-	 * @exception SQLException if a database access error occurs.
-	 */
-	public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
-	{
-		return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-	}
+        /*
+         * A SQL statement with or without IN parameters can be pre-compiled
+         * and stored in a PreparedStatement object.  This object can then
+         * be used to efficiently execute this statement multiple times.
+         *
+         * <B>Note:</B> This method is optimized for handling parametric
+         * SQL statements that benefit from precompilation if the drivers
+         * supports precompilation.  PostgreSQL does not support precompilation.
+         * In this case, the statement is not sent to the database until the
+         * PreparedStatement is executed.  This has no direct effect on users;
+         * however it does affect which method throws certain SQLExceptions
+         *
+         * @param sql a SQL statement that may contain one or more '?' IN
+	 *     	 parameter placeholders
+         * @return a new PreparedStatement object containing the pre-compiled
+	 *     	 statement.
+         * @exception SQLException if a database access error occurs.
+         */
+        public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
+        {
+                return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
 
-	public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
-	{
-		PreparedStatement s = new PreparedStatement(this, sql);
-		s.setResultSetType(resultSetType);
-		s.setResultSetConcurrency(resultSetConcurrency);
-		return s;
-	}
+        public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
+        {
+                PreparedStatement s = new PreparedStatement(this, sql);
+                s.setResultSetType(resultSetType);
+                s.setResultSetConcurrency(resultSetConcurrency);
+                return s;
+        }
 
-	/*
-	 * A SQL stored procedure call statement is handled by creating a
-	 * CallableStatement for it.  The CallableStatement provides methods
-	 * for setting up its IN and OUT parameters and methods for executing
-	 * it.
-	 *
-	 * <B>Note:</B> This method is optimised for handling stored procedure
-	 * call statements.  Some drivers may send the call statement to the
-	 * database when the prepareCall is done; others may wait until the
-	 * CallableStatement is executed.  This has no direct effect on users;
-	 * however, it does affect which method throws certain SQLExceptions
-	 *
-	 * @param sql a SQL statement that may contain one or more '?' parameter
-	 *	placeholders.  Typically this statement is a JDBC function call
-	 *	escape string.
-	 * @return a new CallableStatement object containing the pre-compiled
-	 *	SQL statement
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.CallableStatement prepareCall(String sql) throws SQLException
-	{
-		return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-	}
+        /*
+         * A SQL stored procedure call statement is handled by creating a
+         * CallableStatement for it.  The CallableStatement provides methods
+         * for setting up its IN and OUT parameters and methods for executing
+         * it.
+         *
+         * <B>Note:</B> This method is optimised for handling stored procedure
+         * call statements.  Some drivers may send the call statement to the
+         * database when the prepareCall is done; others may wait until the
+         * CallableStatement is executed.  This has no direct effect on users;
+         * however, it does affect which method throws certain SQLExceptions
+         *
+         * @param sql a SQL statement that may contain one or more '?' parameter
+	 *     	 placeholders.  Typically this statement is a JDBC function call
+	 *     	 escape string.
+         * @return a new CallableStatement object containing the pre-compiled
+	 *     	 SQL statement
+         * @exception SQLException if a database access error occurs
+         */
+        public java.sql.CallableStatement prepareCall(String sql) throws SQLException
+        {
+                return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
 
-	public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
-	{
-		throw new PSQLException("postgresql.con.call");
-		//CallableStatement s = new CallableStatement(this,sql);
-		//s.setResultSetType(resultSetType);
-		//s.setResultSetConcurrency(resultSetConcurrency);
-		//return s;
-	}
+        public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
+        {
+                throw new PSQLException("postgresql.con.call");
+                //CallableStatement s = new CallableStatement(this,sql);
+                //s.setResultSetType(resultSetType);
+                //s.setResultSetConcurrency(resultSetConcurrency);
+                //return s;
+        }
 
-	/*
-	 * Tests to see if a Connection is closed.
-	 *
-	 * Peter Feb 7 2000: Now I've discovered that this doesn't actually obey the
-	 * specifications. Under JDBC2.1, this should only be valid _after_ close()
-	 * has been called. It's result is not guraranteed to be valid before, and
-	 * client code should not use it to see if a connection is open. The spec says
-	 * that the client should monitor the SQLExceptions thrown when their queries
-	 * fail because the connection is dead.
-	 *
-	 * I don't like this definition. As it doesn't hurt breaking it here, our
-	 * isClosed() implementation does test the connection, so for PostgreSQL, you
-	 * can rely on isClosed() returning a valid result.
-	 *
-	 * @return the status of the connection
-	 * @exception SQLException (why?)
-	 */
-	public boolean isClosed() throws SQLException
-	{
-		// If the stream is gone, then close() was called
-		if (pg_stream == null)
-			return true;
+        /*
+         * Tests to see if a Connection is closed.
+         *
+         * Peter Feb 7 2000: Now I've discovered that this doesn't actually obey the
+         * specifications. Under JDBC2.1, this should only be valid _after_ close()
+         * has been called. It's result is not guraranteed to be valid before, and
+         * client code should not use it to see if a connection is open. The spec says
+         * that the client should monitor the SQLExceptions thrown when their queries
+         * fail because the connection is dead.
+         *
+         * I don't like this definition. As it doesn't hurt breaking it here, our
+         * isClosed() implementation does test the connection, so for PostgreSQL, you
+         * can rely on isClosed() returning a valid result.
+         *
+         * @return the status of the connection
+         * @exception SQLException (why?)
+         */
+        public boolean isClosed() throws SQLException
+        {
+                // If the stream is gone, then close() was called
+                if (pg_stream == null)
+                        return true;
+                return false;
+        }
 
-		// ok, test the connection
-		try
-		{
-			// by sending an empty query. If we are dead, then an SQLException should
-			// be thrown
-			java.sql.ResultSet rs = ExecSQL(" ");
-			if (rs != null)
-				rs.close();
+        /*
+         * A connection's database is able to provide information describing
+         * its tables, its supported SQL grammar, its stored procedures, the
+         * capabilities of this connection, etc.  This information is made
+         * available through a DatabaseMetaData object.
+         *
+         * @return a DatabaseMetaData object for this connection
+         * @exception SQLException if a database access error occurs
+         */
+        public java.sql.DatabaseMetaData getMetaData() throws SQLException
+        {
+                if (metadata == null)
+                        metadata = new DatabaseMetaData(this);
+                return metadata;
+        }
 
-			// By now, we must be alive
-			return false;
-		}
-		catch (SQLException se)
-		{
-			// Why throw an SQLException as this may fail without throwing one,
-			// ie isClosed() is called incase the connection has died, and we don't
-			// want to find out by an Exception, so instead we return true, as its
-			// most likely why it was thrown in the first place.
-			return true;
-		}
-	}
+        /*
+         * This overides the method in org.postgresql.Connection and returns a
+         * ResultSet.
+         */
+        public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
+        {
+                // In 7.1 we now test concurrency to see which class to return. If we are not working with a
+                // Statement then default to a normal ResultSet object.
+                if (stat != null)
+                {
+                        if (stat.getResultSetConcurrency() == java.sql.ResultSet.CONCUR_UPDATABLE)
+                                return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
+                }
 
-	/*
-	 * A connection's database is able to provide information describing
-	 * its tables, its supported SQL grammar, its stored procedures, the
-	 * capabilities of this connection, etc.  This information is made
-	 * available through a DatabaseMetaData object.
-	 *
-	 * @return a DatabaseMetaData object for this connection
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.DatabaseMetaData getMetaData() throws SQLException
-	{
-		if (metadata == null)
-			metadata = new DatabaseMetaData(this);
-		return metadata;
-	}
+                return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
+        }
 
-	/*
-	 * This overides the method in org.postgresql.Connection and returns a
-	 * ResultSet.
-	 */
-	public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
-	{
-		// In 7.1 we now test concurrency to see which class to return. If we are not working with a
-		// Statement then default to a normal ResultSet object.
-		if (stat != null)
-		{
-			if (stat.getResultSetConcurrency() == java.sql.ResultSet.CONCUR_UPDATABLE)
-				return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-		}
+        // *****************
+        // JDBC 2 extensions
+        // *****************
 
-		return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-	}
+        public java.util.Map getTypeMap() throws SQLException
+        {
+                // new in 7.1
+                return typemap;
+        }
 
-	// *****************
-	// JDBC 2 extensions
-	// *****************
 
-	public java.util.Map getTypeMap() throws SQLException
-	{
-		// new in 7.1
-		return typemap;
-	}
+        public void setTypeMap(java.util.Map map) throws SQLException
+        {
+                // new in 7.1
+                typemap = map;
+        }
 
+        /*
+         * This overides the standard internal getObject method so that we can
+         * check the jdbc2 type map first
+         *
+         * @return PGobject for this type, and set to value
+         * @exception SQLException if value is not correct for this type
+         * @see org.postgresql.util.Serialize
+         */
+        public Object getObject(String type, String value) throws SQLException
+        {
+                if (typemap != null)
+                {
+                        SQLData d = (SQLData) typemap.get(type);
+                        if (d != null)
+                        {
+                                // Handle the type (requires SQLInput & SQLOutput classes to be implemented)
+                                throw org.postgresql.Driver.notImplemented();
+                        }
+                }
 
-	public void setTypeMap(java.util.Map map) throws SQLException
-	{
-		// new in 7.1
-		typemap = map;
-	}
+                // Default to the original method
+                return super.getObject(type, value);
+        }
 
-	/*
-	 * This overides the standard internal getObject method so that we can
-	 * check the jdbc2 type map first
-	 *
-	 * @return PGobject for this type, and set to value
-	 * @exception SQLException if value is not correct for this type
-	 * @see org.postgresql.util.Serialize
-	 */
-	public Object getObject(String type, String value) throws SQLException
-	{
-		if (typemap != null)
-		{
-			SQLData d = (SQLData) typemap.get(type);
-			if (d != null)
-			{
-				// Handle the type (requires SQLInput & SQLOutput classes to be implemented)
-				throw org.postgresql.Driver.notImplemented();
-			}
-		}
+        /* An implementation of the abstract method in the parent class.
+         * This implemetation uses the jdbc2Types array to support the jdbc2
+         * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
+         * jdbc2 adds the Array types.
+         */
+        public int getSQLType(String pgTypeName)
+        {
+                int sqlType = Types.OTHER; // default value
+                for (int i = 0;i < jdbc2Types.length;i++)
+                {
+                        if (pgTypeName.equals(jdbc2Types[i]))
+                        {
+                                sqlType = jdbc2Typei[i];
+                                break;
+                        }
+                }
+                return sqlType;
+        }
 
-		// Default to the original method
-		return super.getObject(type, value);
-	}
+        /*
+         * This table holds the org.postgresql names for the types supported.
+         * Any types that map to Types.OTHER (eg POINT) don't go into this table.
+         * They default automatically to Types.OTHER
+         *
+         * Note: This must be in the same order as below.
+         *
+         * Tip: keep these grouped together by the Types. value
+         */
+        private static final String jdbc2Types[] = {
+                                "int2",
+                                "int4", "oid",
+                                "int8",
+                                "cash", "money",
+                                "numeric",
+                                "float4",
+                                "float8",
+                                "bpchar", "char", "char2", "char4", "char8", "char16",
+                                "varchar", "text", "name", "filename",
+                                "bytea",
+                                "bool",
+                                "date",
+                                "time",
+                                "abstime", "timestamp", "timestamptz",
+                                "_bool", "_char", "_int2", "_int4", "_text",
+                                "_oid", "_varchar", "_int8", "_float4", "_float8",
+                                "_abstime", "_date", "_time", "_timestamp", "_numeric",
+                                "_bytea"
+                        };
 
-	/* An implementation of the abstract method in the parent class.
-	 * This implemetation uses the jdbc2Types array to support the jdbc2
-	 * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
-	 * jdbc2 adds the Array types.
-	 */
-	public int getSQLType(String pgTypeName)
-	{
-		int sqlType = Types.OTHER; // default value
-		for (int i = 0;i < jdbc2Types.length;i++)
-		{
-			if (pgTypeName.equals(jdbc2Types[i]))
-			{
-				sqlType = jdbc2Typei[i];
-				break;
-			}
-		}
-		return sqlType;
-	}
-
-	/*
-	 * This table holds the org.postgresql names for the types supported.
-	 * Any types that map to Types.OTHER (eg POINT) don't go into this table.
-	 * They default automatically to Types.OTHER
-	 *
-	 * Note: This must be in the same order as below.
-	 *
-	 * Tip: keep these grouped together by the Types. value
-	 */
-	private static final String jdbc2Types[] = {
-				"int2",
-				"int4", "oid",
-				"int8",
-				"cash", "money",
-				"numeric",
-				"float4",
-				"float8",
-				"bpchar", "char", "char2", "char4", "char8", "char16",
-				"varchar", "text", "name", "filename",
-				"bytea",
-				"bool",
-				"date",
-				"time",
-				"abstime", "timestamp", "timestamptz",
-				"_bool", "_char", "_int2", "_int4", "_text",
-				"_oid", "_varchar", "_int8", "_float4", "_float8",
-				"_abstime", "_date", "_time", "_timestamp", "_numeric",
-				"_bytea"
-			};
-
-	/*
-	 * This table holds the JDBC type for each entry above.
-	 *
-	 * Note: This must be in the same order as above
-	 *
-	 * Tip: keep these grouped together by the Types. value
-	 */
-	private static final int jdbc2Typei[] = {
-												Types.SMALLINT,
-												Types.INTEGER, Types.INTEGER,
-												Types.BIGINT,
-												Types.DOUBLE, Types.DOUBLE,
-												Types.NUMERIC,
-												Types.REAL,
-												Types.DOUBLE,
-												Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
-												Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
-												Types.BINARY,
-												Types.BIT,
-												Types.DATE,
-												Types.TIME,
-												Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
-												Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-												Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-												Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-												Types.ARRAY
-											};
+        /*
+         * This table holds the JDBC type for each entry above.
+         *
+         * Note: This must be in the same order as above
+         *
+         * Tip: keep these grouped together by the Types. value
+         */
+        private static final int jdbc2Typei[] = {
+                                                                                                Types.SMALLINT,
+                                                                                                Types.INTEGER, Types.INTEGER,
+                                                                                                Types.BIGINT,
+                                                                                                Types.DOUBLE, Types.DOUBLE,
+                                                                                                Types.NUMERIC,
+                                                                                                Types.REAL,
+                                                                                                Types.DOUBLE,
+                                                                                                Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
+                                                                                                Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+                                                                                                Types.BINARY,
+                                                                                                Types.BIT,
+                                                                                                Types.DATE,
+                                                                                                Types.TIME,
+                                                                                                Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
+                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                                                                                Types.ARRAY
+                                                                                        };
 
 
 }