]> granicus.if.org Git - postgresql/commitdiff
Changed QueryExecutor.java to correctly read responses from the backend.
authorBarry Lind <barry@xythos.com>
Tue, 26 Mar 2002 05:52:50 +0000 (05:52 +0000)
committerBarry Lind <barry@xythos.com>
Tue, 26 Mar 2002 05:52:50 +0000 (05:52 +0000)
Fixed NPE when database name was not passed on the jdbc connection URL
Fixed Connection.isClosed() to not hit the DB for every call

src/interfaces/jdbc/org/postgresql/Connection.java
src/interfaces/jdbc/org/postgresql/Driver.java.in
src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
src/interfaces/jdbc/org/postgresql/core/QueryExecutor2.java [deleted file]
src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java

index 3ee6deea0a5d4ba95e95a23e783c6ea7004da6ea..54f067542de446718e9e16f0c6baf07abf5e0e7d 100644 (file)
@@ -11,7 +11,7 @@ import org.postgresql.util.*;
 import org.postgresql.core.*;\r
 \r
 /*\r
- * $Id: Connection.java,v 1.44 2002/03/21 02:39:06 davec Exp $\r
+ * $Id: Connection.java,v 1.45 2002/03/26 05:52:48 barry Exp $\r
  *\r
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or\r
  * JDBC2 versions of the Connection class.\r
@@ -59,10 +59,6 @@ public abstract class Connection
        private static final int AUTH_REQ_CRYPT = 4;\r
        private static final int AUTH_REQ_MD5 = 5;\r
 \r
-       public final static int PGASYNC_IDLE = 0;                               /* nothing's happening, dude */\r
-       public final static int PGASYNC_BUSY = 1;                               /* query in progress */\r
-       public final static int PGASYNC_READY = 2;                      /* result ready for PQgetResult */\r
-\r
 \r
        // These are used to cache oids, PGTypes and SQLTypes\r
        private static Hashtable sqlTypeCache = new Hashtable();  // oid -> SQLType\r
@@ -81,7 +77,6 @@ public abstract class Connection
        public int pid;\r
        public int ckey;\r
 \r
-  public int asyncStatus = PGASYNC_READY;\r
        /*\r
         * This is called by Class.forName() from within org.postgresql.Driver\r
         */\r
