I just looked into ClobOutputStream.java and it seems like it could have a similar problem. I plan to extend the test, so that it tests both write(b[], int, int) and write(int) methods for blobs and clobs. If the test happens to fail for any of these methods, I think we could just extend the fix.

Fernanda


Satheesh Bandaram wrote:

Thanks for the patch.. I was wondering if similar problem exists if write(int) method is used, instead of write(b[], int, int) method. It seems the offset is not incremented in this case either. Looking at ClobOutputStream.java, does this need patching too?

If the problem still remains for other API calls, we could either extend this fix or file a new bug.

Satheesh

Fernanda Pizzorno (JIRA) wrote:

    [ http://issues.apache.org/jira/browse/DERBY-463?page=all ]

Fernanda Pizzorno updated DERBY-463:
------------------------------------

   Attachment: DERBY-463.diff

Successive writes to a java.sql.Blob.setBinaryStream(long) seem to reset the 
file pointer
-----------------------------------------------------------------------------------------

        Key: DERBY-463
        URL: http://issues.apache.org/jira/browse/DERBY-463
    Project: Derby
       Type: Bug
 Components: JDBC
   Versions: 10.0.2.1
Environment: Sun java full version "1.4.2_05-b04"
Linux x86
Derby is run in network server mode
   Reporter: Laurenz Albe
   Assignee: Fernanda Pizzorno
Attachments: DERBY-463.diff, DERBY-463.diff, DERBY-463.stat, DERBY-463.stat

I have a table
PEOPLE(SEQ_ID INT NOT NULL PRIMARY KEY, PICTURE BLOB).
A row is inserted; both values are not NULL.
From inside a JDBC program, I select the Blob for update.
I then get the Blob output stream with a call to
 Blob.setBinaryStream(long)
To this stream I write several times with
 OutputStream.write(byte[], int, int)
I close the stream, update the selected row with the new Blob and commit.
The new value of the Blob now is exactly the value of the last content of the 
byte[],
and it is like the previous calls to write() have never taken place, or as if 
the file pointer
of the output stream has been reset between the calls.
A sample program follows; the size of the input file "picture.jpg" is 23237, 
the length
of the Blob after the program has run is 23237 % 1024 = 709
------------ sample program -------------
import java.sql.*;
class TestApp {
  private TestApp() {}
  public static void main(String[] args)
        throws ClassNotFoundException, SQLException, java.io.IOException {
     // try to load JDBC driver
     Class.forName("com.ibm.db2.jcc.DB2Driver");
     // open the input file
     java.io.InputStream instream = new java.io.FileInputStream("picture.jpg");
     // login to database
     Connection conn = DriverManager.getConnection(
           "jdbc:derby:net://dbtuxe/testdb", "laurenz", "apassword");
     conn.setAutoCommit(false);
     // select Blob for update
     PreparedStatement stmt = conn.prepareStatement(
           "SELECT PICTURE FROM PEOPLE WHERE SEQ_ID=? FOR UPDATE OF PICTURE");
     stmt.setInt(1, 1);
     ResultSet rs = stmt.executeQuery();
     // get Blob output stream
     rs.next();
     Blob blob = rs.getBlob(1);
     java.io.OutputStream outstream = blob.setBinaryStream(1l);
     // copy the input file to the Blob in chunks of 1K
     byte[] buf = new byte[1024];
     int count;
     while (-1 != (count = instream.read(buf))) {
        outstream.write(buf, 0, count);
        System.out.println("Written " + count + " bytes to Blob");
     }
     // close streams
     instream.close();
     outstream.close();
     // update Blob with new value
     String cursor = rs.getCursorName();
     PreparedStatement stmt2 = conn.prepareStatement(
           "UPDATE PEOPLE SET PICTURE=? WHERE CURRENT OF " + cursor);
     stmt2.setBlob(1, blob);
     stmt2.executeUpdate();
     // clean up
     stmt2.close();
     stmt.close();
     conn.commit();
     conn.close();
  }
}


Reply via email to