db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r908586 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/store/raw/data/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Date Wed, 10 Feb 2010 16:59:58 GMT
Author: kristwaa
Date: Wed Feb 10 16:59:57 2010
New Revision: 908586

URL: http://svn.apache.org/viewvc?rev=908586&view=rev
Log:
DERBY-2992: getBinaryStream returns incorrect result (truncated value) if underlying blob
is deleted 

Made OverflowInputStream throw exception if the underlying value is deleted/modified.
(i.e. if the next overflow page cannot be found/accessed).
Added a new error message (D015).
Incorporated repro (originally contributed by Kathey Marsden, kmarsdenderby at sbcglobal dot
net).

Patch file: derby-2992-1b-throw_exception_on_eof.diff


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/OverflowInputStream.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/MessageId.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BLOBTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/OverflowInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/OverflowInputStream.java?rev=908586&r1=908585&r2=908586&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/OverflowInputStream.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/OverflowInputStream.java
Wed Feb 10 16:59:57 2010
@@ -25,6 +25,7 @@
 import org.apache.derby.iapi.reference.SQLState;
 
 import org.apache.derby.iapi.services.io.CloneableStream;
+import org.apache.derby.iapi.services.i18n.MessageService;
 
 import org.apache.derby.iapi.store.raw.RecordHandle;
 
@@ -33,6 +34,9 @@
 import org.apache.derby.iapi.store.raw.LockingPolicy;
 import org.apache.derby.iapi.store.access.TransactionController;
 
+import org.apache.derby.shared.common.reference.MessageId;
+
+import java.io.EOFException;
 import java.io.InputStream;
 import java.io.IOException;
 
@@ -151,6 +155,11 @@
                     columnOverflowPage.restorePortionLongColumn(this);
                     columnOverflowPage.unlatch();
                     columnOverflowPage = null;
+                } else {
+                    // An overflow page was specified, but we failed to get it.
+                    // Probably the value got deleted under our feet.
+                    throw new EOFException(MessageService.getTextMessage(
+                            MessageId.STORE_STREAM_OVERFLOW_PAGE_NOT_FOUND));
                 }
 
             }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=908586&r1=908585&r2=908586&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Wed Feb 10 16:59:57
2010
@@ -7524,6 +7524,11 @@
                 <text>in READ ONLY mode</text>
             </msg>
 
+            <msg>
+                <name>D015</name>
+                <text>Could not read further because another transaction has modified
the value.</text>
+            </msg>
+
         </family>
 
 

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/MessageId.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/MessageId.java?rev=908586&r1=908585&r2=908586&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/MessageId.java
(original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/MessageId.java
Wed Feb 10 16:59:57 2010
@@ -89,7 +89,11 @@
     String STORE_DURABILITY_TESTMODE_NO_SYNC = "D013"; // for derby.system.durability is

                                                        // set to test
     String STORE_BOOT_READONLY_MSG          = "D014";
-
+    /**
+     * When the specified overflow page isn't found while streaming from a
+     * page overflow chain (large data values, typically BLOB or CLOB).
+     */
+    String STORE_STREAM_OVERFLOW_PAGE_NOT_FOUND = "D015";
 
 	/*
 	** ClassManager

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BLOBTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BLOBTest.java?rev=908586&r1=908585&r2=908586&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BLOBTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BLOBTest.java
Wed Feb 10 16:59:57 2010
@@ -35,6 +35,7 @@
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Types;
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Random;
@@ -544,6 +545,68 @@
         rollback();
     }
 
+    /**
+     * Checks that Derby fails with an exception when a transaction using
+     * READ_UNCOMMITTED obtains a stream from a BLOB (reads one byte) and at
+     * the same time another connection deletes the BLOB.
+     * <p>
+     * Earlier only parts of the BLOB was returned, without errors. It was
+     * impossible to tell for the user that only parts of the value was
+     * retrieved.
+     * <p>
+     * See DERBY-2992.
+     */
+    public void testDerby2992_Repro()
+            throws IOException, SQLException {
+        // Autocommit doesn't seem to be enabled here in all cases.
+        setAutoCommit(true);
+
+        final String TBL = "D2992BLOB";
+        // Switch to READ UNCOMMITTED.
+        getConnection().setTransactionIsolation(
+                Connection.TRANSACTION_READ_UNCOMMITTED);
+        Statement stmt = createStatement();
+        dropTable(TBL);
+        stmt.executeUpdate("create table " + TBL + " (b blob)");
+        stmt.close();
+
+        PreparedStatement ps = prepareStatement("insert into " + TBL +
+                " values (?)");
+        int length = 65*1024*1024; // 65K
+        ps.setBinaryStream(1, new LoopingAlphabetStream(length), length);
+        ps.executeUpdate();
+        ps.close();
+
+        stmt = createStatement();
+        ResultSet rs = stmt.executeQuery("select B from " + TBL);
+        assertTrue(rs.next());
+
+        // Read one byte, keep the stream / rs open.
+        InputStream is = rs.getBinaryStream(1);
+        int i = is.read();
+        assertTrue(i != -1);
+
+        // Open a second connection and delete the BLOB.
+        Connection secondCon = openUserConnection("APP");
+        Statement secondStmt = secondCon.createStatement();
+        assertEquals(1, secondStmt.executeUpdate("delete from " + TBL));
+        secondCon.close();
+
+        // Continue reading the BLOB through the stream.
+        // The stream has now probably read one page of data, and as we progress
+        // it will have to fetch the next page. However, the next page has been
+        // deleted.
+        byte[] buf = new byte[4096];
+        try {
+            // Drain the stream.
+            while (is.read(buf) != -1) { }
+            // Expect the read call above to fail at some point.
+            fail("The read should have failed, value has been deleted");
+        } catch (EOFException eofe) {
+            // As we expected, everything's fine.
+        }
+    }
+
     public static void setRandomValue(
         Random r,
         PreparedStatement ps,



Mime
View raw message