diff --git a/src/interfaces/jdbc/CHANGELOG b/src/interfaces/jdbc/CHANGELOG
index b02e4d3756a95a907ea771339d63bf51d9e225f4..53855073033f9973d63186687fe88f4be02dfc5f 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 e95c646f5d27c701fe8a9c863fb1368bd3fe6a46..5f09ed887bce26563adaebdc8251f19470308861 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 a0f1d0713c4e18cf718353aec49eec3190e22d52..93a175267dfcb136bd35cf04171677c26f209b10 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 0ac435a78fd80b457f602941564d7c5e9cb17304..3cba1c3702a52a98ae075a9f70c4a1c7f7288c1c 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 c73301d131814e978f1ba8a48a5e6d44c38fe9fd..20afda578288d6c2a0f0c0624122871ee8aa43e5 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 6aac14b4b1cd71cb02a65c63f6b47c37e6ef6c0c..37624f528da26c3d787ed6c4c171cbd43ce76cf6 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 0000000000000000000000000000000000000000..28a61044cf6a865e9ac451dc365f2062787b76d8
--- /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;
+  }
+}