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/31 14:39:44 UTC
svn commit: r709408 - in /db/derby/code/branches/10.4/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 31 06:39:43 2008
New Revision: 709408
URL: http://svn.apache.org/viewvc?rev=709408&view=rev
Log:
DERBY-3871: EmbedBlob.setBytes returns incorrect insertion count.
Backported revisions 701372 (1a) and 701979 (2a) to 10.4.
Modified:
db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java?rev=709408&r1=709407&r2=709408&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java Fri Oct 31 06:39:43 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());
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/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?rev=709408&r1=709407&r2=709408&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Fri Oct 31 06:39:43 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/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java?rev=709408&r1=709407&r2=709408&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java (original)
+++ db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java Fri Oct 31 06:39:43 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,23 @@
}
}
+ /**
+ * 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];
+ int bytesRead = 0;
+ LoopingAlphabetStream contents = new LoopingAlphabetStream(length);
+ while ((bytesRead = contents.read(buffer)) > 0) {
+ writer.write(buffer, 0, bytesRead);
+ }
+ }
/**
* Create test suite for this test.