mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-11-21 03:13:05 +08:00
Attached is my attempt to clean up the horrors of the ExecSQL() method in
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
This commit is contained in:
parent
d99794e613
commit
e30b283f30
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user