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 11:29:52 UTC

svn commit: r709375 - in /db/derby/code/branches/10.4/java: engine/org/apache/derby/impl/jdbc/ testing/org/apache/derby/impl/jdbc/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/

Author: kristwaa
Date: Fri Oct 31 03:29:46 2008
New Revision: 709375

URL: http://svn.apache.org/viewvc?rev=709375&view=rev
Log:
DERBY-3793: Remove unnecessary methods from InternalClob interface.
Backported revisions 678724 (1b) and 691608 (2b) to 10.4.
Had to do one minor manual change, because TestConfiguration.setAutoCommit(boolean) doesn't exist in 10.4.

Modified:
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/ClobUpdatableReader.java
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/InternalClob.java
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/TemporaryClob.java
    db/derby/code/branches/10.4/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java
    db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/ClobUpdatableReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/ClobUpdatableReader.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/ClobUpdatableReader.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/ClobUpdatableReader.java Fri Oct 31 03:29:46 2008
@@ -114,7 +114,6 @@
         InternalClob internalClob = clob.getInternalClob();
         materialized = internalClob.isWritable();        
         if (materialized) {
-            long byteLength = internalClob.getByteLength();
             this.stream = internalClob.getRawByteStream();
             // Position the stream on pos using the init method.
             init ((LOBInputStream)stream, pos);

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/InternalClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/InternalClob.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/InternalClob.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/InternalClob.java Fri Oct 31 03:29:46 2008
@@ -40,31 +40,6 @@
 interface InternalClob {
 
     /**
-     * Gets the number of bytes contained in the Clob.
-     *
-     * @return Number of bytes in the Clob.
-     * @throws IOException if accessing underlying I/O resources fail
-     * @throws SQLException if accessing underlying resources fail
-     */
-    long getByteLength() throws IOException, SQLException;
-
-    /**
-     * Obtains the byte position for the given character position.
-     * <p>
-     * The range of valid character positions is 
-     *  <code>1 - Clob.getCharLength() +1</code>, inclusive. The upper bound is
-     * used when appending to the Clob. Note that specifying a character
-     * position that is more than one longer than the Clob raises an exception.
-     *
-     * @param charPos character position. The first position is <code>1</code>.
-     * @return A 0-based byte position.
-     * @throws EOFException if the position is bigger than the Clob
-     * @throws IOException if accessing the underlying I/O resources fail
-     * @throws SQLException if the specified character position is invalid
-     */
-    long getBytePosition(long charPos) throws IOException, SQLException;
-
-    /**
      * Gets the number of characters in the Clob.
      *
      * @return Number of characters in the Clob.
@@ -81,10 +56,15 @@
      * stream, it is up to the Clob representation which one it uses.
      * <p>
      * This stream may be an internal store stream, and should not be directly
-     * published to the end user (returned through the JDBC API). There are two
-     * motivations for this; the stream may be closed by the end user when it is
-     * not supposed to, and operations on the stream might throw exceptions we
-     * do not want to present to the end user unwrapped.
+     * published to the end user (returned through the JDBC API). There are
+     * three reasons for this:
+     * <ul> <li>the stream may be closed by the end user when it is
+     *          not supposed to</li>
+     *      <li>operations on the stream might throw exceptions we don't want to
+     *          present to the end user unwrapped</li>
+     *      <li>the stream may contain a Derby specific end-of-stream marker
+     *      </li>
+     * </ul>
      * <p>
      * The primary use of this method is to clone the Clob contents without
      * going via char (or String). Make sure the clone uses the same encoding

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=709375&r1=709374&r2=709375&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 03:29:46 2008
@@ -357,8 +357,14 @@
 
     /**
      * Copies bytes from stream to local storage.
-     * @param inStream
-     * @param length length to be copied
+     * <p>
+     * Note that specifying the length as {@code Long.MAX_VALUE} results in
+     * reading data from the stream until EOF is reached, but no length checking
+     * will be performed.
+     *
+     * @param inStream the stream to copy from
+     * @param length number of bytes to be copied, or {@code Long.MAX_VALUE} to
+     *      copy everything until EOF is reached
      * @throws IOException, StandardException
      */
     synchronized void copyData(InputStream inStream, long length)
@@ -368,12 +374,31 @@
         while (sz < length) {
             int len = (int) Math.min (length - sz, bufferSize);
             len = inStream.read(data, 0, len);
-            if (len < 0)
-                throw new EOFException("Reached end-of-stream " +
-                        "prematurely at " + sz);
+            if (len == -1) {
+                if (length != Long.MAX_VALUE) {
+                    // We reached EOF before all the requested bytes are read.
+                    throw new EOFException("Reached end-of-stream " +
+                        "prematurely at " + sz + ", expected " + length);
+                } else {
+                    // End of data, but no length checking.
+                    break;
+                }
+            }
             write(data, 0, len, sz);
             sz += len;
         }
+        // If we copied until EOF, see if we have a Derby end-of-stream marker.
+        if (length == Long.MAX_VALUE) {
+            long curLength = getLength();
+            byte[] eos = new byte[3];
+            // Read the three last bytes, marker is 0xE0 0x00 0x00.
+            read(eos, 0, 3, curLength -3);
+            if ((eos[0] & 0xFF) == 0xE0 && (eos[1] & 0xFF) == 0x00 &&
+                    (eos[2] & 0xFF) == 0x00) {
+                // Remove Derby end-of-stream-marker.
+                truncate(curLength -3);
+            }
+        }
     }
 
     protected void finalize() throws Throwable {

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java Fri Oct 31 03:29:46 2008
@@ -53,9 +53,6 @@
 final class StoreStreamClob
     implements InternalClob {
 
-    /** Maximum value used when requesting bytes/chars to be skipped. */
-    private static final long SKIP_BUFFER_SIZE = 8*1024; // 8 KB
-
     /** Tells whether this Clob has been released or not. */
     private volatile boolean released = false;
 
@@ -113,45 +110,6 @@
     }
 
     /**
-     * Returns the number of bytes in the Clob.
-     *
-     * @return The number of bytes in the Clob.
-     * @throws IOException if accessing the I/O resources fail
-     * @throws SQLException if accessing the store resources fail
-     */
-    public long getByteLength()
-            throws IOException, SQLException {
-        checkIfValid();
-        // Read through the whole stream to get the length.
-        long byteLength = 0;
-        try {
-            this.conChild.setupContextStack();
-            this.positionedStoreStream.reposition(0L);
-            // See if length is encoded in the stream.
-            int us1 = this.positionedStoreStream.read();
-            int us2 = this.positionedStoreStream.read();
-            byteLength = (us1 << 8) + (us2 << 0);
-            if (byteLength == 0) {
-                while (true) {
-                    long skipped =
-                        this.positionedStoreStream.skip(SKIP_BUFFER_SIZE);
-                    if (skipped <= 0) {
-                        break;
-                    }
-                    byteLength += skipped;
-                }
-                // Subtract 3 bytes for the end-of-stream marker.
-                byteLength -= 3;
-            }
-            return byteLength;
-        } catch (StandardException se) {
-            throw Util.generateCsSQLException(se);
-        } finally {
-            this.conChild.restoreContextStack();
-        }
-    }
-
-    /**
      * Returns the number of characters in the Clob.
      *
      * @return Number of characters in the Clob.
@@ -234,20 +192,6 @@
     }
 
     /**
-     * Returns the byte position for the specified character position.
-     *
-     * @param charPos character position. First character is at position 1.
-     * @return Corresponding byte position. First byte is at position 0.
-     * @throws EOFException if the position is bigger then the Clob
-     * @throws IOException if accessing the underlying I/O resources fail
-     * @throws SQLException if accessing the underlying store resources fail
-     */
-    public long getBytePosition(long charPos)
-            throws IOException, SQLException {
-        return UTF8Util.skipFully(getRawByteStream(), charPos -1);
-    }
-
-    /**
      * Not supported.
      *
      * @see InternalClob#getWriter

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/TemporaryClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/TemporaryClob.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/TemporaryClob.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/jdbc/TemporaryClob.java Fri Oct 31 03:29:46 2008
@@ -170,9 +170,9 @@
      *      the Clob length +1
      * @throws IOException if accessing underlying I/O resources fail
      */
-    public synchronized long getBytePosition (final long charPos)
+    //@GuardedBy(this)
+    private long getBytePosition (final long charPos)
             throws IOException {
-        checkIfValid();
         long bytePos;
         if (charPos == this.posCache.getCharPos()) {
             // We already know the position.
@@ -395,8 +395,8 @@
     private void copyClobContent(InternalClob clob)
             throws IOException, SQLException {
         try {
-            long byteLength = clob.getByteLength();
-            this.bytes.copyData(clob.getRawByteStream(), byteLength);
+            // Specify LONG.MAX_VALUE to copy data until EOF.
+            this.bytes.copyData(clob.getRawByteStream(), Long.MAX_VALUE);
         } catch (StandardException se) {
             throw Util.generateCsSQLException(se);
         }

Modified: db/derby/code/branches/10.4/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java (original)
+++ db/derby/code/branches/10.4/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java Fri Oct 31 03:29:46 2008
@@ -125,27 +125,6 @@
      * UnsupportedOperationException is allowed for read-only Clobs.
      */
 
-    public void testGetByteLengthAfterRelease()
-            throws IOException, SQLException {
-        iClob.release();
-        try {
-            iClob.getByteLength();
-            fail("Exception should have been raised, but was not");
-        } catch (IllegalStateException ise) {
-            // This is as expected.
-        }
-    }
-
-    public void testGetBytePositionAfterRelease()
-            throws IOException, SQLException {
-        iClob.release();
-        try {
-            iClob.getBytePosition(1L);
-            fail("Exception should have been raised, but was not");
-        } catch (IllegalStateException ise) {
-            // This is as expected.
-        }
-    }
     public void testGetCharLengthAfterRelease()
             throws IOException, SQLException {
         iClob.release();
@@ -230,53 +209,6 @@
 
     /* End of XXXAfterRelease tests. */
 
-    public void testGetByteLength()
-            throws IOException, SQLException {
-        assertEquals(this.initialByteLength, iClob.getByteLength());
-    }
-
-    public void testGetBytePosition_first()
-            throws IOException, SQLException {
-        assertEquals(0L, iClob.getBytePosition(1L));
-    }
-
-    public void testGetBytePosition_second()
-            throws IOException, SQLException {
-        assertEquals(bytesPerChar, iClob.getBytePosition(2L));
-    }
-
-    public void testGetBytePosition_last()
-            throws IOException, SQLException {
-        assertEquals(initialByteLength - bytesPerChar,
-                     iClob.getBytePosition(this.initialCharLength));
-    }
-
-    public void testGetBytePosition_lastPlussOne()
-            throws IOException, SQLException {
-        assertEquals(initialByteLength,
-                     iClob.getBytePosition(this.initialCharLength +1));
-    }
-
-    public void testGetBytePosition_lastPlussTwo()
-            throws IOException, SQLException {
-        try {
-            long pos = iClob.getBytePosition(this.initialCharLength +2);
-            fail("Length +2 should have no valid byte position, got " + pos);
-        } catch (EOFException ioe) {
-            // As expected for Derby.
-        }
-    }
-
-    public void testGetBytePosition_lastPlussThousand()
-            throws IOException, SQLException {
-        try {
-            long pos = iClob.getBytePosition(this.initialCharLength +1000);
-            fail("Length +1000 should have no valid byte position, got " + pos);
-        } catch (EOFException ioe) {
-            // As expected for Derby.
-        }
-    }
-
     public void testGetCharLength()
             throws IOException, SQLException {
         assertEquals(this.initialCharLength, iClob.getCharLength());

Modified: db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java?rev=709375&r1=709374&r2=709375&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java (original)
+++ db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java Fri Oct 31 03:29:46 2008
@@ -35,6 +35,7 @@
 
 import java.sql.Connection;
 import java.sql.Clob;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -204,6 +205,63 @@
             newContent, this.clob.getSubString(1, newContent.length()));
     }
 
+    /**
+     * Tests that Derby specific end-of-stream markers aren't passed over to
+     * the temporary Clob, which doesn't use such markers.
+     * <p>
+     * Passing the marker over will normally result in a UTF encoding exception.
+     * <p>
+     * ID USAGE: reads id 2, writes id 10002
+     */
+    public void testInsertCharacter_ReadOnlyToTemporary()
+            throws IOException, SQLException {
+        getConnection().setAutoCommit(false);
+        // Insert data, a medium sized Clob to store it as a stream.
+        Statement stmt = createStatement();
+        PreparedStatement ps = prepareStatement(
+                "insert into ClobTestData values (?,?)");
+        int initalSize = 128*1024;
+        ps.setInt(1, 2);
+        ps.setCharacterStream(
+                2, new LoopingAlphabetReader(initalSize), initalSize);
+        ps.executeUpdate();
+
+        // Select the Clob, and change one character.
+        PreparedStatement psSelect = prepareStatement(
+                "select dClob from ClobTestData where id = ?");
+        psSelect.setInt(1, 2);
+        ResultSet lRs = psSelect.executeQuery();
+        lRs.next();
+        Clob lClob = lRs.getClob(1);
+        lClob.setString(1, "K");
+        Reader r = lClob.getCharacterStream();
+        assertEquals('K', r.read());
+        long length = 1;
+        while (true) {
+            // Since we're skipping characters, the bytes have to be decoded
+            // and we will detect any encoding errors.
+            long skipped = r.skip(4096);
+            if (skipped > 0) {
+                length += skipped;
+            } else {
+                break;
+            }
+        }
+        lRs.close();
+        assertEquals("Wrong length!", initalSize, length);
+        // Reports the correct length, now try to insert it.
+        ps.setInt(1, 10003);
+        ps.setClob(2, lClob);
+        ps.executeUpdate();
+        // Fetch it back.
+        psSelect.setInt(1, 10003);
+        lRs = psSelect.executeQuery();
+        lRs.next();
+        Clob lClob2 = lRs.getClob(1);
+        assertEquals(lClob.getCharacterStream(), lClob2.getCharacterStream());
+        assertEquals(initalSize, lClob2.length());
+    }
+
     public void testPositionWithString_ASCII_SimplePartialRecurringPattern()
             throws IOException, SQLException {
         String token = "xxSPOTxx";
@@ -289,7 +347,8 @@
         // Obtain a Clob containing the empty string ("").
         Statement stmt = createStatement();
         // Keep reference to the result set to be able to close it.
-        this.rs = stmt.executeQuery("select * from ClobTestData");
+        this.rs = stmt.executeQuery(
+                "select dClob from ClobTestData where id = 1");
         assertTrue(this.rs.next());
         this.clob = this.rs.getClob(1);
     }
@@ -441,8 +500,8 @@
             Connection con = getConnection();
             Statement stmt = con.createStatement();
             stmt.execute("create table ClobTestData (" +
-                    "dClob CLOB)");
-            stmt.executeUpdate("insert into ClobTestData values ('')");
+                    "id int unique, dClob CLOB)");
+            stmt.executeUpdate("insert into ClobTestData values (1, '')");
             stmt.close();
        }