mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-18 18:44:06 +08:00
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:
parent
c1abe85529
commit
bb7b71826d
@ -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
|
||||
|
@ -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" />
|
||||
|
||||
<!--
|
||||
|
@ -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) {
|
||||
|
@ -92,6 +92,7 @@ public class BlobOutputStream extends OutputStream {
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
flush();
|
||||
lo.close();
|
||||
lo=null;
|
||||
} catch(SQLException se) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
184
src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
Normal file
184
src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user