mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
Tue Jan 30 22:24:00 GMT 2001 peter@retep.org.uk
- Fixed bug where Statement.setMaxRows() was a global setting. Now limited to just itself. - Changed LargeObject.read(byte[],int,int) to return the actual number of bytes read (used to be void). - LargeObject now supports InputStream's! - PreparedStatement.setBinaryStream() now works! - ResultSet.getBinaryStream() now returns an InputStream that doesn't copy the blob into memory first! - Connection.isClosed() now tests to see if the connection is still alive rather than if it thinks it's alive.
This commit is contained in:
parent
dca0762efc
commit
8439a83d84
@ -1,3 +1,14 @@
|
|||||||
|
Tue Jan 30 22:24:00 GMT 2001 peter@retep.org.uk
|
||||||
|
- Fixed bug where Statement.setMaxRows() was a global setting. Now
|
||||||
|
limited to just itself.
|
||||||
|
- Changed LargeObject.read(byte[],int,int) to return the actual number
|
||||||
|
of bytes read (used to be void).
|
||||||
|
- LargeObject now supports InputStream's!
|
||||||
|
- PreparedStatement.setBinaryStream() now works!
|
||||||
|
- ResultSet.getBinaryStream() now returns an InputStream that doesn't
|
||||||
|
copy the blob into memory first!
|
||||||
|
- Connection.isClosed() now tests to see if the connection is still alive
|
||||||
|
rather than if it thinks it's alive.
|
||||||
Thu Jan 25 09:11:00 GMT 2001 peter@retep.org.uk
|
Thu Jan 25 09:11:00 GMT 2001 peter@retep.org.uk
|
||||||
- Added an alternative constructor to PGSQLException so that debugging
|
- Added an alternative constructor to PGSQLException so that debugging
|
||||||
some more osteric bugs is easier. If only 1 arg is supplied and it's
|
some more osteric bugs is easier. If only 1 arg is supplied and it's
|
||||||
|
@ -6,7 +6,7 @@ import java.text.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* $Id: basic.java,v 1.5 2000/06/06 11:05:57 peter Exp $
|
* $Id: basic.java,v 1.6 2001/01/31 08:26:01 peter Exp $
|
||||||
*
|
*
|
||||||
* This example tests the basic components of the JDBC driver, and shows
|
* This example tests the basic components of the JDBC driver, and shows
|
||||||
* how even the simplest of queries can be implemented.
|
* how even the simplest of queries can be implemented.
|
||||||
@ -84,8 +84,9 @@ public class basic
|
|||||||
st.executeUpdate("insert into basic values (3,1)");
|
st.executeUpdate("insert into basic values (3,1)");
|
||||||
|
|
||||||
// This shows how to get the oid of a just inserted row
|
// This shows how to get the oid of a just inserted row
|
||||||
|
// updated for 7.1
|
||||||
st.executeUpdate("insert into basic values (4,1)");
|
st.executeUpdate("insert into basic values (4,1)");
|
||||||
int insertedOID = ((org.postgresql.ResultSet)st.getResultSet()).getInsertedOID();
|
int insertedOID = ((org.postgresql.jdbc2.Statement)st).getInsertedOID();
|
||||||
System.out.println("Inserted row with oid "+insertedOID);
|
System.out.println("Inserted row with oid "+insertedOID);
|
||||||
|
|
||||||
// Now change the value of b from 1 to 8
|
// Now change the value of b from 1 to 8
|
||||||
@ -151,6 +152,17 @@ public class basic
|
|||||||
rs.close(); // again, you must close the result when done
|
rs.close(); // again, you must close the result when done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now test maxrows by setting it to 3 rows
|
||||||
|
st.setMaxRows(3);
|
||||||
|
System.out.println("performing a query limited to "+st.getMaxRows());
|
||||||
|
rs = st.executeQuery("select a, b from basic");
|
||||||
|
while(rs.next()) {
|
||||||
|
int a = rs.getInt("a"); // This shows how to get the value by name
|
||||||
|
int b = rs.getInt(2); // This shows how to get the value by column
|
||||||
|
System.out.println(" a="+a+" b="+b);
|
||||||
|
}
|
||||||
|
rs.close(); // again, you must close the result when done
|
||||||
|
|
||||||
// The last thing to do is to drop the table. This is done in the
|
// The last thing to do is to drop the table. This is done in the
|
||||||
// cleanup() method.
|
// cleanup() method.
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<property category="sys" name="CheckStable" value="1" />
|
<property category="sys" name="CheckStable" value="1" />
|
||||||
<property category="sys" name="Company" value="" />
|
<property category="sys" name="Company" value="" />
|
||||||
<property category="sys" name="Copyright" value="Copyright (c) 2001" />
|
<property category="sys" name="Copyright" value="Copyright (c) 2001" />
|
||||||
<property category="sys" name="DefaultPackage" value="org.postgresql.core" />
|
<property category="sys" name="DefaultPackage" value="org.postgresql.largeobject" />
|
||||||
<property category="sys" name="Description" value="" />
|
<property category="sys" name="Description" value="" />
|
||||||
<property category="sys" name="DocPath" value="doc" />
|
<property category="sys" name="DocPath" value="doc" />
|
||||||
<property category="sys" name="ExcludeClassEnabled" value="0" />
|
<property category="sys" name="ExcludeClassEnabled" value="0" />
|
||||||
|
@ -10,7 +10,7 @@ import org.postgresql.largeobject.*;
|
|||||||
import org.postgresql.util.*;
|
import org.postgresql.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $Id: Connection.java,v 1.13 2001/01/18 17:37:12 peter Exp $
|
* $Id: Connection.java,v 1.14 2001/01/31 08:26:01 peter Exp $
|
||||||
*
|
*
|
||||||
* This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
|
* This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
|
||||||
* JDBC2 versions of the Connection class.
|
* JDBC2 versions of the Connection class.
|
||||||
@ -22,7 +22,7 @@ public abstract class Connection
|
|||||||
public PG_Stream pg_stream;
|
public PG_Stream pg_stream;
|
||||||
|
|
||||||
// This is set by org.postgresql.Statement.setMaxRows()
|
// This is set by org.postgresql.Statement.setMaxRows()
|
||||||
public int maxrows = 0; // maximum no. of rows; 0 = unlimited
|
//public int maxrows = 0; // maximum no. of rows; 0 = unlimited
|
||||||
|
|
||||||
private String PG_HOST;
|
private String PG_HOST;
|
||||||
private int PG_PORT;
|
private int PG_PORT;
|
||||||
@ -414,6 +414,11 @@ public abstract class Connection
|
|||||||
*/
|
*/
|
||||||
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.
|
// added Oct 7 1998 to give us thread safety.
|
||||||
synchronized(pg_stream) {
|
synchronized(pg_stream) {
|
||||||
// Deallocate all resources in the stream associated
|
// Deallocate all resources in the stream associated
|
||||||
|
@ -29,6 +29,7 @@ public class Statement implements java.sql.Statement
|
|||||||
SQLWarning warnings = null; // The warnings chain.
|
SQLWarning warnings = null; // The warnings chain.
|
||||||
int timeout = 0; // The timeout for a query (not used)
|
int timeout = 0; // The timeout for a query (not used)
|
||||||
boolean escapeProcessing = true;// escape processing flag
|
boolean escapeProcessing = true;// escape processing flag
|
||||||
|
int maxrows=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a Statement. It simply sets the connection
|
* Constructor for a Statement. It simply sets the connection
|
||||||
@ -129,7 +130,7 @@ public class Statement implements java.sql.Statement
|
|||||||
*/
|
*/
|
||||||
public int getMaxRows() throws SQLException
|
public int getMaxRows() throws SQLException
|
||||||
{
|
{
|
||||||
return connection.maxrows;
|
return maxrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,7 +142,7 @@ public class Statement implements java.sql.Statement
|
|||||||
*/
|
*/
|
||||||
public void setMaxRows(int max) throws SQLException
|
public void setMaxRows(int max) throws SQLException
|
||||||
{
|
{
|
||||||
connection.maxrows = max;
|
maxrows = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
|
|||||||
import org.postgresql.util.*;
|
import org.postgresql.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $Id: Connection.java,v 1.5 2001/01/18 17:37:14 peter Exp $
|
* $Id: Connection.java,v 1.6 2001/01/31 08:26:02 peter Exp $
|
||||||
*
|
*
|
||||||
* A Connection represents a session with a specific database. Within the
|
* A Connection represents a session with a specific database. Within the
|
||||||
* context of a Connection, SQL statements are executed and results are
|
* context of a Connection, SQL statements are executed and results are
|
||||||
@ -265,7 +265,27 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
|
|||||||
*/
|
*/
|
||||||
public boolean isClosed() throws SQLException
|
public boolean isClosed() throws SQLException
|
||||||
{
|
{
|
||||||
return (pg_stream == null);
|
// If the stream is gone, then close() was called
|
||||||
|
if(pg_stream == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// ok, test the connection
|
||||||
|
try {
|
||||||
|
// by sending an empty query. If we are dead, then an SQLException should
|
||||||
|
// be thrown
|
||||||
|
java.sql.ResultSet rs = ExecSQL(" ");
|
||||||
|
if(rs!=null)
|
||||||
|
rs.close();
|
||||||
|
|
||||||
|
// By now, we must be alive
|
||||||
|
return false;
|
||||||
|
} catch(SQLException se) {
|
||||||
|
// Why throw an SQLException as this may fail without throwing one,
|
||||||
|
// ie isClosed() is called incase the connection has died, and we don't
|
||||||
|
// want to find out by an Exception, so instead we return true, as its
|
||||||
|
// most likely why it was thrown in the first place.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -418,7 +418,25 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
|
|||||||
*/
|
*/
|
||||||
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
|
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
|
||||||
{
|
{
|
||||||
throw new PSQLException("postgresql.prep.is");
|
LargeObjectManager lom = connection.getLargeObjectAPI();
|
||||||
|
int oid = lom.create();
|
||||||
|
LargeObject lob = lom.open(oid);
|
||||||
|
OutputStream los = lob.getOutputStream();
|
||||||
|
try {
|
||||||
|
// could be buffered, but then the OutputStream returned by LargeObject
|
||||||
|
// is buffered internally anyhow, so there would be no performance
|
||||||
|
// boost gained, if anything it would be worse!
|
||||||
|
int c=x.read();
|
||||||
|
while(c>-1) {
|
||||||
|
los.write(c);
|
||||||
|
c=x.read();
|
||||||
|
}
|
||||||
|
los.close();
|
||||||
|
} catch(IOException se) {
|
||||||
|
throw new PSQLException("postgresql.prep.is",se);
|
||||||
|
}
|
||||||
|
// lob is closed by the stream so don't call lob.close()
|
||||||
|
setInt(parameterIndex,oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,6 +581,15 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
|
|||||||
*/
|
*/
|
||||||
public InputStream getBinaryStream(int columnIndex) throws SQLException
|
public InputStream getBinaryStream(int columnIndex) throws SQLException
|
||||||
{
|
{
|
||||||
|
// New in 7.1 Handle OID's as BLOBS so return the input stream
|
||||||
|
if(!wasNullFlag)
|
||||||
|
if( fields[columnIndex - 1].getOID() == 26) {
|
||||||
|
LargeObjectManager lom = connection.getLargeObjectAPI();
|
||||||
|
LargeObject lob = lom.open(getInt(columnIndex));
|
||||||
|
return lob.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not an OID so fake the stream
|
||||||
byte b[] = getBytes(columnIndex);
|
byte b[] = getBytes(columnIndex);
|
||||||
|
|
||||||
if (b != null)
|
if (b != null)
|
||||||
|
@ -32,6 +32,7 @@ public class Statement implements java.sql.Statement
|
|||||||
private Vector batch=null;
|
private Vector batch=null;
|
||||||
int resultsettype; // the resultset type to return
|
int resultsettype; // the resultset type to return
|
||||||
int concurrency; // is it updateable or not?
|
int concurrency; // is it updateable or not?
|
||||||
|
int maxrows=0; // the maximum number of rows to return 0=unlimited
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a Statement. It simply sets the connection
|
* Constructor for a Statement. It simply sets the connection
|
||||||
@ -134,7 +135,7 @@ public class Statement implements java.sql.Statement
|
|||||||
*/
|
*/
|
||||||
public int getMaxRows() throws SQLException
|
public int getMaxRows() throws SQLException
|
||||||
{
|
{
|
||||||
return connection.maxrows;
|
return maxrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +147,7 @@ public class Statement implements java.sql.Statement
|
|||||||
*/
|
*/
|
||||||
public void setMaxRows(int max) throws SQLException
|
public void setMaxRows(int max) throws SQLException
|
||||||
{
|
{
|
||||||
connection.maxrows = max;
|
maxrows = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,7 +275,8 @@ public class Statement implements java.sql.Statement
|
|||||||
if(escapeProcessing)
|
if(escapeProcessing)
|
||||||
sql=connection.EscapeSQL(sql);
|
sql=connection.EscapeSQL(sql);
|
||||||
|
|
||||||
result = connection.ExecSQL(sql);
|
// New in 7.1, pass Statement so that ExecSQL can customise to it
|
||||||
|
result = connection.ExecSQL(sql,this);
|
||||||
|
|
||||||
// New in 7.1, required for ResultSet.getStatement() to work
|
// New in 7.1, required for ResultSet.getStatement() to work
|
||||||
((org.postgresql.jdbc2.ResultSet)result).setStatement(this);
|
((org.postgresql.jdbc2.ResultSet)result).setStatement(this);
|
||||||
@ -388,11 +390,6 @@ public class Statement implements java.sql.Statement
|
|||||||
throw org.postgresql.Driver.notImplemented();
|
throw org.postgresql.Driver.notImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
//public int getKeysetSize() throws SQLException
|
|
||||||
//{
|
|
||||||
// throw org.postgresql.Driver.notImplemented();
|
|
||||||
//}
|
|
||||||
|
|
||||||
public int getResultSetConcurrency() throws SQLException
|
public int getResultSetConcurrency() throws SQLException
|
||||||
{
|
{
|
||||||
// new in 7.1
|
// new in 7.1
|
||||||
@ -415,11 +412,6 @@ public class Statement implements java.sql.Statement
|
|||||||
throw org.postgresql.Driver.notImplemented();
|
throw org.postgresql.Driver.notImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
//public void setKeysetSize(int keys) throws SQLException
|
|
||||||
//{
|
|
||||||
// throw org.postgresql.Driver.notImplemented();
|
|
||||||
//}
|
|
||||||
|
|
||||||
public void setResultSetConcurrency(int value) throws SQLException
|
public void setResultSetConcurrency(int value) throws SQLException
|
||||||
{
|
{
|
||||||
concurrency=value;
|
concurrency=value;
|
||||||
@ -430,4 +422,17 @@ public class Statement implements java.sql.Statement
|
|||||||
resultsettype=value;
|
resultsettype=value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New in 7.1: Returns the Last inserted oid. This should be used, rather
|
||||||
|
* than the old method using getResultSet, which for executeUpdate returns
|
||||||
|
* null.
|
||||||
|
* @return OID of last insert
|
||||||
|
*/
|
||||||
|
public int getInsertedOID() throws SQLException
|
||||||
|
{
|
||||||
|
if(result!=null)
|
||||||
|
return ((org.postgresql.ResultSet)result).getInsertedOID();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,156 @@
|
|||||||
|
package org.postgresql.largeobject;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an initial implementation of an InputStream from a large object.
|
||||||
|
* For now, the bare minimum is implemented. Later (after 7.1) we will overide
|
||||||
|
* the other read methods to optimise them.
|
||||||
|
*/
|
||||||
|
public class BlobInputStream extends InputStream {
|
||||||
|
/**
|
||||||
|
* The parent LargeObject
|
||||||
|
*/
|
||||||
|
private LargeObject lo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer used to improve performance
|
||||||
|
*/
|
||||||
|
private byte[] buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position within buffer
|
||||||
|
*/
|
||||||
|
private int bpos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer size
|
||||||
|
*/
|
||||||
|
private int bsize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mark position
|
||||||
|
*/
|
||||||
|
private int mpos=0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lo LargeObject to read from
|
||||||
|
*/
|
||||||
|
public BlobInputStream(LargeObject lo) {
|
||||||
|
this(lo,1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lo LargeObject to read from
|
||||||
|
* @param bsize buffer size
|
||||||
|
*/
|
||||||
|
public BlobInputStream(LargeObject lo,int bsize) {
|
||||||
|
this.lo=lo;
|
||||||
|
buffer=null;
|
||||||
|
bpos=0;
|
||||||
|
this.bsize=bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum required to implement input stream
|
||||||
|
*/
|
||||||
|
public int read() throws java.io.IOException {
|
||||||
|
try {
|
||||||
|
if(buffer==null || bpos>=buffer.length) {
|
||||||
|
buffer=lo.read(bsize);
|
||||||
|
bpos=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle EOF
|
||||||
|
if(bpos>=buffer.length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (int) buffer[bpos++];
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this input stream and releases any system resources associated
|
||||||
|
* with the stream.
|
||||||
|
*
|
||||||
|
* <p> The <code>close</code> method of <code>InputStream</code> does
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
try {
|
||||||
|
lo.close();
|
||||||
|
lo=null;
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the current position in this input stream. A subsequent call to
|
||||||
|
* the <code>reset</code> method repositions this stream at the last marked
|
||||||
|
* position so that subsequent reads re-read the same bytes.
|
||||||
|
*
|
||||||
|
* <p> The <code>readlimit</code> arguments tells this input stream to
|
||||||
|
* allow that many bytes to be read before the mark position gets
|
||||||
|
* invalidated.
|
||||||
|
*
|
||||||
|
* <p> The general contract of <code>mark</code> is that, if the method
|
||||||
|
* <code>markSupported</code> returns <code>true</code>, the stream somehow
|
||||||
|
* remembers all the bytes read after the call to <code>mark</code> and
|
||||||
|
* stands ready to supply those same bytes again if and whenever the method
|
||||||
|
* <code>reset</code> is called. However, the stream is not required to
|
||||||
|
* remember any data at all if more than <code>readlimit</code> bytes are
|
||||||
|
* read from the stream before <code>reset</code> is called.
|
||||||
|
*
|
||||||
|
* <p> The <code>mark</code> method of <code>InputStream</code> does
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
|
* @param readlimit the maximum limit of bytes that can be read before
|
||||||
|
* the mark position becomes invalid.
|
||||||
|
* @see java.io.InputStream#reset()
|
||||||
|
*/
|
||||||
|
public synchronized void mark(int readlimit) {
|
||||||
|
try {
|
||||||
|
mpos=lo.tell();
|
||||||
|
} catch(SQLException se) {
|
||||||
|
//throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repositions this stream to the position at the time the
|
||||||
|
* <code>mark</code> method was last called on this input stream.
|
||||||
|
* NB: If mark is not called we move to the begining.
|
||||||
|
* @see java.io.InputStream#mark(int)
|
||||||
|
* @see java.io.IOException
|
||||||
|
*/
|
||||||
|
public synchronized void reset() throws IOException {
|
||||||
|
try {
|
||||||
|
lo.seek(mpos);
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if this input stream supports the <code>mark</code> and
|
||||||
|
* <code>reset</code> methods. The <code>markSupported</code> method of
|
||||||
|
* <code>InputStream</code> returns <code>false</code>.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if this true type supports the mark and reset
|
||||||
|
* method; <code>false</code> otherwise.
|
||||||
|
* @see java.io.InputStream#mark(int)
|
||||||
|
* @see java.io.InputStream#reset()
|
||||||
|
*/
|
||||||
|
public boolean markSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
package org.postgresql.largeobject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implements a basic output stream that writes to a LargeObject
|
||||||
|
*/
|
||||||
|
public class BlobOutputStream extends OutputStream {
|
||||||
|
/**
|
||||||
|
* The parent LargeObject
|
||||||
|
*/
|
||||||
|
private LargeObject lo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer
|
||||||
|
*/
|
||||||
|
private byte buf[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the buffer (default 1K)
|
||||||
|
*/
|
||||||
|
private int bsize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position within the buffer
|
||||||
|
*/
|
||||||
|
private int bpos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an OutputStream to a large object
|
||||||
|
* @param lo LargeObject
|
||||||
|
*/
|
||||||
|
public BlobOutputStream(LargeObject lo) {
|
||||||
|
this(lo,1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an OutputStream to a large object
|
||||||
|
* @param lo LargeObject
|
||||||
|
* @param bsize The size of the buffer used to improve performance
|
||||||
|
*/
|
||||||
|
public BlobOutputStream(LargeObject lo,int bsize) {
|
||||||
|
this.lo=lo;
|
||||||
|
this.bsize=bsize;
|
||||||
|
buf=new byte[bsize];
|
||||||
|
bpos=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) throws java.io.IOException {
|
||||||
|
try {
|
||||||
|
if(bpos>=bsize) {
|
||||||
|
lo.write(buf);
|
||||||
|
bpos=0;
|
||||||
|
}
|
||||||
|
buf[bpos++]=(byte)b;
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes this output stream and forces any buffered output bytes
|
||||||
|
* to be written out. The general contract of <code>flush</code> is
|
||||||
|
* that calling it is an indication that, if any bytes previously
|
||||||
|
* written have been buffered by the implementation of the output
|
||||||
|
* stream, such bytes should immediately be written to their
|
||||||
|
* intended destination.
|
||||||
|
*
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public void flush() throws IOException {
|
||||||
|
try {
|
||||||
|
if(bpos>0)
|
||||||
|
lo.write(buf,0,bpos);
|
||||||
|
bpos=0;
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this output stream and releases any system resources
|
||||||
|
* associated with this stream. The general contract of <code>close</code>
|
||||||
|
* is that it closes the output stream. A closed stream cannot perform
|
||||||
|
* output operations and cannot be reopened.
|
||||||
|
* <p>
|
||||||
|
* The <code>close</code> method of <code>OutputStream</code> does nothing.
|
||||||
|
*
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
try {
|
||||||
|
lo.close();
|
||||||
|
lo=null;
|
||||||
|
} catch(SQLException se) {
|
||||||
|
throw new IOException(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -152,11 +152,16 @@ public class LargeObject
|
|||||||
* @param buf destination array
|
* @param buf destination array
|
||||||
* @param off offset within array
|
* @param off offset within array
|
||||||
* @param len number of bytes to read
|
* @param len number of bytes to read
|
||||||
|
* @return the number of bytes actually read
|
||||||
* @exception SQLException if a database-access error occurs.
|
* @exception SQLException if a database-access error occurs.
|
||||||
*/
|
*/
|
||||||
public void read(byte buf[],int off,int len) throws SQLException
|
public int read(byte buf[],int off,int len) throws SQLException
|
||||||
{
|
{
|
||||||
System.arraycopy(read(len),0,buf,off,len);
|
byte b[] = read(len);
|
||||||
|
if(b.length<len)
|
||||||
|
len=b.length;
|
||||||
|
System.arraycopy(b,0,buf,off,len);
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,7 +266,7 @@ public class LargeObject
|
|||||||
*/
|
*/
|
||||||
public InputStream getInputStream() throws SQLException
|
public InputStream getInputStream() throws SQLException
|
||||||
{
|
{
|
||||||
throw org.postgresql.Driver.notImplemented();
|
return new BlobInputStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,6 +279,7 @@ public class LargeObject
|
|||||||
*/
|
*/
|
||||||
public OutputStream getOutputStream() throws SQLException
|
public OutputStream getOutputStream() throws SQLException
|
||||||
{
|
{
|
||||||
throw org.postgresql.Driver.notImplemented();
|
return new BlobOutputStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user