From: Barry Lind Date: Tue, 9 Oct 2001 20:47:35 +0000 (+0000) Subject: This patch fixes a bug introduced in the jdbc bytea support patch. X-Git-Tag: REL7_2_BETA1~145 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=839b9bc0117946afd62ee385a4c8a36c01b3053b;p=postgresql This patch fixes a bug introduced in the jdbc bytea support patch. That patch broke the ability to read data from binary cursors. --Barry Lind Modified Files: pgsql/src/interfaces/jdbc/org/postgresql/Connection.java pgsql/src/interfaces/jdbc/org/postgresql/ResultSet.java pgsql/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java --- diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java index aba2849171..b11b5fde3c 100644 --- a/src/interfaces/jdbc/org/postgresql/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/Connection.java @@ -11,7 +11,7 @@ import org.postgresql.util.*; import org.postgresql.core.*; /** - * $Id: Connection.java,v 1.29 2001/09/10 15:07:05 momjian Exp $ + * $Id: Connection.java,v 1.30 2001/10/09 20:47:35 barry Exp $ * * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or * JDBC2 versions of the Connection class. @@ -130,104 +130,104 @@ public abstract class Connection // Now make the initial connection try { - pg_stream = new PG_Stream(host, port); + pg_stream = new PG_Stream(host, port); } catch (ConnectException cex) { - // Added by Peter Mount - // ConnectException is thrown when the connection cannot be made. - // we trap this an return a more meaningful message for the end user - throw new PSQLException ("postgresql.con.refused"); + // Added by Peter Mount + // ConnectException is thrown when the connection cannot be made. + // we trap this an return a more meaningful message for the end user + throw new PSQLException ("postgresql.con.refused"); } catch (IOException e) { - throw new PSQLException ("postgresql.con.failed",e); + throw new PSQLException ("postgresql.con.failed",e); } // Now we need to construct and send a startup packet try - { - // Ver 6.3 code - pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4); - pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2); - pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2); - pg_stream.Send(database.getBytes(),SM_DATABASE); - - // This last send includes the unused fields - pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY); - - // now flush the startup packets to the backend - pg_stream.flush(); - - // Now get the response from the backend, either an error message - // or an authentication request - int areq = -1; // must have a value here - do { - int beresp = pg_stream.ReceiveChar(); - switch(beresp) - { - case 'E': - // An error occured, so pass the error message to the - // user. - // - // The most common one to be thrown here is: - // "User authentication failed" - // + { + // Ver 6.3 code + pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4); + pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2); + pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2); + pg_stream.Send(database.getBytes(),SM_DATABASE); + + // This last send includes the unused fields + pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY); + + // now flush the startup packets to the backend + pg_stream.flush(); + + // Now get the response from the backend, either an error message + // or an authentication request + int areq = -1; // must have a value here + do { + int beresp = pg_stream.ReceiveChar(); + switch(beresp) + { + case 'E': + // An error occured, so pass the error message to the + // user. + // + // The most common one to be thrown here is: + // "User authentication failed" + // throw new SQLException(pg_stream.ReceiveString(encoding)); - case 'R': - // Get the type of request - areq = pg_stream.ReceiveIntegerR(4); - - // Get the password salt if there is one - if(areq == AUTH_REQ_CRYPT) { - byte[] rst = new byte[2]; - rst[0] = (byte)pg_stream.ReceiveChar(); - rst[1] = (byte)pg_stream.ReceiveChar(); - salt = new String(rst,0,2); - DriverManager.println("Salt="+salt); - } - - // now send the auth packet - switch(areq) - { - case AUTH_REQ_OK: - break; - - case AUTH_REQ_KRB4: - DriverManager.println("postgresql: KRB4"); - throw new PSQLException("postgresql.con.kerb4"); - - case AUTH_REQ_KRB5: - DriverManager.println("postgresql: KRB5"); - throw new PSQLException("postgresql.con.kerb5"); - - case AUTH_REQ_PASSWORD: - DriverManager.println("postgresql: PASSWORD"); - pg_stream.SendInteger(5+PG_PASSWORD.length(),4); - pg_stream.Send(PG_PASSWORD.getBytes()); - pg_stream.SendInteger(0,1); - pg_stream.flush(); - break; - - case AUTH_REQ_CRYPT: - DriverManager.println("postgresql: CRYPT"); - String crypted = UnixCrypt.crypt(salt,PG_PASSWORD); - pg_stream.SendInteger(5+crypted.length(),4); - pg_stream.Send(crypted.getBytes()); - pg_stream.SendInteger(0,1); - pg_stream.flush(); - break; - - default: - throw new PSQLException("postgresql.con.auth",new Integer(areq)); - } - break; - - default: - throw new PSQLException("postgresql.con.authfail"); - } - } while(areq != AUTH_REQ_OK); - - } catch (IOException e) { - throw new PSQLException("postgresql.con.failed",e); - } + case 'R': + // Get the type of request + areq = pg_stream.ReceiveIntegerR(4); + + // Get the password salt if there is one + if(areq == AUTH_REQ_CRYPT) { + byte[] rst = new byte[2]; + rst[0] = (byte)pg_stream.ReceiveChar(); + rst[1] = (byte)pg_stream.ReceiveChar(); + salt = new String(rst,0,2); + DriverManager.println("Salt="+salt); + } + + // now send the auth packet + switch(areq) + { + case AUTH_REQ_OK: + break; + + case AUTH_REQ_KRB4: + DriverManager.println("postgresql: KRB4"); + throw new PSQLException("postgresql.con.kerb4"); + + case AUTH_REQ_KRB5: + DriverManager.println("postgresql: KRB5"); + throw new PSQLException("postgresql.con.kerb5"); + + case AUTH_REQ_PASSWORD: + DriverManager.println("postgresql: PASSWORD"); + pg_stream.SendInteger(5+PG_PASSWORD.length(),4); + pg_stream.Send(PG_PASSWORD.getBytes()); + pg_stream.SendInteger(0,1); + pg_stream.flush(); + break; + + case AUTH_REQ_CRYPT: + DriverManager.println("postgresql: CRYPT"); + String crypted = UnixCrypt.crypt(salt,PG_PASSWORD); + pg_stream.SendInteger(5+crypted.length(),4); + pg_stream.Send(crypted.getBytes()); + pg_stream.SendInteger(0,1); + pg_stream.flush(); + break; + + default: + throw new PSQLException("postgresql.con.auth",new Integer(areq)); + } + break; + + default: + throw new PSQLException("postgresql.con.authfail"); + } + } while(areq != AUTH_REQ_OK); + + } catch (IOException e) { + throw new PSQLException("postgresql.con.failed",e); + } // As of protocol version 2.0, we should now receive the cancellation key and the pid @@ -237,8 +237,8 @@ public abstract class Connection pid = pg_stream.ReceiveInteger(4); ckey = pg_stream.ReceiveInteger(4); break; - case 'E': - case 'N': + case 'E': + case 'N': throw new SQLException(pg_stream.ReceiveString(encoding)); default: throw new PSQLException("postgresql.con.setup"); @@ -248,9 +248,9 @@ public abstract class Connection beresp = pg_stream.ReceiveChar(); switch(beresp) { case 'Z': - break; - case 'E': - case 'N': + break; + case 'E': + case 'N': throw new SQLException(pg_stream.ReceiveString(encoding)); default: throw new PSQLException("postgresql.con.setup"); @@ -264,16 +264,16 @@ public abstract class Connection // used, so we denote this with 'UNKNOWN'. final String encodingQuery = - "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end"; + "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end"; // Set datestyle and fetch db encoding in a single call, to avoid making // more than one round trip to the backend during connection startup. java.sql.ResultSet resultSet = - ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";"); + ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";"); if (! resultSet.next()) { - throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); + throw new PSQLException("postgresql.con.failed", "failed getting backend encoding"); } String version = resultSet.getString(1); dbVersionNumber = extractVersionNumber(version); @@ -299,28 +299,28 @@ public abstract class Connection */ public void addWarning(String msg) { - DriverManager.println(msg); - - // Add the warning to the chain - if(firstWarning!=null) - firstWarning.setNextWarning(new SQLWarning(msg)); - else - firstWarning = new SQLWarning(msg); - - // Now check for some specific messages - - // This is obsolete in 6.5, but I've left it in here so if we need to use this - // technique again, we'll know where to place it. - // - // This is generated by the SQL "show datestyle" - //if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) { - //// 13 is the length off "DateStyle is " - //msg = msg.substring(msg.indexOf("DateStyle is ")+13); - // - //for(int i=0;i0) { + //// 13 is the length off "DateStyle is " + //msg = msg.substring(msg.indexOf("DateStyle is ")+13); + // + //for(int i=0;iNote: setTransactionIsolation cannot be called while * in the middle of a transaction * @@ -855,32 +855,32 @@ public abstract class Connection * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel */ public void setTransactionIsolation(int level) throws SQLException { - //In 7.1 and later versions of the server it is possible using + //In 7.1 and later versions of the server it is possible using //the "set session" command to set this once for all future txns - //however in 7.0 and prior versions it is necessary to set it in + //however in 7.0 and prior versions it is necessary to set it in //each transaction, thus adding complexity below. //When we decide to drop support for servers older than 7.1 //this can be simplified isolationLevel = level; String isolationLevelSQL; - if (!haveMinimumServerVersion("7.1")) { - isolationLevelSQL = getIsolationLevelSQL(); - } else { - isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "; - switch(isolationLevel) { - case java.sql.Connection.TRANSACTION_READ_COMMITTED: - isolationLevelSQL += "READ COMMITTED"; - break; - case java.sql.Connection.TRANSACTION_SERIALIZABLE: - isolationLevelSQL += "SERIALIZABLE"; - break; - default: - throw new PSQLException("postgresql.con.isolevel", - new Integer(isolationLevel)); - } - } - ExecSQL(isolationLevelSQL); + if (!haveMinimumServerVersion("7.1")) { + isolationLevelSQL = getIsolationLevelSQL(); + } else { + isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "; + switch(isolationLevel) { + case java.sql.Connection.TRANSACTION_READ_COMMITTED: + isolationLevelSQL += "READ COMMITTED"; + break; + case java.sql.Connection.TRANSACTION_SERIALIZABLE: + isolationLevelSQL += "SERIALIZABLE"; + break; + default: + throw new PSQLException("postgresql.con.isolevel", + new Integer(isolationLevel)); + } + } + ExecSQL(isolationLevelSQL); } /** @@ -893,25 +893,25 @@ public abstract class Connection * servers are dropped */ protected String getIsolationLevelSQL() throws SQLException { - //7.1 and higher servers have a default specified so - //no additional SQL is required to set the isolation level - if (haveMinimumServerVersion("7.1")) { + //7.1 and higher servers have a default specified so + //no additional SQL is required to set the isolation level + if (haveMinimumServerVersion("7.1")) { return ""; } - StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL"); + StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL"); - switch(isolationLevel) { - case java.sql.Connection.TRANSACTION_READ_COMMITTED: - sb.append(" READ COMMITTED"); + switch(isolationLevel) { + case java.sql.Connection.TRANSACTION_READ_COMMITTED: + sb.append(" READ COMMITTED"); break; - case java.sql.Connection.TRANSACTION_SERIALIZABLE: - sb.append(" SERIALIZABLE"); + case java.sql.Connection.TRANSACTION_SERIALIZABLE: + sb.append(" SERIALIZABLE"); break; - default: - throw new PSQLException("postgresql.con.isolevel",new Integer(isolationLevel)); - } + default: + throw new PSQLException("postgresql.con.isolevel",new Integer(isolationLevel)); + } return sb.toString(); } @@ -936,7 +936,7 @@ public abstract class Connection */ public String getCatalog() throws SQLException { - return PG_DATABASE; + return PG_DATABASE; } /** @@ -949,7 +949,7 @@ public abstract class Connection */ public void finalize() throws Throwable { - close(); + close(); } private static String extractVersionNumber(String fullVersionString) @@ -963,7 +963,7 @@ public abstract class Connection * Get server version number */ public String getDBVersionNumber() { - return dbVersionNumber; + return dbVersionNumber; } public boolean haveMinimumServerVersion(String ver) throws SQLException @@ -1069,4 +1069,4 @@ public abstract class Connection } } - + diff --git a/src/interfaces/jdbc/org/postgresql/ResultSet.java b/src/interfaces/jdbc/org/postgresql/ResultSet.java index 8757d21c7e..3274b1eb38 100644 --- a/src/interfaces/jdbc/org/postgresql/ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/ResultSet.java @@ -18,6 +18,7 @@ public abstract class ResultSet protected Vector rows; // The results protected Field fields[]; // The field descriptions protected String status; // Status of the result + protected boolean binaryCursor = false; // is the data binary or Strings protected int updateCount; // How many rows did we get back? protected int insertOID; // The oid of an inserted row protected int current_row; // Our pointer to where we are at @@ -41,7 +42,7 @@ public abstract class ResultSet * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor) { this.connection = conn; this.fields = fields; @@ -51,6 +52,7 @@ public abstract class ResultSet this.insertOID = insertOID; this.this_row = null; this.current_row = -1; + this.binaryCursor = binaryCursor; } @@ -65,10 +67,10 @@ public abstract class ResultSet * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) - { - this(conn,fields,tuples,status,updateCount,0); - } + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) + { + this(conn,fields,tuples,status,updateCount,0,false); + } /** * We at times need to know if the resultSet we are working @@ -172,7 +174,7 @@ public abstract class ResultSet */ public int getInsertedOID() { - return insertOID; + return insertOID; } /** diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index e45dffc1da..318daa84f4 100644 --- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java +++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java @@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException; *

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.1 2001/09/06 03:58:59 momjian Exp $ + * $Id: QueryExecutor.java,v 1.2 2001/10/09 20:47:35 barry Exp $ */ public class QueryExecutor { @@ -24,24 +24,25 @@ public class QueryExecutor { private final org.postgresql.Connection connection; public QueryExecutor(String sql, - java.sql.Statement statement, - PG_Stream pg_stream, - org.postgresql.Connection connection) - throws SQLException + 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; + 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 int insert_oid = 0; @@ -52,84 +53,83 @@ public class QueryExecutor { */ public java.sql.ResultSet execute() throws SQLException { - int fqp = 0; - boolean hfr = false; - - 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 - throw new SQLException(pg_stream.ReceiveString(connection.getEncoding())); - 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)); - } - } - - return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid); - } + int fqp = 0; + boolean hfr = false; + + 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 + throw new SQLException(pg_stream.ReceiveString(connection.getEncoding())); + 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)); + } + } + 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); - } + 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); + } } /** @@ -138,11 +138,12 @@ public class QueryExecutor { * @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 (maxRows == 0 || tuples.size() < maxRows) - tuples.addElement(tuple); + 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); } /** @@ -150,38 +151,38 @@ public class QueryExecutor { */ 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 = Integer.parseInt(status.substring(1 + status.indexOf(' '), - status.lastIndexOf(' '))); - } - } catch (NumberFormatException nfe) { - throw new PSQLException("postgresql.con.fathom", status); - } + 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 = Integer.parseInt(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); - } + 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/jdbc1/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java index 814d693df5..dfdbb81827 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java @@ -17,7 +17,7 @@ import org.postgresql.largeobject.*; import org.postgresql.util.*; /** - * $Id: Connection.java,v 1.10 2001/09/10 15:07:05 momjian Exp $ + * $Id: Connection.java,v 1.11 2001/10/09 20:47:35 barry Exp $ * * A Connection represents a session with a specific database. Within the * context of a Connection, SQL statements are executed and results are @@ -131,10 +131,10 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co * 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,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, boolean binaryCursor) throws SQLException { // in jdbc1 stat is ignored. - return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn,fields,tuples,status,updateCount,insertOID); + return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java index eecce9c939..fe01d15e29 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java @@ -70,9 +70,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor) { - super(conn,fields,tuples,status,updateCount,insertOID); + super(conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } /** @@ -86,10 +86,10 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) - { - super(conn,fields,tuples,status,updateCount,0); - } + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) + { + super(conn,fields,tuples,status,updateCount,0,false); + } /** * A ResultSet is initially positioned before its first row, @@ -375,6 +375,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu if (columnIndex < 1 || columnIndex > fields.length) throw new PSQLException("postgresql.res.colrange"); + //If the data is already binary then just return it + if (binaryCursor) return this_row[columnIndex - 1]; + if (connection.haveMinimumCompatibleVersion("7.2")) { //Version 7.2 supports the bytea datatype for byte arrays return PGbytea.toBytes(getString(columnIndex)); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java index 9aa98cdbb6..91aaa2798a 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java @@ -17,7 +17,7 @@ import org.postgresql.largeobject.*; import org.postgresql.util.*; /** - * $Id: Connection.java,v 1.12 2001/09/10 15:07:05 momjian Exp $ + * $Id: Connection.java,v 1.13 2001/10/09 20:47:35 barry Exp $ * * A Connection represents a session with a specific database. Within the * context of a Connection, SQL statements are executed and results are @@ -204,16 +204,16 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co * 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, 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, 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); + return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } - return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn,fields,tuples,status,updateCount,insertOID); + return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } // ***************** @@ -296,9 +296,9 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co "date", "time", "abstime","timestamp", - "_bool", "_char", "_int2", "_int4", "_text", - "_oid", "_varchar", "_int8", "_float4", "_float8", - "_abstime", "_date", "_time", "_timestamp", "_numeric", + "_bool", "_char", "_int2", "_int4", "_text", + "_oid", "_varchar", "_int8", "_float4", "_float8", + "_abstime", "_date", "_time", "_timestamp", "_numeric", "_bytea" }; @@ -324,8 +324,8 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co Types.DATE, Types.TIME, 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, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY }; diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java index feec8d08c2..3d39f6461a 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java @@ -74,9 +74,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor) { - super(conn,fields,tuples,status,updateCount,insertOID); + super(conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } /** @@ -90,10 +90,10 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) - { - super(conn,fields,tuples,status,updateCount,0); - } + public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) + { + super(conn,fields,tuples,status,updateCount,0,false); + } /** * A ResultSet is initially positioned before its first row, @@ -313,6 +313,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu if (columnIndex < 1 || columnIndex > fields.length) throw new PSQLException("postgresql.res.colrange"); + //If the data is already binary then just return it + if (binaryCursor) return this_row[columnIndex - 1]; + if (connection.haveMinimumCompatibleVersion("7.2")) { //Version 7.2 supports the bytea datatype for byte arrays return PGbytea.toBytes(getString(columnIndex)); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java index 077c4b0ee2..12fec3bf7c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java @@ -40,9 +40,9 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public UpdateableResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID) + public UpdateableResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor) { - super(conn,fields,tuples,status,updateCount,insertOID); + super(conn,fields,tuples,status,updateCount,insertOID,binaryCursor); } /** @@ -56,10 +56,10 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet * @param updateCount the number of rows affected by the operation * @param cursor the positioned update/delete cursor name */ - public UpdateableResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) - { - super(conn,fields,tuples,status,updateCount,0); - } + // public UpdateableResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount) + // { + // super(conn,fields,tuples,status,updateCount,0,false); + //} public void cancelRowUpdates() throws SQLException { @@ -77,7 +77,7 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet { // New in 7.1 - The updateable ResultSet class will now return // CONCUR_UPDATEABLE. - return CONCUR_UPDATABLE; + return CONCUR_UPDATABLE; } public void insertRow() throws SQLException @@ -120,26 +120,26 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet } public void updateAsciiStream(int columnIndex, - java.io.InputStream x, - int length - ) throws SQLException + java.io.InputStream x, + int length + ) throws SQLException { // only sub-classes implement CONCUR_UPDATEABLE throw org.postgresql.Driver.notImplemented(); } public void updateBigDecimal(int columnIndex, - java.math.BigDecimal x - ) throws SQLException + java.math.BigDecimal x + ) throws SQLException { // only sub-classes implement CONCUR_UPDATEABLE throw org.postgresql.Driver.notImplemented(); } public void updateBinaryStream(int columnIndex, - java.io.InputStream x, - int length - ) throws SQLException + java.io.InputStream x, + int length + ) throws SQLException { // only sub-classes implement CONCUR_UPDATEABLE throw org.postgresql.Driver.notImplemented(); @@ -164,9 +164,9 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet } public void updateCharacterStream(int columnIndex, - java.io.Reader x, - int length - ) throws SQLException + java.io.Reader x, + int length + ) throws SQLException { // only sub-classes implement CONCUR_UPDATEABLE throw org.postgresql.Driver.notImplemented();