Commit 839b9bc0 authored by Barry Lind's avatar Barry Lind

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
parent ffb8f738
......@@ -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;
}
/**
......
......@@ -13,7 +13,7 @@ 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.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);
}
}
}
......@@ -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);
}
......
......@@ -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));
......
......@@ -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
};
......
......@@ -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));
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment