mirror of
https://github.com/postgres/postgres.git
synced 2025-05-22 00:02:02 -04: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
|
Tue Feb 13 16:33:00 GMT 2001 peter@retep.org.uk
|
||||||
- More TestCases implemented. Refined the test suite api's.
|
- More TestCases implemented. Refined the test suite api's.
|
||||||
- Removed need for SimpleDateFormat in ResultSet.getDate() improving
|
- 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
|
build file to allow ant (http://jakarta.apache.org/ant/) to be used
|
||||||
to build the PostgreSQL JDBC Driver.
|
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="database" value="jdbc:postgresql:test" />
|
||||||
<property name="username" value="test" />
|
<property name="username" value="test" />
|
||||||
<property name="password" value="password" />
|
<property name="password" value="password" />
|
||||||
|
<property name="tablename" value="jdbctest" />
|
||||||
<property name="junit.ui" value="textui" />
|
<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
|
// is buffered internally anyhow, so there would be no performance
|
||||||
// boost gained, if anything it would be worse!
|
// boost gained, if anything it would be worse!
|
||||||
int c=x.read();
|
int c=x.read();
|
||||||
while(c>-1) {
|
int p=0;
|
||||||
|
while(c>-1 && p<length) {
|
||||||
los.write(c);
|
los.write(c);
|
||||||
c=x.read();
|
c=x.read();
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
los.close();
|
los.close();
|
||||||
} catch(IOException se) {
|
} catch(IOException se) {
|
||||||
|
@ -92,6 +92,7 @@ public class BlobOutputStream extends OutputStream {
|
|||||||
*/
|
*/
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
try {
|
||||||
|
flush();
|
||||||
lo.close();
|
lo.close();
|
||||||
lo=null;
|
lo=null;
|
||||||
} catch(SQLException se) {
|
} catch(SQLException se) {
|
||||||
|
@ -62,6 +62,10 @@ public class LargeObject
|
|||||||
private int oid; // OID of this object
|
private int oid; // OID of this object
|
||||||
private int fd; // the descriptor of the open large 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.
|
* This opens a large object.
|
||||||
*
|
*
|
||||||
@ -100,9 +104,25 @@ public class LargeObject
|
|||||||
*/
|
*/
|
||||||
public void close() throws SQLException
|
public void close() throws SQLException
|
||||||
{
|
{
|
||||||
|
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];
|
FastpathArg args[] = new FastpathArg[1];
|
||||||
args[0] = new FastpathArg(fd);
|
args[0] = new FastpathArg(fd);
|
||||||
fp.fastpath("lo_close",false,args); // true here as we dont care!!
|
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
|
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
|
// MetaData
|
||||||
|
|
||||||
// Fastpath/LargeObject
|
|
||||||
|
|
||||||
// Other misc tests, based on previous problems users have had or specific
|
// Other misc tests, based on previous problems users have had or specific
|
||||||
// features some applications require.
|
// features some applications require.
|
||||||
suite.addTestSuite(JBuilderTest.class);
|
suite.addTestSuite(JBuilderTest.class);
|
||||||
suite.addTestSuite(MiscTest.class);
|
suite.addTestSuite(MiscTest.class);
|
||||||
|
|
||||||
|
// Fastpath/LargeObject
|
||||||
|
suite.addTestSuite(BlobTest.class);
|
||||||
|
|
||||||
// That's all folks
|
// That's all folks
|
||||||
return suite;
|
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…
x
Reference in New Issue
Block a user