@@ -427,7 +422,7 @@ public abstract class Connection
         */\r
        public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException\r
        {\r
-               return new QueryExecutor2(sql, stat, pg_stream, this).execute();\r
+               return new QueryExecutor(sql, stat, pg_stream, this).execute();\r
        }\r
 \r
        /*\r
index a6d0fb03a257332a819443545e0f8ae9cfcabd6e..bc1925efe56bd9b86c5e6b3a12abfe26f7a2bf23 100644 (file)
@@ -419,7 +419,7 @@ public class Driver implements java.sql.Driver
         */
        public String database()
        {
-               return props.getProperty("PGDBNAME");
+               return props.getProperty("PGDBNAME", "");
        }
 
        /*
index 237aa49684f653ee0991dedd119f2e9780613069..bfa6af3572380fef41cae2f54c3edc634d73b7ea 100644 (file)
@@ -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 (file)
index f48c95c..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-\r
-package org.postgresql.core;\r
-\r
-import java.util.Vector;\r
-import java.io.IOException;\r
-import java.sql.*;\r
-import org.postgresql.*;\r
-import org.postgresql.util.PSQLException;\r
-\r
-/*\r
- * Executes a query on the backend.\r
- *\r
- * <p>The lifetime of a QueryExecutor object is from sending the query\r
- * until the response has been received from the backend.\r
- *\r
- * $Id: QueryExecutor2.java,v 1.1 2002/03/21 03:20:29 davec Exp $\r
- */\r
-\r
-public class QueryExecutor2\r
-{\r
-\r
-       private final String sql;\r
-       private final java.sql.Statement statement;\r
-       private final PG_Stream pg_stream;\r
-       private final org.postgresql.Connection connection;\r
-\r
-       public QueryExecutor2(String sql,\r
-                                                java.sql.Statement statement,\r
-                                                PG_Stream pg_stream,\r
-                                                org.postgresql.Connection connection)\r
-       throws SQLException\r
-       {\r
-               this.sql = sql;\r
-               this.statement = statement;\r
-               this.pg_stream = pg_stream;\r
-               this.connection = connection;\r
-\r
-               if (statement != null)\r
-                       maxRows = statement.getMaxRows();\r
-               else\r
-                       maxRows = 0;\r
-       }\r
-\r
-       private Field[] fields = null;\r
-       private Vector tuples = new Vector();\r
-       private boolean binaryCursor = false;\r
-       private String status = null;\r
-       private int update_count = 1;\r
-       private long insert_oid = 0;\r
-       private int maxRows;\r
-\r
-       /*\r
-        * Execute a query on the backend.\r
-        */\r
-       public java.sql.ResultSet execute() throws SQLException\r
-       {\r
-\r
-    StringBuffer errorMessage = null;\r
-\r
-               synchronized (pg_stream)\r
-               {\r
-\r
-                       sendQuery(sql);\r
-      connection.asyncStatus = org.postgresql.Connection.PGASYNC_BUSY;\r
-\r
-                       while ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_IDLE )\r
-                       {\r
-                               int c = pg_stream.ReceiveChar();\r
-\r
-        if ( c == 'A' )\r
-        {\r
-\r
-          int pid = pg_stream.ReceiveIntegerR(4);\r
-          String msg = pg_stream.ReceiveString(connection.getEncoding());\r
-\r
-          org.postgresql.Driver.debug(msg);\r
-          continue;\r
-        }\r
-        else if ( c == 'N' )\r
-        {\r
-          String notification = pg_stream.ReceiveString(connection.getEncoding());\r
-          org.postgresql.Driver.debug(notification);\r
-          connection.addWarning(notification);\r
-          continue;\r
-        }\r
-        else if ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_BUSY )\r
-        {\r
-          if ( connection.asyncStatus != org.postgresql.Connection.PGASYNC_IDLE )\r
-          {\r
-            // only one possibility left which is PGASYNC_READY, so let's get out\r
-            break;\r
-          }\r
-          if ( c == 'E' ) {\r
-            String error = pg_stream.ReceiveString(connection.getEncoding());\r
-            org.postgresql.Driver.debug(error);\r
-\r
-            // no sense in creating this object until we really need it\r
-            if ( errorMessage == null ) {\r
-              errorMessage = new StringBuffer();\r
-            }\r
-\r
-            errorMessage.append(error);\r
-            break;\r
-          }\r
-        }else{\r
-\r
-          switch (c)\r
-          {\r
-            case 'C':  // Command Status\r
-              receiveCommandStatus();\r
-              break;\r
-\r
-            case 'E':  // Error Message\r
-\r
-              // it's possible to get multiple error messages from one query\r
-              // see libpq, there are some comments about a connection being closed\r
-              // by the backend after real error occurs, so append error messages here\r
-              // so append them and just remember that an error occured\r
-              // throw the exception at the end of processing\r
-\r
-              String error = pg_stream.ReceiveString(connection.getEncoding());\r
-              org.postgresql.Driver.debug(error);\r
-\r
-              // no sense in creating this object until we really need it\r
-              if ( errorMessage == null ) {\r
-                errorMessage = new StringBuffer();\r
-              }\r
-\r
-              errorMessage.append(error);\r
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_READY;\r
-              break;\r
-\r
-            case 'Z':           // backend ready for query, ignore for now :-)\r
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_IDLE;\r
-              break;\r
-\r
-            case 'I':  // Empty Query\r
-              int t = pg_stream.ReceiveChar();\r
-              if (t != 0)\r
-                throw new PSQLException("postgresql.con.garbled");\r
-\r
-              connection.asyncStatus = org.postgresql.Connection.PGASYNC_READY;\r
-              break;\r
-\r
-            case 'P':  // Portal Name\r
-              String pname = pg_stream.ReceiveString(connection.getEncoding());\r
-              org.postgresql.Driver.debug(pname);\r
-              break;\r
-\r
-            case 'T':  // MetaData Field Description\r
-              receiveFields();\r
-              break;\r
-\r
-            case 'B':  // Binary Data Transfer\r
-              receiveTuple(true);\r
-              break;\r
-\r
-            case 'D':  // Text Data Transfer\r
-              receiveTuple(false);\r
-              break;\r
-\r
-           default:\r
-              throw new PSQLException("postgresql.con.type",\r
-                          new Character((char) c));\r
-          }\r
-        }\r
-                       }\r
-      // did we get an error message?\r
-\r
-      if ( errorMessage != null ) {\r
-        // yes, throw an exception\r
-        throw new SQLException(errorMessage.toString());\r
-      }\r
-                       return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);\r
-               }\r
-       }\r
-\r
-       /*\r
-        * Send a query to the backend.\r
-        */\r
-       private void sendQuery(String query) throws SQLException\r
-       {\r
-               try\r
-               {\r
-                       pg_stream.SendChar('Q');\r
-                       pg_stream.Send(connection.getEncoding().encode(query));\r
-                       pg_stream.SendChar(0);\r
-                       pg_stream.flush();\r
-\r
-               }\r
-               catch (IOException e)\r
-               {\r
-                       throw new PSQLException("postgresql.con.ioerror", e);\r
-               }\r
-       }\r
-\r
-       /*\r
-        * Receive a tuple from the backend.\r
-        *\r
-        * @param isBinary set if the tuple should be treated as binary data\r
-        */\r
-       private void receiveTuple(boolean isBinary) throws SQLException\r
-       {\r
-               if (fields == null)\r
-                       throw new PSQLException("postgresql.con.tuple");\r
-               Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);\r
-               if (isBinary)\r
-                       binaryCursor = true;\r
-               if (maxRows == 0 || tuples.size() < maxRows)\r
-                       tuples.addElement(tuple);\r
-       }\r
-\r
-       /*\r
-        * Receive command status from the backend.\r
-        */\r
-       private void receiveCommandStatus() throws SQLException\r
-       {\r
-               status = pg_stream.ReceiveString(connection.getEncoding());\r
-\r
-               try\r
-               {\r
-                       // Now handle the update count correctly.\r
-                       if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))\r
-                       {\r
-                               update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));\r
-                       }\r
-                       if (status.startsWith("INSERT"))\r
-                       {\r
-                               insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),\r
-                                                                                         status.lastIndexOf(' ')));\r
-                       }\r
-               }\r
-               catch (NumberFormatException nfe)\r
-               {\r
-                       throw new PSQLException("postgresql.con.fathom", status);\r
-               }\r
-       }\r
-\r
-       /*\r
-        * Receive the field descriptions from the back end.\r
-        */\r
-       private void receiveFields() throws SQLException\r
-       {\r
-               if (fields != null)\r
-                       throw new PSQLException("postgresql.con.multres");\r
-\r
-               int size = pg_stream.ReceiveIntegerR(2);\r
-               fields = new Field[size];\r
-\r
-               for (int i = 0; i < fields.length; i++)\r
-               {\r
-                       String typeName = pg_stream.ReceiveString(connection.getEncoding());\r
-                       int typeOid = pg_stream.ReceiveIntegerR(4);\r
-                       int typeLength = pg_stream.ReceiveIntegerR(2);\r
-                       int typeModifier = pg_stream.ReceiveIntegerR(4);\r
-                       fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);\r
-               }\r
-       }\r
-}\r
index 2581f59b52c79cf5e619d5e4612010e0771bbfa8..a74645015a87b2e9764d53d44efa81155b2dcaae 100644 (file)
@@ -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();
+        }
 }
 
index e3ff6393940c9ec52162eac95414bb373b119579..0d62c74c9ad779f3b79b773520aead7e508cad4a 100644 (file)
@@ -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
+                                                                                        };
 
 
 }