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 km...@apache.org on 2007/07/17 21:21:24 UTC

svn commit: r557032 - in /db/derby/code/trunk/java: drda/org/apache/derby/impl/drda/ engine/org/apache/derby/iapi/jdbc/ engine/org/apache/derby/impl/jdbc/

Author: kmarsden
Date: Tue Jul 17 12:21:22 2007
New Revision: 557032

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

Port to 10.4. Verified with 10.2 client running LargeDataLocksTest


Modified:
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java?view=diff&rev=557032&r1=557031&r2=557032
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java Tue Jul 17 12:21:22 2007
@@ -6656,7 +6656,7 @@
 
 					if (SanityManager.DEBUG)
 						trace("!!drdaType = " + java.lang.Integer.toHexString(drdaType) + 
-					 			 "precision = " + precision +" scale = " + scale);
+					 			 " precision=" + precision +" scale = " + scale);
 					switch (ndrdaType)
 					{
 						case DRDAConstants.DRDA_TYPE_NLOBBYTES:
@@ -6664,7 +6664,7 @@
 							EXTDTAInputStream extdtaStream=  
 								EXTDTAInputStream.getEXTDTAStream(rs, i, drdaType);
 							writeFdocaVal(i,extdtaStream, drdaType,
-										  precision,scale,rs.wasNull(),stmt);
+										  precision,scale,extdtaStream.isNull(),stmt);
 							break;
 						case DRDAConstants.DRDA_TYPE_NINTEGER:
 							int ival = rs.getInt(i);
