db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kmars...@apache.org
Subject svn commit: r642974 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Date Mon, 31 Mar 2008 12:23:04 GMT
Author: kmarsden
Date: Mon Mar 31 05:23:02 2008
New Revision: 642974

URL: http://svn.apache.org/viewvc?rev=642974&view=rev
Log:
DERBY-2892 Closing a resultset after retrieving a large > 32665 bytes value with Network
Server does not release locks

Fixes getString(), getCharacaterStream(), getBytes, getBinaryStream() so they don't hold locks.
 Also restricts BLOB columns to a single getXXX call.

Patch contributed by  Oystein Grovlen (oystein dot grovlen at sun dot com)

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/BlobLocatorInputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/UpdateSensitiveLOBLocatorInputStream.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LargeDataLocksTest.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?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- 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 Mon Mar 31 05:23:02
2008
@@ -21,7 +21,6 @@
 
 package org.apache.derby.client.am;
 
-import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -260,7 +259,7 @@
         }
     }
 
-    private java.io.InputStream getBinaryStreamX() throws SqlException {
+    java.io.InputStream getBinaryStreamX() throws SqlException {
         checkForClosedConnection();
 
         if (isBinaryStream())    // this Lob is used for input
@@ -651,8 +650,6 @@
      * @throws SQLException if pos is less than 1 or if pos is greater than
      * the number of bytes in the <code>Blob</code> or if pos + length is
      * greater than the number of bytes in the <code>Blob</code>
-     *
-     * @throws SQLException.
      */
     public InputStream getBinaryStream(long pos, long length)
         throws SQLException {

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
(original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
Mon Mar 31 05:23:02 2008
@@ -21,11 +21,12 @@
 
 package org.apache.derby.client.am;
 
-import java.sql.CallableStatement;
 import java.sql.SQLException;
 
 import java.io.IOException;
 
+import org.apache.derby.shared.common.error.ExceptionUtil;
+import org.apache.derby.shared.common.reference.SQLState;
 import org.apache.derby.shared.common.sanity.SanityManager;
 
 /**
@@ -186,7 +187,38 @@
             throw ioEx;
         }
     }
-    
+
+    /**
+     * Closes this input stream and releases any system resources associated
+     * with the stream.  This will release the underlying Blob value. 
+     *  
+     * @throws java.io.IOException
+     */
+    public void close() throws IOException {
+        try {
+            if (blob != null  && freeBlobOnClose) {
+                blob.free();
+            }
+        } catch (SQLException ex) {
+            if (ex.getSQLState().compareTo
+                    (ExceptionUtil.getSQLStateFromIdentifier
+                            (SQLState.LOB_OBJECT_INVALID)) == 0) {
+                // Blob has already been freed, probably because of autocommit
+                return;  // Ignore error
+            }
+
+            IOException ioEx = new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+
+    /**
+     * Tell stream to free the underlying Blob when it is closed.
+     */
+    public void setFreeBlobOnClose() {
+        freeBlobOnClose = true;
+    }
     
     /**
      * Connection used to read Blob from server.
@@ -209,4 +241,11 @@
      * maxPos starts counting from 1.
      */
     private final long maxPos;
+ 
+    /**
+     * If true, the underlying Blob will be freed when the underlying stream is
+     * closed.  Used to implement correct behavior for streams obtained from
+     * result sets.
+     */
+    private boolean freeBlobOnClose = false;
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java Mon Mar 31 05:23:02
2008
@@ -354,7 +354,7 @@
         }
     }
 
-    private java.io.Reader getCharacterStreamX() throws SqlException {
+    java.io.Reader getCharacterStreamX() throws SqlException {
         checkForClosedConnection();
 
         //check is this Lob is locator enabled
@@ -400,7 +400,7 @@
         }
     }
 
-    private java.io.InputStream getAsciiStreamX() throws SqlException {
+    java.io.InputStream getAsciiStreamX() throws SqlException {
         checkForClosedConnection();
 
         if (isAsciiStream())  // this Lob is used for input

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
(original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
Mon Mar 31 05:23:02 2008
@@ -21,12 +21,13 @@
 
 package org.apache.derby.client.am;
 
-import java.sql.CallableStatement;
 import java.sql.SQLException;
 
 import java.io.IOException;
 
 import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.shared.common.error.ExceptionUtil;
+import org.apache.derby.shared.common.reference.SQLState;
 
 /**
  * An <code>InputStream</code> that will use an locator to fetch the
@@ -63,6 +64,13 @@
     private long currentPos;
     
     /**
+     * If true, the underlying Blob will be freed when the underlying stream is
+     * closed.  Used to implement correct behavior for streams obtained from
+     * result sets.
+     */
+    private boolean freeClobOnClose = false;
+
+    /**
      * Create an <code>InputStream</code> for reading the
      * <code>Clob</code> value represented by the given locator based
      * <code>Clob</code> object.
@@ -158,6 +166,39 @@
             throw ioEx;
         }
     }
+
+    /**
+     * Closes this input stream and releases any system resources associated
+     * with the stream.  This will release the underlying Clob value. 
+     *  
+     * @throws java.io.IOException
+     */
+    public void close() throws IOException {
+        try {
+            if (clob != null  && freeClobOnClose) {
+                clob.free();
+            }
+        } catch (SQLException ex) {
+            if (ex.getSQLState().compareTo
+                    (ExceptionUtil.getSQLStateFromIdentifier
+                            (SQLState.LOB_OBJECT_INVALID)) == 0) {
+                // Clob has already been freed, probably because of autocommit
+                return;  // Ignore error
+            }
+
+            IOException ioEx = new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+      
+    /**
+     * Tell stream to free the underlying Clob when it is closed.
+     */
+    public void setFreeClobOnClose() {
+        freeClobOnClose = true;
+    }
+    
 
     /**
      * Returns a <code>Byte</code> array from the

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java Mon
Mar 31 05:23:02 2008
@@ -23,7 +23,10 @@
 
 import java.io.IOException;
 
+import java.sql.SQLException;
 import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.shared.common.error.ExceptionUtil;
+import org.apache.derby.shared.common.reference.SQLState;
 
 /**
  * An <code>Reader</code> that will use an locator to fetch the
@@ -67,6 +70,13 @@
     private boolean isClosed = false;
     
     /**
+     * If true, the underlying Blob will be freed when the underlying stream is
+     * closed.  Used to implement correct behavior for streams obtained from
+     * result sets.
+     */
+    private boolean freeClobOnClose = false;
+
+    /**
      * Create an <code>Reader</code> for reading the
      * <code>Clob</code> value represented by the given locator based
      * <code>Clob</code> object.
@@ -165,8 +175,32 @@
             return;
         }
         isClosed = true;
+        
+        try {
+            if (clob != null && freeClobOnClose) {
+                clob.free();
+            }
+        } catch (SQLException ex) {
+            if (ex.getSQLState().compareTo
+                    (ExceptionUtil.getSQLStateFromIdentifier
+                            (SQLState.LOB_OBJECT_INVALID)) == 0) {
+                // Clob has already been freed, probably because of autocommit
+                return;  // Ignore error
+            }
+
+            IOException ioEx = new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
     }
-    
+
+    /**
+     * Tell stream to free the underlying Clob when it is closed.
+     */
+    public void setFreeClobOnClose() {
+        freeClobOnClose = true;
+    }
+
     /**
      * Check to see if this <code>Reader</code> is closed. If it
      * is closed throw an <code>IOException</code> that states that

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Cursor.java Mon Mar 31 05:23:02
2008
@@ -23,6 +23,8 @@
 import org.apache.derby.shared.common.reference.SQLState;
 
 import java.sql.SQLException;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
 import java.io.UnsupportedEncodingException;
 
 // When we calculate column offsets make sure we calculate the correct offsets for double
byte charactr5er data
@@ -979,11 +981,16 @@
                 return (maxFieldSize_ == 0) ? tempString :
                         tempString.substring(0, java.lang.Math.min(maxFieldSize_, tempString.length()));
             case java.sql.Types.BLOB:
-                Blob b = (Blob) getBlobColumn_(column, agent_);
-                return agent_.crossConverters_.getStringFromBytes(b.getBytes(1, (int) b.length()));
+                Blob b = getBlobColumn_(column, agent_);
+                tempString = agent_.crossConverters_.
+                        getStringFromBytes(b.getBytes(1, (int) b.length()));
+                b.free();  // Free resources from underlying Blob
+                return tempString;
             case java.sql.Types.CLOB:
                 Clob c = getClobColumn_(column, agent_);
-                return c.getSubString(1, (int) c.length());
+                tempString = c.getSubString(1, (int) c.length());
+                c.free();  // Free resources from underlying Clob
+                return tempString;
             default:
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "String");
@@ -1002,8 +1009,10 @@
             case java.sql.Types.LONGVARBINARY:
                 return get_VARCHAR_FOR_BIT_DATA(column);
             case java.sql.Types.BLOB:
-                Blob b = (Blob) getBlobColumn_(column, agent_);
-                return b.getBytes(1, (int) b.length());
+                Blob b = getBlobColumn_(column, agent_);
+                byte[] bytes = b.getBytes(1, (int) b.length());
+                b.free(); // Free resources from underlying Blob
+                return bytes;
             default:
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "byte[]");
@@ -1013,32 +1022,47 @@
         }
     }
 
-    public final java.io.InputStream getBinaryStream(int column) throws SqlException {
-        try {
-            switch (jdbcTypes_[column - 1]) {
+    public final java.io.InputStream getBinaryStream(int column) 
+            throws SqlException 
+    {
+        switch (jdbcTypes_[column - 1]) {
             case java.sql.Types.BINARY:
                 return new java.io.ByteArrayInputStream(get_CHAR_FOR_BIT_DATA(column));
             case java.sql.Types.VARBINARY:
             case java.sql.Types.LONGVARBINARY:
                 return new java.io.ByteArrayInputStream(get_VARCHAR_FOR_BIT_DATA(column));
             case java.sql.Types.BLOB:
-                Blob b = (Blob) getBlobColumn_(column, agent_);
-                return b.getBinaryStream();
+                Blob b = getBlobColumn_(column, agent_);
+                if (b.isLocator()) {
+                    BlobLocatorInputStream is 
+                            = new BlobLocatorInputStream(agent_.connection_, b);
+                    // Underlying Blob should be released when stream is closed
+                    is.setFreeBlobOnClose();
+                    return new BufferedInputStream(is);
+                } else {
+                    return b.getBinaryStreamX();
+                }
             default:
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "java.io.InputStream");
-            }
-        } catch ( SQLException se ) {
-            throw new SqlException(se);
         }
     }
 
-    public final java.io.InputStream getAsciiStream(int column) throws SqlException {
-        try {
-            switch (jdbcTypes_[column - 1]) {
+    public final java.io.InputStream getAsciiStream(int column) 
+            throws SqlException
+    {
+        switch (jdbcTypes_[column - 1]) {
             case java.sql.Types.CLOB:
                 Clob c = getClobColumn_(column, agent_);
-                return c.getAsciiStream();
+                if (c.isLocator()) {
+                    ClobLocatorInputStream is 
+                            = new ClobLocatorInputStream(agent_.connection_, c);
+                    // Underlying Clob should be released when stream is closed
+                    is.setFreeClobOnClose();
+                    return new BufferedInputStream(is);
+                } else {
+                    return c.getAsciiStreamX();
+                }
             case java.sql.Types.CHAR:
                 try {
                     return new java.io.ByteArrayInputStream(getCHAR(column).getBytes("ISO-8859-1"));
@@ -1062,18 +1086,13 @@
             case java.sql.Types.LONGVARBINARY:
                 return new java.io.ByteArrayInputStream(get_VARCHAR_FOR_BIT_DATA(column));
             case java.sql.Types.BLOB:
-                Blob b = (Blob) getBlobColumn_(column, agent_);
-                return b.getBinaryStream();
+                return getBinaryStream(column);
             default:
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "java.io.InputStream");
-            }
-        }
-        catch ( SQLException se ) {
-            throw new SqlException(se);
         }
     }
-
+ 
     public final java.io.InputStream getUnicodeStream(int column) throws SqlException {
         try {
             switch (jdbcTypes_[column - 1]) {
@@ -1081,6 +1100,7 @@
                 {
                     Clob c = getClobColumn_(column, agent_);
                     String s = c.getSubString(1L, (int) c.length());
+                    c.free(); // Release resources from underlying Clob
                     try {
                         return new java.io.ByteArrayInputStream(s.getBytes("UTF-8"));
                     } catch (java.io.UnsupportedEncodingException e) {
@@ -1114,8 +1134,7 @@
             case java.sql.Types.LONGVARBINARY:
                 return new java.io.ByteArrayInputStream(get_VARCHAR_FOR_BIT_DATA(column));
             case java.sql.Types.BLOB:
-                Blob b = (Blob) getBlobColumn_(column, agent_);
-                return b.getBinaryStream();
+                return getBinaryStream(column);
             default:
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "UnicodeStream");
@@ -1125,12 +1144,21 @@
         }
     }
 
-    public final java.io.Reader getCharacterStream(int column) throws SqlException {
-        try {
-            switch (jdbcTypes_[column - 1]) {
+    public final java.io.Reader getCharacterStream(int column) 
+            throws SqlException 
+    {
+        switch (jdbcTypes_[column - 1]) {
             case java.sql.Types.CLOB:
                 Clob c = getClobColumn_(column, agent_);
-                return c.getCharacterStream();
+                if (c.isLocator()) {
+                    ClobLocatorReader reader
+                            = new ClobLocatorReader(agent_.connection_, c);
+                    //  Make sure underlying Blob is released when reader is closed
+                    reader.setFreeClobOnClose();
+                    return new BufferedReader(reader);
+                } else {
+                    return c.getCharacterStreamX();
+                }
             case java.sql.Types.CHAR:
                 return new java.io.StringReader(getCHAR(column));
             case java.sql.Types.VARCHAR:
@@ -1155,8 +1183,8 @@
                 }
             case java.sql.Types.BLOB:
                 try {
-                    Blob b = (Blob) getBlobColumn_(column, agent_);
-                    return new java.io.InputStreamReader(b.getBinaryStream(), "UTF-16BE");
+                    return new java.io.InputStreamReader(getBinaryStream(column),
+                                                         "UTF-16BE");
                 } catch (java.io.UnsupportedEncodingException e) {
                     throw new SqlException(agent_.logWriter_, 
                     		new ClientMessageId (SQLState.UNSUPPORTED_ENCODING), 
@@ -1166,9 +1194,6 @@
                 throw new ColumnTypeConversionException(agent_.logWriter_,
                     "java.sql.Types " + jdbcTypes_[column -1], "java.io.Reader");
             }
-        } catch ( SQLException se ) {
-            throw new SqlException(se);
-        }
     }
 
     public final java.sql.Blob getBlob(int column) throws SqlException {

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java Mon Mar 31 05:23:02
2008
@@ -426,6 +426,7 @@
         if (!openOnClient_) {
             return;
         }
+        closeCloseFilterInputStream();
         preClose_();
         try {
             if (openOnServer_) {

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/UpdateSensitiveLOBLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/UpdateSensitiveLOBLocatorInputStream.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/UpdateSensitiveLOBLocatorInputStream.java
(original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/UpdateSensitiveLOBLocatorInputStream.java
Mon Mar 31 05:23:02 2008
@@ -160,6 +160,13 @@
         currentPos += ret;
         return ret;
     }
+
+    public void close() throws IOException 
+    {
+       if (is != null) {
+            is.close();
+        }
+    }
     
     /**
      * Verifies whether the current updateCount matches

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LargeDataLocksTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LargeDataLocksTest.java?rev=642974&r1=642973&r2=642974&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LargeDataLocksTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/LargeDataLocksTest.java
Mon Mar 31 05:23:02 2008
@@ -197,7 +197,7 @@
         TestSuite suite = new TestSuite("LargeDataLocksTest");
         suite.addTest(baseSuite("LargeDataLocksTest:embedded"));
         // Disable for client until DERBY-2892 is fixed
-        //suite.addTest(TestConfiguration.clientServerDecorator(baseSuite("LargeDataLocksTest:client")));
+        suite.addTest(TestConfiguration.clientServerDecorator(baseSuite("LargeDataLocksTest:client")));
         return suite;
 
     }



Mime
View raw message