Index: java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java =================================================================== --- java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (revision 545663) +++ java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (working copy) @@ -5100,4 +5100,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); + } + } + } Index: java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java =================================================================== --- java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java (revision 545663) +++ java/engine/org/apache/derby/iapi/jdbc/EngineResultSet.java (working copy) @@ -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; + } Index: java/drda/org/apache/derby/impl/drda/DDMWriter.java =================================================================== --- java/drda/org/apache/derby/impl/drda/DDMWriter.java (revision 545663) +++ java/drda/org/apache/derby/impl/drda/DDMWriter.java (working copy) @@ -734,6 +734,8 @@ out.flush(); }catch(IOException e){ + //System.out.println(e.getMessage()); + // e.printStackTrace(); agent.markCommunicationsFailure ("DDMWriter.writeScalarStream()", "", e.getMessage(), Index: java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java =================================================================== --- java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java (revision 545663) +++ java/drda/org/apache/derby/impl/drda/EXTDTAInputStream.java (working copy) @@ -20,23 +20,21 @@ */ package org.apache.derby.impl.drda; -import java.io.ByteArrayInputStream; 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 java.io.UnsupportedEncodingException; - +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; /** - * @author marsden * * EXTDTAObjectHolder provides Externalized Large Object representation that * does not hold locks until the end of the transaction (DERBY-255) @@ -49,25 +47,28 @@ class EXTDTAInputStream extends InputStream { private InputStream binaryInputStream = null; + + //Stream is initialized (getBinaryStream or getCharacterStream called) + // on the first read. - private boolean isEmptyStream; + /** ResultSet that contains the stream*/ + EngineResultSet rs; + /** Column index starting with 1 */ + int columnNumber; + /** DRDA Type of column */ + int ndrdaType; + - private ResultSet dataResultSet = null; - private Blob blob = null; - private Clob clob = null; - 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; + } @@ -111,46 +112,14 @@ } - /** - * 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; - - } - /** * * * @see java.io.InputStream#read() */ public int read() throws IOException { + return binaryInputStream.read(); } @@ -170,17 +139,9 @@ */ public void close() throws IOException { - try{ if (binaryInputStream != null) binaryInputStream.close(); binaryInputStream = null; - - }finally{ - - blob = null; - clob = null; - dataResultSet = null; - } } @@ -257,60 +218,56 @@ } - 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. + * 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. * * @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. * - * @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); } @@ -323,74 +280,27 @@ " not valid EXTDTA object type"); } } - - boolean exist = is.read() > -1; - - is.close(); - is = null; - - if(exist){ - openInputStreamAgain(); + if (! is.markSupported()) { + is = new BufferedInputStream(is); } - - return exist; - }catch(IllegalStateException e){ - throw Util.javaException(e); - - }finally{ - if(is != null) - is.close(); - - } - + this.binaryInputStream=is; } - - /** - * - * 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()); - } - - }catch(IOException e){ - throw new IllegalStateException(e.getMessage()); - } - - if(! is.markSupported() ){ - is = new BufferedInputStream(is); - } - - this.binaryInputStream = is; - - } - - + protected void finalize() throws Throwable{ close(); } - + /** + * Is the value null. This is determined in the constructor + * by inspecting the ResultSet before the stream is retrieved + * @return true if this value is null + * + */ + public boolean isNull() throws SQLException + { + return this.rs.isNull(columnNumber); + + } } Index: java/drda/org/apache/derby/impl/drda/DRDAConnThread.java =================================================================== --- java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (revision 545663) +++ java/drda/org/apache/derby/impl/drda/DRDAConnThread.java (working copy) @@ -6531,7 +6531,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: @@ -6539,7 +6539,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); @@ -7802,7 +7802,9 @@ Object o = extdtaValues.get(i); if (o instanceof EXTDTAInputStream) { EXTDTAInputStream stream = (EXTDTAInputStream) o; + try{ + stream.initInputStream(); writer.writeScalarStream (chainedWithSameCorrelator, CodePoint.EXTDTA, stream, Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/blobclob4BLOB.out =================================================================== --- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/blobclob4BLOB.out (revision 545663) +++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/blobclob4BLOB.out (working copy) @@ -556,8 +556,7 @@ row 9 is null, skipped clobTest91 finished START: clobTest92 -FAIL -- unexpected exception **************** -SQLSTATE(40XL1): A lock could not be obtained within the time requested +clobTest92 finished START: clobTest93 clobTest92 finished START: clobTest94 Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/blobclob4BLOB.out =================================================================== --- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/blobclob4BLOB.out (revision 545663) +++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/blobclob4BLOB.out (working copy) @@ -560,8 +560,7 @@ row 9 is null, skipped clobTest91 finished START: clobTest92 -FAIL -- unexpected exception **************** -SQLSTATE(40XL1): A lock could not be obtained within the time requested +clobTest92 finished START: clobTest93 clobTest92 finished START: clobTest94 Index: java/testing/org/apache/derbyTesting/functionTests/suites/jdbcapi.runall =================================================================== --- java/testing/org/apache/derbyTesting/functionTests/suites/jdbcapi.runall (revision 556134) +++ java/testing/org/apache/derbyTesting/functionTests/suites/jdbcapi.runall (working copy) @@ -11,6 +11,7 @@ jdbcapi/secureUsers.sql jdbcapi/secureUsers1.sql jdbcapi/maxfieldsize.java +jdbcapi/LargeDataLocks.java jdbcapi/LOBTest.java jdbcapi/blobclob4BLOB.java jdbcapi/parameterMapping.java