Web Feb 14 17:29:00 GMT 2001 peter@retep.org.uk

- Fixed bug in LargeObject & BlobOutputStream where the stream's output
          was not flushed when either the stream or the blob were closed.
        - Fixed PreparedStatement.setBinaryStream() where it ignored the length
This commit is contained in:
Peter Mount 2001-02-14 17:45:17 +00:00
parent c1abe85529
commit bb7b71826d
7 changed files with 224 additions and 8 deletions

View File

@ -1,3 +1,8 @@
Web Feb 14 17:29:00 GMT 2001 peter@retep.org.uk
- Fixed bug in LargeObject & BlobOutputStream where the stream's output
was not flushed when either the stream or the blob were closed.
- Fixed PreparedStatement.setBinaryStream() where it ignored the length
Tue Feb 13 16:33:00 GMT 2001 peter@retep.org.uk
- More TestCases implemented. Refined the test suite api's.
- Removed need for SimpleDateFormat in ResultSet.getDate() improving

View File

@ -3,7 +3,7 @@
build file to allow ant (http://jakarta.apache.org/ant/) to be used
to build the PostgreSQL JDBC Driver.
$Id: build.xml,v 1.5 2001/02/07 09:13:20 peter Exp $
$Id: build.xml,v 1.6 2001/02/14 17:45:13 peter Exp $
-->
@ -26,6 +26,7 @@
<property name="database" value="jdbc:postgresql:test" />
<property name="username" value="test" />
<property name="password" value="password" />
<property name="tablename" value="jdbctest" />
<property name="junit.ui" value="textui" />
<!--

View File

@ -431,9 +431,11 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
// 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) {
int p=0;
while(c>-1 && p<length) {
los.write(c);
c=x.read();
p++;
}
los.close();
} catch(IOException se) {

View File

@ -92,6 +92,7 @@ public class BlobOutputStream extends OutputStream {
*/
public void close() throws IOException {
try {
flush();
lo.close();
lo=null;
} catch(SQLException se) {

View File

@ -62,6 +62,10 @@ public class LargeObject
private int oid; // OID of this object
private int fd; // the descriptor of the open large object
private BlobOutputStream os; // The current output stream
private boolean closed=false; // true when we are closed
/**
* This opens a large object.
*
@ -100,9 +104,25 @@ public class LargeObject
*/
public void close() throws SQLException
{
FastpathArg args[] = new FastpathArg[1];
args[0] = new FastpathArg(fd);
fp.fastpath("lo_close",false,args); // true here as we dont care!!
if(!closed) {
// flush any open output streams
if(os!=null) {
try {
// we can't call os.close() otherwise we go into an infinite loop!
os.flush();
} catch(IOException ioe) {
throw new SQLException(ioe.getMessage());
} finally {
os=null;
}
}
// finally close
FastpathArg args[] = new FastpathArg[1];
args[0] = new FastpathArg(fd);
fp.fastpath("lo_close",false,args); // true here as we dont care!!
closed=true;
}
}
/**
@ -279,7 +299,9 @@ public class LargeObject
*/
public OutputStream getOutputStream() throws SQLException
{
return new BlobOutputStream(this);
if(os==null)
os = new BlobOutputStream(this);
return os;
}
}

View File

@ -207,13 +207,14 @@ public class JDBC2Tests extends TestSuite {
// MetaData
// Fastpath/LargeObject
// Other misc tests, based on previous problems users have had or specific
// features some applications require.
suite.addTestSuite(JBuilderTest.class);
suite.addTestSuite(MiscTest.class);
// Fastpath/LargeObject
suite.addTestSuite(BlobTest.class);
// That's all folks
return suite;
}

View File

@ -0,0 +1,184 @@
package org.postgresql.test.jdbc2;
import org.postgresql.test.JDBC2Tests;
import junit.framework.TestCase;
import java.io.*;
import java.sql.*;
import org.postgresql.largeobject.*;
/**
* $Id: BlobTest.java,v 1.1 2001/02/14 17:45:17 peter Exp $
*
* Some simple tests based on problems reported by users. Hopefully these will
* help prevent previous problems from re-occuring ;-)
*
*/
public class BlobTest extends TestCase {
public BlobTest(String name) {
super(name);
}
/**
* The table format used by this TestCase
*/
private static final String BLOB_TABLE_FMT = "id name,lo oid";
/**
* Tests one method of uploading a blob to the database
*/
public void testUploadBlob_LOOP() {
try {
Connection con = JDBC2Tests.openDB();
JDBC2Tests.createTable(con,BLOB_TABLE_FMT);
con.setAutoCommit(false);
assert(!con.getAutoCommit());
assert(uploadFile(con,"build.xml",LOOP)>0);
// Now compare the blob & the file. Note this actually tests the
// InputStream implementation!
assert(compareBlobs(con));
JDBC2Tests.closeDB(con);
} catch(Exception ex) {
assert(ex.getMessage(),false);
}
}
/**
* Tests one method of uploading a blob to the database
*/
public void testUploadBlob_NATIVE() {
try {
Connection con = JDBC2Tests.openDB();
JDBC2Tests.createTable(con,BLOB_TABLE_FMT);
con.setAutoCommit(false);
assert(!con.getAutoCommit());
assert(uploadFile(con,"build.xml",NATIVE_STREAM)>0);
// Now compare the blob & the file. Note this actually tests the
// InputStream implementation!
assert(compareBlobs(con));
JDBC2Tests.closeDB(con);
} catch(Exception ex) {
assert(ex.getMessage(),false);
}
}
private static final int LOOP = 0; // LargeObject API using loop
private static final int NATIVE_STREAM = 1; // LargeObject API using OutputStream
private static final int JDBC_STREAM = 2; // JDBC API using OutputStream
/**
* Helper - uploads a file into a blob using old style methods. We use this
* because it always works, and we can use it as a base to test the new
* methods.
*/
private int uploadFile(Connection con,String file,int method) throws Exception {
LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
FileInputStream fis = new FileInputStream(file);
int oid = lom.create(LargeObjectManager.READWRITE);
LargeObject blob = lom.open(oid);
int s,t;
byte buf[];
OutputStream os;
switch(method)
{
case LOOP:
buf = new byte[2048];
t=0;
while((s=fis.read(buf,0,buf.length))>0) {
t+=s;
blob.write(buf,0,s);
}
break;
case NATIVE_STREAM:
os = blob.getOutputStream();
s= fis.read();
while(s>-1) {
os.write(s);
s=fis.read();
}
os.close();
break;
case JDBC_STREAM:
File f = new File(file);
PreparedStatement ps = con.prepareStatement(JDBC2Tests.insert("?"));
ps.setBinaryStream(1,fis,(int) f.length());
ps.execute();
break;
default:
assert("Unknown method in uploadFile",false);
}
blob.close();
fis.close();
// Insert into the table
Statement st = con.createStatement();
st.executeUpdate(JDBC2Tests.insert("id,lo","'"+file+"',"+oid));
con.commit();
st.close();
return oid;
}
/**
* Helper - compares the blobs in a table with a local file. Note this alone
* tests the InputStream methods!
*/
private boolean compareBlobs(Connection con) throws Exception {
boolean result=true;
LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(JDBC2Tests.select("id,lo"));
assert(rs!=null);
while(rs.next()) {
String file = rs.getString(1);
int oid = rs.getInt(2);
FileInputStream fis = new FileInputStream(file);
LargeObject blob = lom.open(oid);
InputStream bis = blob.getInputStream();
int f=fis.read();
int b=bis.read();
int c=0;
while(f>=0 && b>=0 & result) {
result=(f==b);
f=fis.read();
b=bis.read();
c++;
}
result=result && f==-1 && b==-1;
if(!result)
System.out.println("\nBlob compare failed at "+c+" of "+blob.size());
blob.close();
fis.close();
}
rs.close();
st.close();
return result;
}
}