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 ka...@apache.org on 2007/05/27 19:56:33 UTC

svn commit: r542011 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/client/net/ testing/org/apache/derbyTesting/functionTests/tests/derbynet/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/

Author: kahatlen
Date: Sun May 27 10:56:32 2007
New Revision: 542011

URL: http://svn.apache.org/viewvc?view=rev&rev=542011
Log:
DERBY-2496: Implement Blob support for Locators

The attached patch, enableblobloc.diff, contains the the necessary
changes to enable the use of locators for Blob. The patch addresses
the following issues:

   * Enable the use of locators.
   * Modification of tests that experience changed behavior with locators
   * If stored procedures reports that the given locator can not be
     found, it is assumed that this is because transaction has been
     terminated and an "Blob accessed after commit" error is
     reported. This makes the client driver and the embedded driver
     report the same error for this case.

Contributed by Øystein Grøvlen.

Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/CallableLocatorProcedures.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetRequest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/_Suite.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java Sun May 27 10:56:32 2007
@@ -22,7 +22,6 @@
 package org.apache.derby.client.am;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/CallableLocatorProcedures.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/CallableLocatorProcedures.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/CallableLocatorProcedures.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/CallableLocatorProcedures.java Sun May 27 10:56:32 2007
@@ -176,7 +176,12 @@
         }
 
         blobReleaseLocatorCall.setIntX(1, locator);
