db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Daniel John Debrunner (JIRA)" <derby-...@db.apache.org>
Subject [jira] Commented: (DERBY-463) Successive writes to a java.sql.Blob.setBinaryStream(long) seem to reset the file pointer
Date Fri, 04 Nov 2005 03:42:03 GMT
    [ http://issues.apache.org/jira/browse/DERBY-463?page=comments#action_12356742 ] 

Daniel John Debrunner commented on DERBY-463:
---------------------------------------------

Sunitha, I don't think that is a problem because the api for OutputStream.write(int b) is
that it is a write of a byte, the top 24 bits are discarded.

There is a different serious problem with the class, nothing to do with this patch, it's an
existing problem.
The code use String(byte[]) to create a string from a byte array. This uses the default platform
encoding, which is typically not required
behaviour. Since this class is used for Clob.setAsciiStream I assume the encoding should be
ascii based.
Though the performance of this class  looks terrible if write(int) is used,  at least five
objects created for eveny byte written!

In fact this class and the client Clob have code like this everywhere, as the Clob is updated:

        clob_.string_ = clob_.string_.concat(new String(newByte));
        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
        clob_.characterStream_ = new java.io.StringReader(clob_.string_);

Would probably be better to create most of those objects on demand, rather than on every modification.
I mean if the CLOB is modified
but the application never retrieives the ascii  or character streams, what was the benefit
of creating them?



> 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
>      Fix For: 10.2.0.0
>  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();
>    }
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


Mime
View raw message