db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r793565 - in /db/derby/code/branches/10.5/java: engine/org/apache/derby/iapi/services/io/ engine/org/apache/derby/iapi/types/ testing/org/apache/derbyTesting/functionTests/tests/jdbc4/
Date Mon, 13 Jul 2009 12:14:07 GMT
Author: kristwaa
Date: Mon Jul 13 12:14:07 2009
New Revision: 793565

URL: http://svn.apache.org/viewvc?rev=793565&view=rev
Log:
DERBY-4245: Sorting a table containing a CLOB fails after upgrade to 10.5.
Merged fixes from trunk: 784701 (2a), 785104 (1c), 785105
(fixed spelling errors), 790162 (4a) and 791398 (3a).

Added:
    db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java
      - copied, changed from r785104, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java
Modified:
    db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/services/io/LimitInputStream.java
    db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/types/SQLClob.java
    db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java

Modified: db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/services/io/LimitInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/services/io/LimitInputStream.java?rev=793565&r1=793564&r2=793565&view=diff
==============================================================================
--- db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/services/io/LimitInputStream.java
(original)
+++ db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/services/io/LimitInputStream.java
Mon Jul 13 12:14:07 2009
@@ -144,4 +144,18 @@
 	public void setInput(InputStream in) {
 		this.in = in;
 	}
+
+    /**
+     * This stream doesn't support mark/reset, independent of whether the
+     * underlying stream does so or not.
+     * <p>
+     * The reason for not supporting mark/reset, is that it is hard to combine
+     * with the limit functionality without always keeping track of the number
+     * of bytes read.
+     *
+     * @return {@code false}
+     */
+    public boolean markSupported() {
+        return false;
+    }
 }

Modified: db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/types/SQLClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/types/SQLClob.java?rev=793565&r1=793564&r2=793565&view=diff
==============================================================================
--- db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/types/SQLClob.java (original)
+++ db/derby/code/branches/10.5/java/engine/org/apache/derby/iapi/types/SQLClob.java Mon Jul
13 12:14:07 2009
@@ -26,6 +26,7 @@
 import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 
 import org.apache.derby.iapi.services.io.ArrayInputStream;
+import org.apache.derby.iapi.services.io.FormatIdInputStream;
 import org.apache.derby.iapi.services.io.InputStreamUtil;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
 
@@ -38,6 +39,7 @@
 import java.io.InputStream;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.io.PushbackInputStream;
 import java.sql.Clob;
 import java.sql.Date;
 import java.sql.SQLException;
@@ -242,11 +244,11 @@
         long charLength = 0;
         try {
             if (repositionStream) {
-                rewindStream(csd.getDataOffset());
+                rewindStream(stream, csd.getDataOffset());
             }
             charLength = UTF8Util.skipUntilEOF(stream);
             // We just drained the whole stream. Reset it.
-            rewindStream(0);
+            rewindStream(stream, 0);
         } catch (IOException ioe) {
             throwStreamingIOException(ioe);
         }
@@ -348,7 +350,7 @@
                 if (read > hdrInfo.headerLength()) {
                     // We have read too much. Reset the stream.
                     read = hdrInfo.headerLength();
-                    rewindStream(read);
+                    rewindStream(stream, read);
                 }
                 csd = new CharacterStreamDescriptor.Builder().stream(stream).
                     bufferable(false).positionAware(false).
@@ -692,11 +694,12 @@
                                             : (int)csd.getByteLength();
             hdrInfo = new HeaderInfo(hdrLen, valueLength);
             // Make sure the stream is correctly positioned.
-            rewindStream(hdrLen);
+            rewindStream((InputStream)in, hdrLen);
         } else {
-            final boolean markSet = stream.markSupported();
+            final InputStream srcIn = (InputStream)in;
+            final boolean markSet = srcIn.markSupported();
             if (markSet) {
-                stream.mark(MAX_STREAM_HEADER_LENGTH);
+                srcIn.mark(MAX_STREAM_HEADER_LENGTH);
             }
             byte[] header = new byte[MAX_STREAM_HEADER_LENGTH];
             int read = in.read(header);
@@ -706,18 +709,31 @@
             }
             hdrInfo = investigateHeader(header, read);
             if (read > hdrInfo.headerLength()) {
-                // We read too much data, reset and position on the first byte
-                // of the user data.
-                // First see if we set a mark on the stream and can reset it.
-                // If not, try using the Resetable interface.
+                // We read too much data. To "unread" the bytes, the following
+                // mechanisms will be attempted:
+                //  1) See if we set a mark on the stream, if so reset it.
+                //  2) If we have a FormatIdInputStream, use a
+                //     PushBackInputStream and use it as the source.
+                //  3) Try using the Resetable interface.
+                // To avoid silent data truncation / data corruption, we fail
+                // in step three if the stream isn't resetable.
                 if (markSet) {
-                    // Stream is not a store Resetable one, use mark/reset
-                    // functionality instead.
-                    stream.reset();
-                    InputStreamUtil.skipFully(stream, hdrInfo.headerLength());
-                } else if (stream instanceof Resetable) {
-                    // We have a store stream.
-                    rewindStream(hdrInfo.headerLength());
+                    // 1) Reset the stream to the previously set mark.
+                    srcIn.reset();
+                    InputStreamUtil.skipFully(srcIn, hdrInfo.headerLength());
+                } else if (in instanceof FormatIdInputStream) {
+                    // 2) Add a push back stream on top of the underlying
+                    // source, and unread the surplus bytes we read. Set the
+                    // push back stream to be the source of the data input obj.
+                    final int surplus = read - hdrInfo.headerLength();
+                    FormatIdInputStream formatIn = (FormatIdInputStream)in;
+                    PushbackInputStream pushbackIn = new PushbackInputStream(
+                            formatIn.getInputStream(), surplus);
+                    pushbackIn.unread(header, hdrInfo.headerLength(), surplus);
+                    formatIn.setInput(pushbackIn);
+                } else {
+                    // 3) Assume we have a store stream.
+                    rewindStream(srcIn, hdrInfo.headerLength());
                 }
             }
         }
