You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2008/10/03 15:14:40 UTC

svn commit: r701372 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/jdbc/EmbedBlob.java engine/org/apache/derby/impl/jdbc/LOBStreamControl.java testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java

Author: kristwaa
Date: Fri Oct  3 06:14:40 2008
New Revision: 701372

URL: http://svn.apache.org/viewvc?rev=701372&view=rev
Log:
DERBY-3871: EmbedBlob.setBytes returns incorrect insertion count.
Made EmbedBlob.setBytes return the number of bytes inserted, instead of returning the Blob position after the insert.
Improved some JavaDoc comments.
Added regression tests.
Patch file: derby-3871-1a_insertion_count.diff

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java?rev=701372&r1=701371&r2=701372&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java Fri Oct  3 06:14:40 2008
@@ -793,39 +793,40 @@
 	/////////////////////////////////////////////////////////////////////////
 
 	/**
-    * JDBC 3.0
-    *
-    * Writes the given array of bytes to the BLOB value that this Blob object
-    * represents, starting at position pos, and returns the number of bytes written.
-    *
-    * @param pos - the position in the BLOB object at which to start writing
-    * @param bytes - the array of bytes to be written to the BLOB value that this
-    * Blob object represents
-    * @return the number of bytes written
-    * @exception SQLException Feature not implemented for now.
-	*/
+     * Writes the given array of bytes to the BLOB value that this Blob object
+     * represents, starting at position pos, and returns the number of bytes
+     * written.
+     *
+     * @param pos the position in the BLOB object at which to start writing
+     * @param bytes the array of bytes to be written to the BLOB value that this
+     *       Blob object represents
+     * @return The number of bytes written to the BLOB.
+     * @throws SQLException if writing the bytes to the BLOB fails
+     * @since 1.4
+	 */
 	public int setBytes(long pos, byte[] bytes) throws SQLException {
             return setBytes(pos, bytes, 0, bytes.length);
 	}
 