-        blobReleaseLocatorCall.executeX();
+        try {
+            blobReleaseLocatorCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
     }
 
     /**
@@ -211,7 +216,12 @@
         blobGetPositionFromLocatorCall.setIntX(2, locator);
         blobGetPositionFromLocatorCall.setIntX(3, searchLocator);
         blobGetPositionFromLocatorCall.setLongX(4, fromPosition);
-        blobGetPositionFromLocatorCall.executeX();
+        try {
+            blobGetPositionFromLocatorCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return blobGetPositionFromLocatorCall.getLongX(1);
     }
 
@@ -342,7 +352,12 @@
         blobGetPositionFromBytesCall.setIntX(2, locator);
         blobGetPositionFromBytesCall.setBytesX(3, bytesToBeCompared);
         blobGetPositionFromBytesCall.setLongX(4, fromPosition);
-        blobGetPositionFromBytesCall.executeX();
+        try {
+            blobGetPositionFromBytesCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return blobGetPositionFromBytesCall.getLongX(1);
     }
 
@@ -369,7 +384,12 @@
         }
 
         blobGetLengthCall.setIntX(2, sourceLocator);
-        blobGetLengthCall.executeX();
+        try {
+            blobGetLengthCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return blobGetLengthCall.getLongX(1);
     }
 
@@ -419,7 +439,12 @@
             blobGetBytesCall.setIntX(2, sourceLocator);
             blobGetBytesCall.setLongX(3, fromPosition + gotSoFar);
             blobGetBytesCall.setIntX(4, forLength - gotSoFar);
-            blobGetBytesCall.executeX();
+            try {
+                blobGetBytesCall.executeX();
+            } catch (SqlException sqle) {
+                sqle = handleInvalidLocator(sqle);
+                throw sqle;
+            }
             byte[] result = blobGetBytesCall.getBytesX(1);
             
             if (gotSoFar == 0) {  // First round of reading
@@ -501,7 +526,12 @@
             blobSetBytesCall.setLongX(2, fromPosition + sentSoFar);
             blobSetBytesCall.setIntX(3, numBytesThisRound);
             blobSetBytesCall.setBytesX(4, bytesToBeSent);
-            blobSetBytesCall.executeX();
+            try {
+                blobSetBytesCall.executeX();
+            } catch (SqlException sqle) {
+                sqle = handleInvalidLocator(sqle);
+                throw sqle;
+            }
             
             sentSoFar += numBytesThisRound;
         }
@@ -513,7 +543,7 @@
      * <p>
      * <b>Note:</b> If the value specified for <code>length</code> is greater
      * than the length+1 of the <code>BLOB</code> value then an
-     * <code>SQLException</code> will be thrown.
+     * <code>SqlException</code> will be thrown.
      * 
      * @param sourceLocator locator identifying the Blob to be truncated
      * @param length the length, in bytes, to which the <code>BLOB</code> value
@@ -534,7 +564,12 @@
 
         blobTruncateCall.setIntX(1, sourceLocator);
         blobTruncateCall.setLongX(2, length);
-        blobTruncateCall.executeX();
+        try {
+            blobTruncateCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
     }
 
     /**
@@ -619,7 +654,12 @@
         }
 
         clobReleaseLocatorCall.setIntX(1, locator);
-        clobReleaseLocatorCall.executeX();
+        try {
+            clobReleaseLocatorCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
     }
 
 
@@ -745,7 +785,12 @@
         clobGetPositionFromStringCall.setIntX(2, locator);
         clobGetPositionFromStringCall.setStringX(3, searchLiteral);
         clobGetPositionFromStringCall.setLongX(4, fromPosition);
-        clobGetPositionFromStringCall.executeX();
+        try {
+            clobGetPositionFromStringCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return clobGetPositionFromStringCall.getLongX(1);
     }
 
@@ -781,7 +826,12 @@
         clobGetPositionFromLocatorCall.setIntX(2, locator);
         clobGetPositionFromLocatorCall.setIntX(3, searchLocator);
         clobGetPositionFromLocatorCall.setLongX(4, fromPosition);
-        clobGetPositionFromLocatorCall.executeX();
+        try {
+            clobGetPositionFromLocatorCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return clobGetPositionFromLocatorCall.getLongX(1);
     }
 
@@ -807,7 +857,12 @@
         }
 
         clobGetLengthCall.setIntX(2, sourceLocator);
-        clobGetLengthCall.executeX();
+        try {
+            clobGetLengthCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
         return clobGetLengthCall.getLongX(1);
     }
 
@@ -858,7 +913,12 @@
             clobGetSubStringCall.setIntX(2, sourceLocator);
             clobGetSubStringCall.setLongX(3, fromPosition + gotSoFar);
             clobGetSubStringCall.setIntX(4, forLength - gotSoFar);
-            clobGetSubStringCall.executeX();
+            try {
+                clobGetSubStringCall.executeX();
+            } catch (SqlException sqle) {
+                sqle = handleInvalidLocator(sqle);
+                throw sqle;
+            }
             String result =  clobGetSubStringCall.getStringX(1);
 
             if (gotSoFar == 0) {  // First round of reading
@@ -937,7 +997,12 @@
             clobSetStringCall.setLongX(2, fromPosition + sentSoFar);
             clobSetStringCall.setIntX(3, numCharsThisRound);
             clobSetStringCall.setStringX(4, stringToBeSent);
-            clobSetStringCall.executeX();
+            try {
+                clobSetStringCall.executeX();
+            } catch (SqlException sqle) {
+                sqle = handleInvalidLocator(sqle);
+                throw sqle;
+            }
 
             sentSoFar += numCharsThisRound;
         }
@@ -949,7 +1014,7 @@
      * <p>
      * <b>Note:</b> If the value specified for <code>length</code> is greater
      * than the length+1 of the <code>CLOB</code> value then an
-     * <code>SQLException</code> will be thrown.
+     * <code>SqlException</code> will be thrown.
      * 
      * @param sourceLocator locator identifying the Clob to be truncated
      * @param length the length, in characters, to which the <code>CLOB</code>
@@ -970,6 +1035,42 @@
 
         clobTruncateCall.setIntX(1, sourceLocator);
         clobTruncateCall.setLongX(2, length);
-        clobTruncateCall.executeX();
+        try {
+            clobTruncateCall.executeX();
+        } catch (SqlException sqle) {
+            sqle = handleInvalidLocator(sqle);
+            throw sqle;
+        }
+    }
+
+    /**
+     * If the given exception indicates that locator was not valid, we
+     * assume the locator has been garbage-collected due to
+     * transaction commit, and wrap the exception in an exception with
+     * SQL state <code>BLOB_ACCESSED_AFTER_COMMIT</code>.
+     * @param sqle Exception to be checked
+     * @return If <code>sqle</code> indicates that locator was
+     *         invalid, an <code>SqlException</code> with SQL state
+     *         <code>BLOB_ACCESSED_AFTER_COMMIT</code>. Otherwise, the
+     *         incoming exception is returned.
+     */
+    private SqlException handleInvalidLocator(SqlException sqle)
+    {
+        if ((sqle.getMessage().indexOf(ExceptionUtil
+                .getSQLStateFromIdentifier(SQLState.LOB_LOCATOR_INVALID)) >= 0)
+            // With Java 6, the reason for the failure of the
+            // procedure call is not reported, just
+            // LANG_UNEXPECTED_USER_EXCEPTION (see DERBY-1629).
+            // Until this is fixed, treat all such errors as INVALID_LOCATOR
+            || (sqle.getSQLState().compareTo
+                (ExceptionUtil.getSQLStateFromIdentifier
+                 (SQLState.LANG_UNEXPECTED_USER_EXCEPTION)) == 0)) {
+            return new SqlException(connection.agent_.logWriter_,
+                    new ClientMessageId(SQLState.BLOB_ACCESSED_AFTER_COMMIT),
+                    null,
+                    sqle);
+        } else {
+            return sqle;
+        }
     }
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Sun May 27 10:56:32 2007
@@ -2210,10 +2210,7 @@
         //If the locator value is -1 it means that we do not
         //have locator support on the server.
         
