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.
* @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();
}
/**
* 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