-   /**
-    * JDBC 3.0
-    *
-    * Writes all or part of the given array of byte array to the BLOB value that
-    * this Blob object represents and returns the number of bytes written.
-    * Writing starts at position pos in the BLOB value; len bytes from the given
-    * byte array are written.
-    *
-    * @param pos - the position in the BLOB object at which to start writing
-    * @param bytes - the array of bytes to be written to the BLOB value that this
-    * Blob object represents
-    * @param offset - the offset into the array bytes at which to start reading
-    * the bytes to be set
-    * @param len - the number of bytes to be written to the BLOB value from the
-    * array of bytes bytes
-    * @return the number of bytes written
-    * @exception SQLException Feature not implemented for now.
-	*/
+    /**
+     * Writes all or part of the given array of byte array to the BLOB value
+     * that this Blob object represents and returns the number of bytes written.
+     * Writing starts at position pos in the BLOB value; len bytes from the
+     * given byte array are written.
+     *
+     * @param pos the position in the BLOB object at which to start writing
+     * @param bytes the array of bytes to be written to the BLOB value that this
+     *       Blob object represents
+     * @param offset the offset into the byte array at which to start reading
+     *       the bytes to be written
+     * @param len the number of bytes to be written to the BLOB value from the
+     *       array of bytes bytes
+     * @return The number of bytes written to the BLOB.
+     * @throws SQLException if writing the bytes to the BLOB fails
+     * @throws IndexOutOfBoundsException if {@code len} is larger than
+     *       {@code bytes.length - offset}
+     * @since 1.4
+	 */
     public int setBytes(long pos,
             byte[] bytes,
             int offset,
@@ -839,12 +840,12 @@
                 if (pos < 1)
                     throw Util.generateCsSQLException(
                         SQLState.BLOB_BAD_POSITION, new Long(pos));
-                len = (int) control.write (bytes, offset, len, pos - 1);
+                control.write (bytes, offset, len, pos - 1);
             }
             else {
                 control = new LOBStreamControl (getEmbedConnection().getDBName());
                 control.copyData (myStream, length());
-                len = (int) control.write(bytes, offset, len, pos - 1);
+                control.write(bytes, offset, len, pos - 1);
                 myStream.close();
                 streamLength = -1;
                 materialized = true;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?rev=701372&r1=701371&r2=701372&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Fri Oct  3 06:14:40 2008
@@ -214,13 +214,17 @@
     }
 
     /**
-     * Writes part of the byte array.
+     * Writes {@code len} bytes from the specified byte array to the LOB.
+     *
      * @param b byte array
      * @param off offset from where to read from the byte array
-     * @param len number of bytes to be copied
-     * @param pos starting postion
-     * @return new postion
-     * @throws IOException, StandardException
+     * @param len number of bytes to be written
+     * @param pos starting position
+     * @return The position after the bytes have been written to the LOB.
+     * @throws IOException if writing to the LOB fails
+     * @throws StandardException if writing to the LOB fails
+     * @throws IndexOutOfBoundsException if {@code len} is larger than
+     *       {@code b.length - off}
      */
     synchronized long write(byte[] b, int off, int len, long pos)
             throws IOException, StandardException {

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java?rev=701372&r1=701371&r2=701372&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java Fri Oct  3 06:14:40 2008
@@ -610,6 +610,76 @@
      }
      
     /**
+     * Tests the return count on insertion when the Blob is represented as a
+     * byte array in memory.
+     */
+    public void testSetBytesReturnValueSmall()
+            throws SQLException {
+        Blob myBlob = getConnection().createBlob();
+        byte[] byteBatch = new byte[] {
+                    0x65, 0x66, 0x67, 0x68, 0x69,
+                    0x65, 0x66, 0x67, 0x68, 0x69
+                };
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(1, byteBatch));
+        // Try again, overwrites the bytes.
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(1, byteBatch));
+        // Last time, start at a different index.
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(4, byteBatch));
+    }
+
+    /**
+     * Tests the return count on insertion when the Blob is represented as a
+     * temporary file on disk.
+     */
+    public void testSetBytesReturnValueLarge()
+            throws IOException, SQLException {
+        Blob myBlob = getConnection().createBlob();
+        // Insert one MB, should cause Blob to spill to disk.
+        OutputStream blobWriter = myBlob.setBinaryStream(1);
+        transferAlphabetData(blobWriter, 1*1024*1024);
+        byte[] byteBatch = new byte[] {
+                    0x65, 0x66, 0x67, 0x68, 0x69,
+                    0x65, 0x66, 0x67, 0x68, 0x69
+                };
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(1, byteBatch));
+        // Try again, overwrites the bytes.
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(1, byteBatch));
+        // Start at a different, low index.
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(4, byteBatch));
+        // Start at a different, higher index.
+        assertEquals("Wrong insertion count",
+                byteBatch.length, myBlob.setBytes(512*1024, byteBatch));
+    }
+
+    /**
+     * Tests the return count on insertion when the Blob is fetched from the
+     * database and then modified.
+     * <p>
+     * The main point for this test is to provoke the transition from a
+     * read-only internal representation to a writable representation.
+     * For a Blob of "considerable" size, this involved going from a store
+     * stream representation to a {@code LOBStreamControl} representation using
+     * a temporary file.
+     */
+    public void testSetBytesReturnValueLargeStateChange()
+            throws IOException, SQLException {
+        // Get a Blob from the database, don't create an empty one.
+        initializeLongBlob(); // Ignoring id for now, use instance variable.
+        assertEquals("Wrong insertion count",
+                1, blob.setBytes(30000, new byte[] {0x69}));
+        assertEquals("Wrong insertion count",
+                1, blob.setBytes(1, new byte[] {0x69}));
+        assertEquals("Wrong insertion count",
+                2, blob.setBytes(1235, new byte[] {0x69, 0x69}));
+    }
+
+    /**
      * Test that a lock held on the corresponding row is released when free() is
      * called on the Blob object.
      * @throws java.sql.SQLException 
@@ -740,6 +810,22 @@
         }
     }
 
+    /**
+     * Transfers the specified number of bytes generated from the modern latin
+     * alphabet (lowercase) to the destination stream.
+     *
+     * @param writer the destination
+     * @param length number of bytes to write
+     * @throws IOException if writing to the destination stream fails
+     */
+    public static void transferAlphabetData(OutputStream writer, long length)
+            throws IOException {
+        byte[] buffer = new byte[8*1024];
+        LoopingAlphabetStream contents = new LoopingAlphabetStream(length);
+        while (contents.read(buffer) > 0) {
+            writer.write(buffer);
+        }
+    }
     
     /**
      * Create test suite for this test.