-        //The code here has been disabled because the Lob implementations
-        //have still not been completely converted to use locators. Once
-        //the Lob implementations are completed then this code can be enabled.
-        if (locator != INVALID_LOCATOR && false) {
+        if (locator != INVALID_LOCATOR) {
             //A valid locator value has been obtained.
             blob = new org.apache.derby.client.am.Blob(this.agent_, locator);
         } 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetRequest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetRequest.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetRequest.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetResultSetRequest.java Sun May 27 10:56:32 2007
@@ -272,7 +272,7 @@
                              ColumnMetaData resultSetMetaData,
                              boolean firstOutovrBuilt,
                              boolean hasLobs) throws SqlException {
-        if (false && hasLobs) {  // Disable use of locators for now
+        if (hasLobs) {
             if (!firstOutovrBuilt) {
                 buildOUTOVR(resultSet, resultSetMetaData);
                 resultSet.firstOutovrBuilt_ = true;

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/_Suite.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/_Suite.java Sun May 27 10:56:32 2007
@@ -48,7 +48,6 @@
              
         suite.addTest(PrepareStatementTest.suite());
         suite.addTest(ShutDownDBWhenNSShutsDownTest.suite());
-        suite.addTest(SuicideOfStreamingTest.suite());
         suite.addTest(DRDAProtocolTest.suite());
         suite.addTest(ClientSideSystemPropertiesTest.suite());
         suite.addTest(BadConnectionTest.suite());

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java?view=diff&rev=542011&r1=542010&r2=542011
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java Sun May 27 10:56:32 2007
@@ -2208,65 +2208,50 @@
         commit();
 
 
-        assertTrue("FAIL - shotBlob is NULL", shortBlob != null);
-        assertEquals("FAIL - wrong length after commit",
-                26, shortBlob.length());
+        assertTrue("FAIL - shortBlob is NULL", shortBlob != null);
+        // this should give blob/clob unavailable exceptions on client
+        try {
+            shortBlob.length();
+            if (usingDerbyNetClient()) {
+                fail("FAIL - should not be able to access Blob after commit");
+            }
+        } catch (SQLException e) {
+            checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
+            assertTrue("FAIL - method should not fail when using embedded",
+                       usingDerbyNetClient());
+        }
 
+        assertTrue("FAIL - blob is NULL", blob != null);
         // these should all give blob/clob data unavailable exceptions
         try {
             blob.length();
-            if (usingEmbedded()) {
-                fail("FAIL - should not be able to access large log " +
-                        "after commit");
-            }
+            fail("FAIL - should not be able to access large Blob after commit");
         } catch (SQLException e) {
             checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
-            assertTrue("FAIL - method should not fail when using Derby Client" +
-                    " and JCC", usingEmbedded());
         }
         try {
             blob.getBytes(2,3);
-            if (usingEmbedded()) {
-                fail("FAIL - should not be able to access large log " +
-                        "after commit");
-            }
+            fail("FAIL - should not be able to access large Blob after commit");
         } catch (SQLException e) {
             checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
-            assertTrue("FAIL - method should not fail when using Derby Client" +
-                    " and JCC", usingEmbedded());
         }
         try {
             blob.getBinaryStream();
-            if (usingEmbedded()) {
-                fail("FAIL - should not be able to access large log " +
-                        "after commit");
-            }
+            fail("FAIL - should not be able to access large Blob after commit");
         } catch (SQLException e) {
             checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
-            assertTrue("FAIL - method should not fail when using Derby Client" +
-                    " and JCC", usingEmbedded());
         }
         try {
             blob.position("foo".getBytes("US-ASCII"),2);
-            if (usingEmbedded()) {
-                fail("FAIL - should not be able to access large log " +
-                        "after commit");
-            }
+            fail("FAIL - should not be able to access large Blob after commit");
         } catch (SQLException e) {
             checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
-            assertTrue("FAIL - method should not fail when using Derby Client" +
-                    " and JCC", usingEmbedded());
         }
         try {
             blob.position(blob,2);
-            if (usingEmbedded()) {
-                fail("FAIL - should not be able to access large log " +
-                        "after commit");
-            }
+            fail("FAIL - should not be able to access large Blob after commit");
         } catch (SQLException e) {
             checkException(BLOB_ACCESSED_AFTER_COMMIT, e);
-            assertTrue("FAIL - method should not fail when using Derby Client" +
-                    " and JCC", usingEmbedded());
         }
     }