OSDN Git Service

Attached is my attempt to clean up the horrors of the ExecSQL() method in
authorBruce Momjian <bruce@momjian.us>
Thu, 6 Sep 2001 03:13:34 +0000 (03:13 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 6 Sep 2001 03:13:34 +0000 (03:13 +0000)
the JDBC driver.

I've done this by extracting it into a new method object called
QueryExecutor (should go into org/postgresql/core/) and then taking it
apart into different methods in that class.

A short summary:

* Extracted ExecSQL() from Connection into a method object called
  QueryExecutor.

* Moved ReceiveFields() from Connection to QueryExecutor.

* Extracted parts of the original ExecSQL() method body into smaller
  methods on QueryExecutor.

* Bug fix: The instance variable "pid" in Connection was used in two
  places with different meaning. Both were probably in dead code, but it's
  fixed anyway.

Anders Bengtsson

src/interfaces/jdbc/org/postgresql/Connection.java
src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java

index 8218f51..3850bd2 100644 (file)
@@ -8,10 +8,10 @@ import org.postgresql.Field;
 import org.postgresql.fastpath.*;
 import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
-import org.postgresql.core.Encoding;
+import org.postgresql.core.*;
 
 /**
- * $Id: Connection.java,v 1.26 2001/08/24 16:50:12 momjian Exp $
+ * $Id: Connection.java,v 1.27 2001/09/06 03:13:34 momjian Exp $
  *
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -348,166 +348,9 @@ public abstract class Connection
      * @return a ResultSet holding the results
      * @exception SQLException if a database error occurs
      */
-    public java.sql.ResultSet ExecSQL(String sql,java.sql.Statement stat) throws SQLException
+    public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
     {
-      // added Jan 30 2001 to correct maxrows per statement
-      int maxrows=0;
-      if(stat!=null)
-        maxrows=stat.getMaxRows();
-
-       // added Oct 7 1998 to give us thread safety.
-       synchronized(pg_stream) {
-           // Deallocate all resources in the stream associated
-           // with a previous request.
-           // This will let the driver reuse byte arrays that has already
-           // been allocated instead of allocating new ones in order
-           // to gain performance improvements.
-           // PM 17/01/01: Commented out due to race bug. See comments in
-            // PG_Stream
-            //pg_stream.deallocate();
-
-           Field[] fields = null;
-           Vector tuples = new Vector();
-           byte[] buf = null;
-           int fqp = 0;
-           boolean hfr = false;
-           String recv_status = null, msg;
-           int update_count = 1;
-           int insert_oid = 0;
-           SQLException final_error = null;
-
-           buf = encoding.encode(sql);
-           try
-               {
-                   pg_stream.SendChar('Q');
-                   pg_stream.Send(buf);
-                   pg_stream.SendChar(0);
-                   pg_stream.flush();
-               } catch (IOException e) {
-                   throw new PSQLException("postgresql.con.ioerror",e);
-               }
-
-           while (!hfr || fqp > 0)
-               {
-                   Object tup=null;    // holds rows as they are recieved
-
-                   int c = pg_stream.ReceiveChar();
-
-                   switch (c)
-                       {
-                       case 'A':       // Asynchronous Notify
-                           pid = pg_stream.ReceiveInteger(4);
-                            msg = pg_stream.ReceiveString(encoding);
-                           break;
-                       case 'B':       // Binary Data Transfer
-                           if (fields == null)
-                               throw new PSQLException("postgresql.con.tuple");
-                           tup = pg_stream.ReceiveTuple(fields.length, true);
-                           // This implements Statement.setMaxRows()
-                           if(maxrows==0 || tuples.size()<maxrows)
-                               tuples.addElement(tup);
-                           break;
-                       case 'C':       // Command Status
-                            recv_status = pg_stream.ReceiveString(encoding);
-
-                               // Now handle the update count correctly.
-                               if(recv_status.startsWith("INSERT") || recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE") || recv_status.startsWith("MOVE")) {
-                                       try {
-                                               update_count = Integer.parseInt(recv_status.substring(1+recv_status.lastIndexOf(' ')));
-                                       } catch(NumberFormatException nfe) {
-                                               throw new PSQLException("postgresql.con.fathom",recv_status);
-                                       }
-                                       if(recv_status.startsWith("INSERT")) {
-                                           try {
-                                               insert_oid = Integer.parseInt(recv_status.substring(1+recv_status.indexOf(' '),recv_status.lastIndexOf(' ')));
-                                           } catch(NumberFormatException nfe) {
-                                               throw new PSQLException("postgresql.con.fathom",recv_status);
-                                           }
-                                       }
-                               }
-                           if (fields != null)
-                               hfr = true;
-                           else
-                               {
-                                   try
-                                       {
-                                           pg_stream.SendChar('Q');
-                                           pg_stream.SendChar(' ');
-                                           pg_stream.SendChar(0);
-                                           pg_stream.flush();
-                                       } catch (IOException e) {
-                                           throw new PSQLException("postgresql.con.ioerror",e);
-                                       }
-                                   fqp++;
-                               }
-                           break;
-                       case 'D':       // Text Data Transfer
-                           if (fields == null)
-                               throw new PSQLException("postgresql.con.tuple");
-                           tup = pg_stream.ReceiveTuple(fields.length, false);
-                           // This implements Statement.setMaxRows()
-                           if(maxrows==0 || tuples.size()<maxrows)
-                               tuples.addElement(tup);
-                           break;
-                       case 'E':       // Error Message
-                            msg = pg_stream.ReceiveString(encoding);
-                           final_error = new SQLException(msg);
-                           hfr = true;
-                           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
-                            addWarning(pg_stream.ReceiveString(encoding));
-                           break;
-                       case 'P':       // Portal Name
-                            String pname = pg_stream.ReceiveString(encoding);
-                           break;
-                       case 'T':       // MetaData Field Description
-                           if (fields != null)
-                               throw new PSQLException("postgresql.con.multres");
-                           fields = ReceiveFields();
-                           break;
-                       case 'Z':       // backend ready for query, ignore for now :-)
-                           break;
-                       default:
-                           throw new PSQLException("postgresql.con.type",new Character((char)c));
-                       }
-               }
-           if (final_error != null)
-               throw final_error;
-
-           return getResultSet(this, stat, fields, tuples, recv_status, update_count, insert_oid);
-       }
-    }
-
-    /**
-     * Receive the field descriptions from the back end
-     *
-     * @return an array of the Field object describing the fields
-     * @exception SQLException if a database error occurs
-     */
-    private Field[] ReceiveFields() throws SQLException
-    {
-       int nf = pg_stream.ReceiveIntegerR(2), i;
-       Field[] fields = new Field[nf];
-
-       for (i = 0 ; i < nf ; ++i)
-           {
-                String typname = pg_stream.ReceiveString(encoding);
-               int typid = pg_stream.ReceiveIntegerR(4);
-               int typlen = pg_stream.ReceiveIntegerR(2);
-               int typmod = pg_stream.ReceiveIntegerR(4);
-               fields[i] = new Field(this, typname, typid, typlen, typmod);
-           }
-       return fields;
+       return new QueryExecutor(sql, stat, pg_stream, this).execute();
     }
 
     /**
@@ -793,7 +636,7 @@ public abstract class Connection
      * This returns a resultset. It must be overridden, so that the correct
      * version (from jdbc1 or jdbc2) are returned.
      */
-    protected abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) throws SQLException;
+    public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) throws SQLException;
 
     /**
      * In some cases, it is desirable to immediately release a Connection's
index a809d33..cf2b4bf 100644 (file)
@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.8 2001/08/24 16:50:15 momjian Exp $
+ * $Id: Connection.java,v 1.9 2001/09/06 03:13:34 momjian Exp $
  *
  * A Connection represents a session with a specific database.  Within the
  * context of a Connection, SQL statements are executed and results are
@@ -131,7 +131,7 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
      * This overides the method in org.postgresql.Connection and returns a
      * ResultSet.
      */
-    protected java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) throws SQLException
+    public java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) throws SQLException
     {
       // in jdbc1 stat is ignored.
        return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn,fields,tuples,status,updateCount,insertOID);
index 5b4c17d..f705693 100644 (file)
@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.10 2001/08/24 16:50:16 momjian Exp $
+ * $Id: Connection.java,v 1.11 2001/09/06 03:13:34 momjian Exp $
  *
  * A Connection represents a session with a specific database.  Within the
  * context of a Connection, SQL statements are executed and results are
@@ -204,7 +204,7 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
      * This overides the method in org.postgresql.Connection and returns a
      * ResultSet.
      */
-    protected java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat,Field[] fields, Vector tuples, String status, int updateCount, int insertOID) throws SQLException
+    public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat,Field[] fields, Vector tuples, String status, int updateCount, int insertOID) 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.