aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Mount <peter@retep.org.uk>2001-02-14 17:45:17 +0000
committerPeter Mount <peter@retep.org.uk>2001-02-14 17:45:17 +0000
commitbb7b71826d7a32752ace2f4574752a401fb7fa0f (patch)
treee273ace65b4d32e51e57d481c1be5099d7f3d4df /src
parentc1abe85529da1cd995896fb88492d353eafbfc8d (diff)
downloadpostgresql-bb7b71826d7a32752ace2f4574752a401fb7fa0f.tar.gz
postgresql-bb7b71826d7a32752ace2f4574752a401fb7fa0f.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/jdbc/CHANGELOG5
-rw-r--r--src/interfaces/jdbc/build.xml3
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java4
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java1
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java30
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java5
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java184
7 files changed, 224 insertions, 8 deletions
diff --git a/src/interfaces/jdbc/CHANGELOG b/src/interfaces/jdbc/CHANGELOG
index b02e4d3756a..53855073033 100644
--- a/src/interfaces/jdbc/CHANGELOG
+++ b/src/interfaces/jdbc/CHANGELOG
@@ -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
diff --git a/src/interfaces/jdbc/build.xml b/src/interfaces/jdbc/build.xml
index e95c646f5d2..5f09ed887bc 100644
--- a/src/interfaces/jdbc/build.xml
+++ b/src/interfaces/jdbc/build.xml
@@ -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" />
<!--
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
index a0f1d0713c4..93a175267df 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
@@ -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) {
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java b/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
index 0ac435a78fd..3cba1c3702a 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
@@ -92,6 +92,7 @@ public class BlobOutputStream extends OutputStream {
*/
public void close() throws IOException {
try {
+ flush();
lo.close();
lo=null;
} catch(SQLException se) {
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
index c73301d1318..20afda57828 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
@@ -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;
}
}
diff --git a/src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java b/src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java
index 6aac14b4b1c..37624f528da 100644
--- a/src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java
+++ b/src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java
@@ -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;
}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
new file mode 100644
index 00000000000..28a61044cf6
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
@@ -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;
+ }
+}