@@ -769,14 +785,15 @@
      * Rewinds the stream to the beginning and then skips the specified number
      * of bytes.
      *
-     * @param pos number of bytes to skip
+     * @param in input stream to rewind
+     * @param offset number of bytes to skip
      * @throws IOException if resetting or reading from the stream fails
      */
-    private void rewindStream(long pos)
+    private void rewindStream(InputStream in, long offset)
             throws IOException {
         try {
-            ((Resetable)stream).resetStream();
-            InputStreamUtil.skipFully(stream, pos);
+            ((Resetable)in).resetStream();
+            InputStreamUtil.skipFully(in, offset);
         } catch (StandardException se) {
             IOException ioe = new IOException(se.getMessage());
             ioe.initCause(se);

Copied: db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java
(from r785104, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java)
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java?p2=db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java&p1=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java&r1=785104&r2=793565&rev=793565&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java
(original)
+++ db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/LobSortTest.java
Mon Jul 13 12:14:07 2009
@@ -26,6 +26,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Properties;
 import java.util.Random;
 
 import junit.framework.Test;
@@ -36,6 +37,7 @@
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.SystemPropertyTestSetup;
 
 /**
  * Executes sorting of LOB values based on the length of the LOB or a random
@@ -158,7 +160,7 @@
         }
         rs.close();
         rs = stmt.executeQuery(sql);
-        // Get the BLOB value length though Blob.length
+        // Get the BLOB value length through Blob.length
         while (rs.next()) {
             assertEquals(rs.getInt(1), (int)rs.getBlob(2).length());
         }
@@ -186,7 +188,7 @@
         }
         rs.close();
         rs = stmt.executeQuery(sql);
-        // Get the CLOB value length though Clob.length
+        // Get the CLOB value length through Clob.length
         while (rs.next()) {
             assertEquals(rs.getInt(1), (int)rs.getClob(2).length());
         }
@@ -195,9 +197,13 @@
     }
 
     public static Test suite() {
+        Properties props = new Properties();
+        // Adjust sort buffer size to trigger the bug situation with less data.
+        props.setProperty("derby.storage.sortBufferMax", "4");
         TestSuite suite = new TestSuite(LobSortTest.class,
                                         "LobSortTestEmbedded");
-        return new CleanDatabaseTestSetup(suite) {
+        return new CleanDatabaseTestSetup(
+                new SystemPropertyTestSetup(suite, props, true)) {
             /**
              * Generates a table with Blob and Clobs of mixed size.
              */
@@ -217,7 +223,7 @@
                 ps.setInt(4, 0);
                 ps.setInt(5, rnd.nextInt());
                 ps.executeUpdate();
-                for (int i=0; i < 600; i++) {
+                for (int i=0; i < 100; i++) {
                     CharAlphabet ca = getCharAlphabet(1 + rnd.nextInt(3));
                     int length = (int)(rnd.nextDouble() * 64.0 * 1024.0);
                     if (rnd.nextInt(1000) < 500) {

Modified: db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java?rev=793565&r1=793564&r2=793565&view=diff
==============================================================================
--- db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java
(original)
+++ db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java
Mon Jul 13 12:14:07 2009
@@ -70,6 +70,7 @@
 		suite.addTest(ConnectionMethodsTest.suite());
         suite.addTest(VerifySignatures.suite());
         suite.addTest (LobStreamTest.suite());
+        suite.addTest(LobSortTest.suite());
         suite.addTest (BlobSetMethodsTest.suite());
         suite.addTest (JDBC4FromJDBC3DataSourceTest.suite());
 		



Mime
View raw message