@@ -7946,7 +7946,9 @@
 		Object o  = extdtaValues.get(i);
         if (o instanceof EXTDTAInputStream) {
 			EXTDTAInputStream stream = (EXTDTAInputStream) o;
+                        
 			try{
+                        stream.initInputStream();
 			writer.writeScalarStream (chainedWithSameCorrelator,
 									  CodePoint.EXTDTA,
 									  stream,

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java?view=diff&rev=557032&r1=557031&r2=557032
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java Tue Jul 17 12:21:22 2007
@@ -23,11 +23,13 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.BufferedInputStream;
+import java.io.Reader;
 import java.sql.ResultSet;
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.SQLException;
 
+import org.apache.derby.iapi.jdbc.EngineResultSet;
 import org.apache.derby.iapi.reference.DRDAConstants;
 import org.apache.derby.iapi.services.sanity.SanityManager;
 import org.apache.derby.impl.jdbc.Util;
@@ -45,35 +47,33 @@
 class EXTDTAInputStream extends InputStream {
 
     private InputStream binaryInputStream = null;
-
-    private boolean isEmptyStream;
-	
-    private ResultSet dataResultSet = null;
-    private Blob blob = null;
-    private Clob clob = null;
+ 
+    
+    /** ResultSet that contains the stream*/
+    EngineResultSet rs;
+    /** Column index starting with 1 */
+    int columnNumber;
+    /** DRDA Type of column */
+    int ndrdaType;
+      
 	
 	private EXTDTAInputStream(ResultSet rs,
 				  int columnNumber,
 				  int ndrdaType) 
-	    throws SQLException, IOException
     {
 	
-	    this.dataResultSet = rs;
-	    this.isEmptyStream = ! initInputStream(rs,
-						   columnNumber,
-						   ndrdaType);
-		
-	}
+        this.rs = (EngineResultSet) rs;
+        this.columnNumber = columnNumber;
+        this.ndrdaType = ndrdaType;
+    }
 
     
-    
 	/**
-	 * Retrieve stream from the ResultSet and column specified.  Create an
-	 * input stream for the large object being retrieved. Do not hold
-	 * locks until end of transaction. DERBY-255.
+	 * Create a new EXTDTAInputStream.  Before read the stream must be 
+     * initialized by the user with {@link #initInputStream()} 
 	 * 
-	 * 
-	 * See DDMWriter.writeScalarStream
+	 * @see DDMWriter#writeScalarStream
+     * @see #initInputStream()
 	 * 
 	 * @param rs
 	 *            result set from which to retrieve the lob
@@ -92,61 +92,25 @@
 	 * @throws SQLException
 	 */
 	public static EXTDTAInputStream getEXTDTAStream(ResultSet rs, int column, int drdaType) 
-			throws SQLException {
- 	    try{
+		{
+ 	    
 		int ndrdaType = drdaType | 1; //nullable drdaType
 			
 		return new EXTDTAInputStream(rs,
 					     column,
 					     ndrdaType);
 		
- 	    }catch(IOException e){
- 		throw new SQLException(e.getMessage());
-		}
-		
 	}
 
 	
-	/**
-	 * Get the length of the InputStream 
-	 * This method is currently not used because there seems to be no way to 
-	 * reset the she stream.
-	 *   
-	 * @param binaryInputStream
-	 *            an InputStream whose length needs to be calclulated
-	 * @return length of stream
-	 */
-	private static long getInputStreamLength(InputStream binaryInputStream)
-			throws SQLException {
-		long length = 0;
-		if (binaryInputStream == null)
-			return length;
-		
-		try {
-			for (;;) {
-				int avail = binaryInputStream.available();
-				binaryInputStream.skip(avail);
-				if (avail == 0)
-					break;
-				length += avail;
-				
-			}
-			//binaryInputStream.close();
-		} catch (IOException ioe) {
-			throw Util.javaException(ioe);
-		}
-
-		return length;
-
-	}
-	
 	
 	/**
-	 * 
+	 * Requires {@link #initInputStream()} be called before we can read from the stream
 	 * 
 	 * @see java.io.InputStream#read()
 	 */
 	public int read() throws IOException {
+                       
 		return binaryInputStream.read();
 	}
 
@@ -166,17 +130,9 @@
 	 */
 	public void close() throws IOException {
 	    
-	    try{
 		if (binaryInputStream != null)
 			binaryInputStream.close();	
 		binaryInputStream = null;
-
-	    }finally{
-		
-		blob = null;
-		clob = null;
-		dataResultSet = null;
-	    }
 	    
 	}
 
@@ -256,60 +212,51 @@
 	}
 
 
-    protected boolean isEmptyStream(){
-	return isEmptyStream;
-    }
+    protected boolean isEmptyStream() throws SQLException{
+            return (rs.getLength(columnNumber) == 0);
+        
+        }
     
     
     /**
      * This method takes information of ResultSet and 
-     * initialize binaryInputStream variable of this object with not empty stream and return true.
-     * If the stream was empty, this method remain binaryInputStream null and return false.
-     *
-     * @param rs        ResultSet object to get stream from.
-     * @param column    index number of column in ResultSet to get stream.
-     * @param ndrdaType describe type column to get stream.
+     * initializes the binaryInputStream variable of this object with not empty stream 
+     * by calling getBinaryStream or getCharacterStream() as appropriate.
+     * The Reader returned from getCharacterStream() will be encoded in binarystream.
      *
-     * @return          true if the stream was not empty, false if the stream was empty.
      *
      */
-    private boolean initInputStream(ResultSet rs,
-				    int column,
-				    int ndrdaType)
-	throws SQLException,
-	       IOException
+    public  void initInputStream()
+	throws SQLException
     {
 
 	InputStream is = null;
-	try{
-	    // BLOBS
-	    if (ndrdaType == DRDAConstants.DRDA_TYPE_NLOBBYTES) 
-		{
-		    blob = rs.getBlob(column);
-		    if(blob == null){
-			return false;
-		    }
-		    
-		    is = blob.getBinaryStream();
-		    
-		}
+	Reader r = null;
+	// BLOBS
+	if (ndrdaType == DRDAConstants.DRDA_TYPE_NLOBBYTES) 
+	{ 	    	
+	    is = this.rs.getBinaryStream(this.columnNumber);
+	    if (is == null) 
+              return;
+	}
 	    // CLOBS
-	    else if (ndrdaType ==  DRDAConstants.DRDA_TYPE_NLOBCMIXED)
-		{	
-		    try {
-			clob = rs.getClob(column);
-			
-			if(clob == null){
-			    return false;
-			}
+	else if (ndrdaType ==  DRDAConstants.DRDA_TYPE_NLOBCMIXED)
+	{	
+	    try {
+	        
+	        r = this.rs.getCharacterStream(this.columnNumber);
+		    	
+	        if(r == null){	            
+                    return;
+	        }
 
-			is = new ReEncodedInputStream(clob.getCharacterStream());
+			is = new ReEncodedInputStream(r);
 			
 		    }catch (java.io.UnsupportedEncodingException e) {
-			throw new SQLException (e.getMessage());
+			throw Util.javaException(e);
 			
 		    }catch (IOException e){
-			throw new SQLException (e.getMessage());
+			throw Util.javaException(e);
 			
 		    }
 		    
@@ -322,74 +269,29 @@
 						      " not valid EXTDTA object type");
 			}
 		}
-	    
-	    boolean exist = is.read() > -1;
-	    
-	    is.close();
-	    is = null;
-	    
-	    if(exist){
-		openInputStreamAgain();
-	    }
-
-	    return exist;
-	    
-	}catch(IllegalStateException e){
-	    throw Util.javaException(e);
-
-	}finally{
-	    if(is != null)
-		is.close();
-	    
-	}
-	
-    }
-    
-    
-    /**
-     *
-     * This method is called from initInputStream and 
-     * opens inputstream again to stream actually.
-     *
-     */
-    private void openInputStreamAgain() throws IllegalStateException,SQLException {
-	
-	if(this.binaryInputStream != null){
-	    return;
-	}
-		
-	InputStream is = null;
-	try{
-	    
-	    if(SanityManager.DEBUG){
-		SanityManager.ASSERT( ( blob != null && clob == null ) ||
-				      ( clob != null && blob == null ),
-				      "One of blob or clob must be non-null.");
-	    }
-
-	    if(blob != null){
-		is = blob.getBinaryStream();
-		
-	    }else if(clob != null){
-		is = new ReEncodedInputStream(clob.getCharacterStream());
+	if (! is.markSupported()) {
+	    is = new BufferedInputStream(is);
 	    }
 	    
-	}catch(IOException e){
-	    throw new IllegalStateException(e.getMessage());
-	}
-	
-	if(! is.markSupported() ){
-	    is = new BufferedInputStream(is);
-	}
-
-	this.binaryInputStream = is;
-
+ 	this.binaryInputStream=is;
     }
     
-    
+        
     protected void finalize() throws Throwable{
 	close();
 	}
 
-
+    /**
+     * Is the value null?  Null status is obtained from the underlying 
+     * EngineResultSet, so that it can be determined before the stream
+     * is retrieved.
+     * 
+     * @return true if this value is null
+     * 
+     */
+    public boolean isNull() throws SQLException
+    {
+        return this.rs.isNull(columnNumber);
+     
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java?view=diff&rev=557032&r1=557031&r2=557032
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java Tue Jul 17 12:21:22 2007
@@ -21,6 +21,9 @@
 package org.apache.derby.iapi.jdbc;
 
 import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.error.StandardException;
 /**
  * Additional methods the embedded engine exposes on its ResultSet object
  * implementations. An internal api only, mainly for the network
@@ -32,4 +35,26 @@
      * Is this result set from a select for update statement?
      */
     public boolean isForUpdate();
+    
+    /**
+     * Is the designated columnIndex a null data value?
+     * This is used by EXTDTAInputStream to get the null value without 
+     * retrieving the underlying data value.
+     * @param columnIndex
+     * @return true if the data value at columnIndex for the current row is null 
+     * @throws SQLException 
+     */
+    public boolean isNull(int columnIndex) throws SQLException;
+    
+    /**
+     * Return the length of the designated columnIndex data value.
+     * Implementation is type dependent.
+     * 
+     * @param columnIndex  column to access
+     * @return length of data value
+     * @throws SQLException
+     * @see org.apache.derby.iapi.types.DataValueDescriptor#getLength() 
+     */
+    public int getLength(int columnIndex) throws SQLException;
+    
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?view=diff&rev=557032&r1=557031&r2=557032
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Tue Jul 17 12:21:22 2007
@@ -5051,4 +5051,26 @@
        checkIfClosed("updateClob");
        updateClob(findColumnName(columnName), x);
     }
+    
+    /* 
+     * @see org.apache.derby.iapi.jdbc.EngineResultSet#isNull(int)
+     */
+    public boolean isNull(int columnIndex) throws SQLException{
+        try {
+            DataValueDescriptor dvd = getColumn(columnIndex);
+            return dvd.isNull();
+        } catch (StandardException t) {
+                throw noStateChangeException(t);
+        }
+    }
+    
+    public int getLength(int columnIndex) throws SQLException {
+        try {
+            DataValueDescriptor dvd = getColumn(columnIndex);
+            return dvd.getLength();            
+        } catch (StandardException t) {
+                throw noStateChangeException(t);
+        }
+    }
+    
 }