db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kmars...@apache.org
Subject svn commit: r327012 - in /db/derby/code/branches/10.1/java: engine/org/apache/derby/iapi/reference/ engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/impl/store/raw/data/ engine/org/apache/derby/loc/ testing/org/apache/derbyTesting/functionTes...
Date Thu, 20 Oct 2005 22:18:53 GMT
Author: kmarsden
Date: Thu Oct 20 15:18:36 2005
New Revision: 327012

URL: http://svn.apache.org/viewcvs?rev=327012&view=rev
Log:
DERBY-500 - Update/Select failure when BLOB/CLOB fields updated in several rows by PreparedStatement
using setBinaryStream and setCharacterStream

Sunitha merged  r326307 from trunk manually because of conflicts.

Contributed by Sunitha Kambhampati (ksunithaghm@gmail.com)



Modified:
    db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/RawToBinaryFormatStream.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/ReaderToUTF8Stream.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/RememberBytesInputStream.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties
    db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/forbitdata.out
    db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
    db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/lang/forbitdata.java
    db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn.java
    db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn_derby.properties

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
(original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
Thu Oct 20 15:18:36 2005
@@ -1358,6 +1358,7 @@
     String INVALID_JDBCTYPE = "XJ021.S";
     String SET_STREAM_FAILURE = "XJ022.S";
     String SET_STREAM_INEXACT_LENGTH_DATA = "XJ023.S";
+    String STREAM_EOF = "XJ085.S";
     String SET_UNICODE_INVALID_LENGTH = "XJ024.S";
     String NEGATIVE_STREAM_LENGTH = "XJ025.S";
     String NO_AUTO_COMMIT_ON = "XJ030.S";

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/RawToBinaryFormatStream.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/RawToBinaryFormatStream.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/RawToBinaryFormatStream.java
(original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/RawToBinaryFormatStream.java
Thu Oct 20 15:18:36 2005
@@ -23,6 +23,7 @@
 import java.io.InputStream;
 import java.io.FilterInputStream;
 import java.io.IOException;
+import java.io.EOFException;
 
 import org.apache.derby.iapi.services.io.LimitInputStream;
 import org.apache.derby.iapi.services.i18n.MessageService;
@@ -32,10 +33,16 @@
 	Stream that takes a raw input stream and converts it
 	to the format of the binary types by prepending the
 	length of the value. In this case 0 is always written.
+    Note: This stream cannot be re-used. Once end of file is
+    reached, the next read call will throw an EOFException
 */
 class RawToBinaryFormatStream extends LimitInputStream {
 
 	private int dummyBytes = 4;
+    
+    // flag to indicate the stream has already been read
+    // and eof reached
+    private boolean eof = false;
 
 	/**
 		@param	in Application's raw binary stream passed into JDBC layer
@@ -50,9 +57,15 @@
 
 	/**
 		Read from the wrapped stream prepending the intial bytes if needed.
+        If stream has been read, and eof reached, in that case any subsequent
+        read will throw an EOFException
 	*/
 	public int read() throws IOException {
 
+        if ( eof )
+            throw new EOFException(MessageService.getTextMessage
+                        (SQLState.STREAM_EOF));
+        
 		if (dummyBytes != 0) {
 			dummyBytes--;
 			return 0;
@@ -73,8 +86,13 @@
 	*/
 	private void checkSufficientData() throws IOException
 	{
+        // if we reached here, then read call returned -1, and we 
+        // have already reached the end of stream, so set eof=true
+        // so that subsequent reads on this stream will return an 
+        // EOFException
+        eof = true;
 		if (!limitInPlace)
-			return;
+        return;
 
 		int remainingBytes = clearLimit();
 
@@ -99,8 +117,13 @@
 
 	/**
 		Read from the wrapped stream prepending the intial bytes if needed.
+        If stream has been read, and eof reached, in that case any subsequent
+        read will throw an EOFException
 	*/
 	public int read(byte b[], int off, int len) throws IOException {
+  
+        if ( eof )
+            throw new EOFException(MessageService.getTextMessage(SQLState.STREAM_EOF));
 
 		int dlen = dummyBytes;
 
@@ -124,7 +147,6 @@
 				return dlen;
 
 			checkSufficientData();
-
 			return realRead;
 		}
 

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/ReaderToUTF8Stream.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/ReaderToUTF8Stream.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/ReaderToUTF8Stream.java
(original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/jdbc/ReaderToUTF8Stream.java
Thu Oct 20 15:18:36 2005
@@ -54,8 +54,22 @@
 		blen = -1;
 	}
 
+    /**
+     * read from stream; characters converted to utf-8 derby specific encoding.
+     * If stream has been read, and eof reached, in that case any subsequent
+     * read will throw an EOFException
+     * @see java.io.InputStream#read()
+     */
 	public int read() throws IOException {
 
+        // when stream has been read and eof reached, stream is closed
+        // and buffer is set to null ( see close() method)
+        // since stream cannot be re-used, check if stream is closed and 
+        // if so throw an EOFException
+        if ( buffer == null)
+            throw new EOFException(MessageService.getTextMessage(SQLState.STREAM_EOF));
+
+        
 		// first read
 		if (blen < 0)
 			fillBuffer(2);
@@ -64,7 +78,14 @@
 		{
 			// reached end of buffer, read more?
 			if (eof)
-				return -1;
+            {
+               // we have reached the end of this stream
+               // cleanup here and return -1 indicating 
+               // eof of stream
+               close();
+               return -1;
+            }
+                
 
 			fillBuffer(0);
 		}
@@ -74,7 +95,16 @@
 	}
 
 	public int read(byte b[], int off, int len) throws IOException {
-		// first read
+        
+        // when stream has been read and eof reached, stream is closed
+        // and buffer is set to null ( see close() method)
+        // since stream cannot be re-used, check if stream is closed and 
+        // if so throw an EOFException
+        if ( buffer == null )
+            throw new EOFException(MessageService.getTextMessage
+                    (SQLState.STREAM_EOF));
+
+        // first read
 		if (blen < 0)
 			fillBuffer(2);
 
@@ -90,8 +120,18 @@
 			{
 				if (eof)
 				{
-					return readCount == 0 ? readCount : -1;
-				}
+                    if (readCount > 0)
+                    {
+                        return readCount;
+                    }
+                    else
+                    {
+                        // we have reached the eof, so close the stream
+                        close();
+                        return -1;  
+                    }
+                }
+                    
 				fillBuffer(0);
 				continue;
 			}
@@ -105,7 +145,6 @@
 			readCount += copyBytes;
 
 		}
-
 		return readCount;
 	}
 
@@ -184,6 +223,7 @@
 
 			buffer[0] = (byte) ((utflen >>> 8) & 0xFF);
 			buffer[1] = (byte) ((utflen >>> 0) & 0xFF);
+
 		}
 		else
 		{
@@ -193,10 +233,23 @@
 		}
 	}
 
+    /**
+     * return resources 
+     */
 	public void close() throws IOException
 	{
-		buffer = null;
-		reader.close();
+        // since stream has been read and eof reached, return buffer back to 
+        // the vm.
+        // Instead of using another variable to indicate stream is closed
+        // a check on (buffer==null) is used instead. 
+        buffer = null;
+
+        // Note : Do not call reader.close() here since the reader 
+        // holds the user's stream and calling reader.close would close
+        // the user's stream and that is incorrect. Derby must not
+        // close the user's stream, but it is the responsibility of the 
+        // application to close the stream or do whatever the application
+        // wishes.
 	}
 
     /**

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/RememberBytesInputStream.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/RememberBytesInputStream.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/RememberBytesInputStream.java
(original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/RememberBytesInputStream.java
Thu Oct 20 15:18:36 2005
@@ -44,6 +44,12 @@
 {
 	ByteHolder bh;
 	boolean recording = true;
+    
+    // In case of streams (e.g ReaderToUTF8Stream,
+    // RawToBinaryFormatStream) that cannot be re-used
+    // a read on a closed stream will throw an EOFException
+    // hence keep track if the stream is closed or not
+    boolean streamClosed = false;
 	
 	/**
 	  Construct a RememberBytesInputStream.
@@ -58,6 +64,7 @@
             SanityManager.ASSERT(bh.writingMode());
 
 		this.bh = bh;
+
 	}
 	
 	/**
@@ -69,10 +76,19 @@
 		if (SanityManager.DEBUG)
 			SanityManager.ASSERT(recording,
 								 "Must be in record mode to perform a read.");
-		int value = super.read();
-		if (value != -1)
-			bh.write(value);
-		return value;
+		
+        int value = -1;
+        
+        if ( !streamClosed )
+        {
+            value = super.read();
+            if ( value != -1 )
+                bh.write(value);
+            else
+                streamClosed =true;
+        }
+		
+        return value;
 	}
 
 	/**
@@ -84,22 +100,46 @@
 		if (SanityManager.DEBUG)
 			SanityManager.ASSERT(recording,
 								 "Must be in record mode to perform a read.");
-		if ((len + off) > b.length)
-			len = b.length - off;
-		len = super.read(b,off,len);
-		if (len != -1)
-			bh.write(b,off,len);
-		return len;
+		
+        if ( !streamClosed ) {
+            if ((len + off) > b.length)
+                len = b.length - off;
+
+            len = super.read(b, off, len);
+            if (len > 0 )
+                bh.write(b, off, len);
+            else
+                streamClosed = true;
+        } else {
+            return -1;
+        }
+
+        return len;
 	}
 
 	/**
 	  read len bytes from the input stream, and store it in the byte holder.
 
+      Note, fillBuf does not return negative values, if there are no 
+      bytes to store in the byteholder, it will return 0
 	  @exception IOException thrown on an io error spooling rememberd bytes
 	             to backing storage.
 	  */
 	public long fillBuf(int len) throws IOException{
-		return bh.write(this.in, len);
+        
+        long val = 0;
+
+        if ( !streamClosed )
+        {
+            val = bh.write(this.in, len);
+            
+            // if bh.write returns less than len, then the stream
+            // has reached end of stream. See logic in MemByteHolder.write
+            if ( val < len )
+                streamClosed=true;
+        }       
+
+        return val;
 	}
 
 	/**
@@ -160,6 +200,7 @@
 	 */
 	public void setInput(InputStream in) {
 		this.in = in;
+        streamClosed = false;
 	}
 
 	/**

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
(original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
Thu Oct 20 15:18:36 2005
@@ -6154,6 +6154,13 @@
                 // into the RememberBytesInputStream.
                 if (row[arrayPosition] instanceof StreamStorable)
                     ((StreamStorable)row[arrayPosition]).setStream(bufferedIn);
+                
+                // set column to the RememberBytesInputStream so that 
+                // all future access to this column will be able to get 
+                // at bytes that have been already read. This assignment
+                // is needed to ensure that if long column exception is 
+                // thrown, the column is set correctly
+                column = bufferedIn;
 			}
 
 			// read the buffer by reading the max we can read.

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties Thu
Oct 20 15:18:36 2005
@@ -1096,7 +1096,7 @@
 XJ082.U=BLOB/CLOB values are not allowed as method parameters or receiver.
 XJ083.U=''{0}'' not allowed because the ResultSet is not an updatable ResultSet. 
 XJ084.U=Column does not correspond to a column in the base table. Cannot issue ''{0}'' on
this column.
-
+XJ085.S=Stream has already been read and end-of-file reached and cannot be re-used.
 0A000.S=Feature not implemented: {0}.
 
 XJ004.C=Database ''{0}'' not found.

Modified: db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/forbitdata.out
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/forbitdata.out?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/forbitdata.out
(original)
+++ db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/forbitdata.out
Thu Oct 20 15:18:36 2005
@@ -599,32 +599,62 @@
 START testEncodedLengths
  EL byte[] 10 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 10 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 10 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 10 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 30 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 30 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 30 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 30 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 31 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 31 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 31 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 31 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 32 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 32 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 32 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 32 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 1345 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 1345 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 1345 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 1345 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 23456 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 23456 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 23456 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 23456 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL byte[] 32672 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
  EL stream 32672 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 32672 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL stream 32672 C1 OK DATA OK C2 OK DATA OK C3 OK DATA OK
+ EL byte[] 32700 C1 NULL C2 OK DATA OK C3 OK DATA OK
+ EL stream 32700 C1 NULL C2 OK DATA OK C3 OK DATA OK
  EL byte[] 32700 C1 NULL C2 OK DATA OK C3 OK DATA OK
  EL stream 32700 C1 NULL C2 OK DATA OK C3 OK DATA OK
  EL byte[] 32767 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 32767 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 32767 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 32767 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 32768 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 32768 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 32768 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 32768 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 32769 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 32769 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 32769 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 32769 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 65535 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 65535 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 65535 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 65535 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 65536 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 65536 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 65536 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 65536 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 65537 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 65537 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 65537 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 65537 C1 NULL C2 NULL C3 OK DATA OK
+ EL byte[] 115882 C1 NULL C2 NULL C3 OK DATA OK
+ EL stream 115882 C1 NULL C2 NULL C3 OK DATA OK
  EL byte[] 115882 C1 NULL C2 NULL C3 OK DATA OK
  EL stream 115882 C1 NULL C2 NULL C3 OK DATA OK
 END testEncodedLengths

Modified: db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
(original)
+++ db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/master/streamingColumn.out
Thu Oct 20 15:18:36 2005
@@ -98,4 +98,39 @@
 ===> testing trailing non-blanks(using setObject) length = 32703
 expected exception for data > 32700 in length
 Test 13 - long varchar truncation tests end in here
+======================================
+START  DERBY-500 TEST 
+Inserting rows 
+Rows inserted =10
+Rows selected =10
+Update qualifies many rows + streams
+EXPECTED EXCEPTION - streams cannot be re-used
+EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
+EXPECTED SQL Exception: (XJ001) Java exception: 'Stream has already been read and end-of-file
reached and cannot be re-used.: java.io.EOFException'.
+Rows selected =10
+DERBY500 #2 Rows updated  =1
+Rows selected =1
+DERBY500 #3 Rows deleted =10
+Rows selected =0
+DERBY500 #4 Rows deleted  =0
+Rows selected =0
+EXPECTED EXCEPTION - streams cannot be re-used
+EXPECTED SQL Exception: (XSDA4) An unexpected exception was thrown
+EXPECTED SQL Exception: (XJ001) Java exception: 'Stream has already been read and end-of-file
reached and cannot be re-used.: java.io.EOFException'.
+END  DERBY-500 TEST 
+======================================
+======================================
+START  DERBY-500 TEST for varchar 
+Rows inserted =10
+Rows selected =10
+DERBY500 for varchar #1 Rows updated  =11
+Rows selected =10
+DERBY500 for varchar #2 Rows updated  =1
+Rows selected =1
+DERBY500 for varchar #3 Rows deleted =11
+Rows selected =0
+DERBY500 for varchar #4 Rows deleted  =0
+Rows selected =0
+END  DERBY-500 TEST  for varchar
+======================================
 Test streamingColumn finished

Modified: db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/lang/forbitdata.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/lang/forbitdata.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/lang/forbitdata.java
(original)
+++ db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/lang/forbitdata.java
Thu Oct 20 15:18:36 2005
@@ -717,44 +717,7 @@
 		psi.executeUpdate();
 		conn.commit();
 
-		ResultSet rs = pss.executeQuery();
-		while (rs.next())
-		{
-			System.out.print(" EL byte[] " + length);
-			byte[] v = rs.getBytes(1);
-			if (v != null) {
-				System.out.print(" C1 " + ((v.length == length) ? "OK" : ("FAIL <" + v.length + ">")));
-				System.out.print(" DATA " + ((v[off] == 0x23) ? "OK" : ("FAIL " + off)));
-			}
-			else
-				System.out.print(" C1 NULL");
-
-			v = rs.getBytes(2);
-			if (v != null) {
-				System.out.print(" C2 " + ((v.length == length) ? "OK" : ("FAIL <" + v.length + ">")));
-				System.out.print(" DATA " + ((v[off] == 0x23) ? "OK" : ("FAIL " + off)));
-			}
-			else
-				System.out.print(" C2 NULL");
-			InputStream c3 = rs.getBinaryStream(3);
-			checkEncodedLengthValue("C3", c3, length, off);
-
-			System.out.println("");
-		}
-		rs.close();
-
-		rs = pss.executeQuery();
-		while (rs.next())
-		{
-			System.out.print(" EL stream " + length);
-
-			checkEncodedLengthValue("C1", rs.getBinaryStream(1), length, off);
-			checkEncodedLengthValue("C2", rs.getBinaryStream(2), length, off);
-			checkEncodedLengthValue("C3", rs.getBinaryStream(3), length, off);
-
-			System.out.println("");
-		}
-		rs.close();
+		selectData(pss,data,off,length);
 
 		conn.commit();
 
@@ -762,21 +725,68 @@
 		conn.commit();
 
 
+        // Set values using stream and then verify that select is successful
 		psi.setBinaryStream(1, (length <= 32672) ? new java.io.ByteArrayInputStream(data) :
null, length);
 		psi.setBinaryStream(2, (length <= 32700) ? new java.io.ByteArrayInputStream(data) :
null, length);
 		psi.setBinaryStream(3, new java.io.ByteArrayInputStream(data), length); // BLOB column
 		psi.executeUpdate();
 		conn.commit();
 
-		psd.executeUpdate();
+		selectData(pss,data,off,length);
 
+        conn.commit();
 
 
+		psd.executeUpdate();
 		conn.commit();
 
 
 	}
 
+    private static void selectData(PreparedStatement pss,byte[] data,int off,int length)
+        throws SQLException,IOException
+    {
+        
+        ResultSet rs = pss.executeQuery();
+        while (rs.next())
+        {
+            System.out.print(" EL byte[] " + length);
+            byte[] v = rs.getBytes(1);
+            if (v != null) {
+                System.out.print(" C1 " + ((v.length == length) ? "OK" : ("FAIL <" + v.length
+ ">")));
+                System.out.print(" DATA " + ((v[off] == 0x23) ? "OK" : ("FAIL " + off)));
+            }
+            else
+                System.out.print(" C1 NULL");
+
+            v = rs.getBytes(2);
+            if (v != null) {
+                System.out.print(" C2 " + ((v.length == length) ? "OK" : ("FAIL <" + v.length
+ ">")));
+                System.out.print(" DATA " + ((v[off] == 0x23) ? "OK" : ("FAIL " + off)));
+            }
+            else
+                System.out.print(" C2 NULL");
+            InputStream c3 = rs.getBinaryStream(3);
+            checkEncodedLengthValue("C3", c3, length, off);
+
+            System.out.println("");
+        }
+        rs.close();
+
+        rs = pss.executeQuery();
+        while (rs.next())
+        {
+            System.out.print(" EL stream " + length);
+
+            checkEncodedLengthValue("C1", rs.getBinaryStream(1), length, off);
+            checkEncodedLengthValue("C2", rs.getBinaryStream(2), length, off);
+            checkEncodedLengthValue("C3", rs.getBinaryStream(3), length, off);
+
+            System.out.println("");
+        }
+        rs.close();
+
+    }
 	private static void checkEncodedLengthValue(String col, InputStream is, int length, int
off) throws IOException {
 
 		if (is == null) {

Modified: db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn.java
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn.java?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn.java
(original)
+++ db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn.java
Thu Oct 20 15:18:36 2005
@@ -92,7 +92,9 @@
 			streamTest5(conn, 0);
 			streamTest5(conn, 1500);
 			streamTest5(conn, 5000);
-			streamTest5(conn, 100000);
+            // This test fails when running w/ derby.language.logStatementText=true
+            // see DERBY-595 
+            //streamTest5(conn, 100000);
 
 			streamTest6(conn, 5000);
 			streamTest7(conn);
@@ -117,6 +119,19 @@
 			// bug 5592 test - any character(including blank character) truncation should give error
for long varchars
 			streamTest13(conn);
 
+            
+            
+            // Derby500
+            // user supplied stream parameter values are not re-used
+            derby500Test(conn);
+
+            // currently in case of char,varchar,long varchar types
+            // stream paramter value is materialized the first time around
+            // and used for executions. Hence verify that the fix to 
+            // DERBY-500 did not change the behavior for char,varchar
+            // and long varchar types when using streams.
+            derby500_verifyVarcharStreams(conn);
+            
 			// turn autocommit on because in JCC, java.sql.Connection.close() can not be
 			// requested while a transaction is in progress on the connection.
 			// If autocommit is off in JCC, the transaction remains active, 
@@ -1145,6 +1160,438 @@
 	}
 
 
+
+    /**
+     * Streams are not re-used. This test tests the fix for 
+     * DERBY-500. If an update statement has multiple rows that
+     * is affected, and one of the parameter values is a stream,
+     * the update will fail because streams are not re-used.
+     * @param conn database connection
+     */
+    private static void derby500Test(Connection conn) {
+
+        Statement stmt;
+
+        System.out.println("======================================");
+        System.out.println("START  DERBY-500 TEST ");
+
+        try {
+            stmt = conn.createStatement();
+            conn.setAutoCommit(false);
+            stmt.execute("CREATE TABLE t1 (" + "id INTEGER NOT NULL,"
+                    + "mname VARCHAR( 254 ) NOT NULL," + "mvalue INT NOT NULL,"
+                    + "bytedata BLOB NOT NULL," + "chardata CLOB NOT NULL,"
+                    + "PRIMARY KEY ( id ))");
+
+            PreparedStatement ps = conn
+                    .prepareStatement("insert into t1 values (?,?,?,?,?)");
+
+            // insert 10 rows.
+            int rowCount = 0;
+            // use blob and clob values
+            int len = 10000;
+            byte buf[] = new byte[len];
+            char cbuf[] = new char[len];
+            char orig =  'c';
+            for (int i = 0; i < len; i++) {
+                buf[i] = (byte)orig;
+                cbuf[i] = orig;
+            }
+            int randomOffset = 9998;
+            buf[randomOffset] = (byte) 'e';
+            cbuf[randomOffset] = 'e';
+            System.out.println("Inserting rows ");
+            for (int i = 0; i < 10; i++) {
+                ps.setInt(1, i);
+                ps.setString(2, "mname" + i);
+                ps.setInt(3, 0);
+                ps.setBinaryStream(4, new ByteArrayInputStream(buf), len);
+                ps.setAsciiStream(5, new ByteArrayInputStream(buf), len);
+                rowCount += ps.executeUpdate();
+            }
+            conn.commit();
+            System.out.println("Rows inserted =" + rowCount);
+
+            
+            //conn.commit();
+            PreparedStatement pss = conn
+                    .prepareStatement(" select chardata,bytedata from t1 where id = ?");
+            verifyDerby500Test(pss, buf, cbuf,0, 10, true);
+            
+            // do the update, update must qualify more than 1 row and update will fail
+            // as currently we dont allow stream values to be re-used
+            PreparedStatement psu = conn
+                    .prepareStatement("update t1 set bytedata = ? "
+                            + ", chardata = ? where mvalue = ?  ");
+
+            buf[randomOffset + 1] = (byte) 'u';
+            cbuf[randomOffset +1] = 'u';
+            rowCount = 0;
+            System.out.println("Update qualifies many rows + streams");
+
+            try {
+                psu.setBinaryStream(1, new ByteArrayInputStream(buf), len);
+                psu.setCharacterStream(2, new CharArrayReader(cbuf), len);
+                psu.setInt(3, 0);
+                rowCount += psu.executeUpdate();
+                System.out.println("DERBY500 #1 Rows updated  ="
+                        + rowCount);
+
+            } catch (SQLException sqle) {
+                System.out
+                        .println("EXPECTED EXCEPTION - streams cannot be re-used");
+                expectedException(sqle);
+                conn.rollback();
+            }
+            
+            //verify data
+            //set back buffer value to what was inserted.
+            buf[randomOffset + 1] = (byte)orig;
+            cbuf[randomOffset + 1] = orig;
+            
+            verifyDerby500Test(pss, buf,cbuf, 0, 10,true);
+
+            PreparedStatement psu2 = conn
+                    .prepareStatement("update t1 set bytedata = ? "
+                            + ", chardata = ? where id = ?  ");
+
+            buf[randomOffset + 1] = (byte) 'u';
+            cbuf[randomOffset + 1] = 'u';
+            
+            rowCount = 0;
+            try {
+                psu2.setBinaryStream(1, new ByteArrayInputStream(buf), len);
+                psu2.setAsciiStream(2, new ByteArrayInputStream(buf), len);
+                psu2.setInt(3, 0);
+                rowCount += psu2.executeUpdate();
+                System.out.println("DERBY500 #2 Rows updated  ="
+                        + rowCount);
+
+            } catch (SQLException sqle) {
+                System.out
+                        .println("UNEXPECTED EXCEPTION - update should have actually gone
through");
+                dumpSQLExceptions(sqle);
+            }
+            conn.commit();
+            verifyDerby500Test(pss, buf,cbuf, 0, 1,true);
+            
+            // delete
+            // as currently we dont allow stream values to be re-used
+            PreparedStatement psd = conn
+                    .prepareStatement("delete from t1 where mvalue = ?");
+
+            rowCount = 0;
+            try {
+                psd.setInt(1, 0);
+                rowCount += psd.executeUpdate();
+                rowCount += psd.executeUpdate();
+                System.out.println("DERBY500 #3 Rows deleted ="
+                        + rowCount);
+
+            } catch (SQLException sqle) {
+                System.out
+                .println("UNEXPECTED EXCEPTION - delete should have actually gone through");
+                dumpSQLExceptions(sqle);
+            }
+
+            conn.commit();
+            //verify data
+           
+            verifyDerby500Test(pss, buf,cbuf, 0, 10, true);
+
+            PreparedStatement psd2 = conn
+                    .prepareStatement("delete from t1 where id = ?");
+            
+            rowCount = 0;
+            try {
+                psd2.setInt(1, 0);
+                rowCount += psd2.executeUpdate();
+                System.out.println("DERBY500 #4 Rows deleted  ="
+                        + rowCount);
+
+            } catch (SQLException sqle) {
+                System.out
+                        .println("UNEXPECTED EXCEPTION - delete should have actually gone
through");
+                dumpSQLExceptions(sqle);
+            }
+            conn.commit();
+            verifyDerby500Test(pss, buf,cbuf, 1, 2,true);
+
+            try
+            {
+                ps.setInt(1,11);
+                rowCount += ps.executeUpdate();
+                System.out.println("Rows inserted = "+ rowCount);
+            } catch (SQLException sqle) {
+                System.out
+                        .println("EXPECTED EXCEPTION - streams cannot be re-used");
+                expectedException(sqle);
+                conn.rollback();
+            }
+
+            stmt.execute("drop table t1");
+            conn.commit();
+            stmt.close();
+            pss.close();
+            psu2.close();
+            psu.close();
+            psd.close();
+            psd2.close();
+            System.out.println("END  DERBY-500 TEST ");
+            System.out.println("======================================");
+
+        } catch (SQLException sqle) {
+            dumpSQLExceptions(sqle);
+        } catch (Exception e) {
+            System.out.println("DERBY-500 TEST FAILED!");
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * Test that DERBY500 fix did not change the behavior for varchar,
+     * char, long varchar types when stream api is used. 
+     * Currently, for char,varchar and long varchar - the stream is 
+     * read once and materialized, hence the materialized stream value
+     * will/can be used for multiple executions of the prepared statement  
+     * @param conn database connection
+     */
+    private static void derby500_verifyVarcharStreams(Connection conn) {
+
+        Statement stmt;
+
+        System.out.println("======================================");
+        System.out.println("START  DERBY-500 TEST for varchar ");
+
+        try {
+            stmt = conn.createStatement();
+            stmt.execute("CREATE TABLE t1 (" + "id INTEGER NOT NULL,"
+                    + "mname VARCHAR( 254 ) NOT NULL," + "mvalue INT NOT NULL,"
+                    + "vc varchar(32500)," + "lvc long varchar NOT NULL,"
+                    + "PRIMARY KEY ( id ))");
+
+            PreparedStatement ps = conn
+                    .prepareStatement("insert into t1 values (?,?,?,?,?)");
+
+            // insert 10 rows.
+            int rowCount = 0;
+            // use blob and clob values
+            int len = 10000;
+            byte buf[] = new byte[len];
+            char cbuf[] = new char[len];
+            char orig =  'c';
+            for (int i = 0; i < len; i++) {
+                buf[i] = (byte)orig;
+                cbuf[i] = orig;
+            }
+            int randomOffset = 9998;
+            buf[randomOffset] = (byte)'e';
+            cbuf[randomOffset] = 'e';
+            for (int i = 0; i < 10; i++) {
+                ps.setInt(1, i);
+                ps.setString(2, "mname" + i);
+                ps.setInt(3, 0);
+                ps.setCharacterStream(4, new CharArrayReader(cbuf), len);
+                ps.setAsciiStream(5, new ByteArrayInputStream(buf), len);
+                rowCount += ps.executeUpdate();
+            }
+            conn.commit();
+            System.out.println("Rows inserted =" + rowCount);
+
+            try
+            {
+                ps.setInt(1,11);
+                rowCount += ps.executeUpdate();
+            } catch (SQLException sqle) {
+                System.out.println("UNEXPECTED EXCEPTION - streams cannot be "+
+                   "re-used but in case of varchar, stream is materialized the"+
+                   " first time around. So multiple executions using streams should "+
+                   " work fine. ");
+                dumpSQLExceptions(sqle);
+            }
+            
+            PreparedStatement pss = conn
+                    .prepareStatement(" select lvc,vc from t1 where id = ?");
+            verifyDerby500Test(pss, buf, cbuf,0, 10,false);
+            
+            // do the update, update must qualify more than 1 row and update will
+            // pass for char,varchar,long varchar columns.
+            PreparedStatement psu = conn
+                    .prepareStatement("update t1 set vc = ? "
+                            + ", lvc = ? where mvalue = ?  ");
+
+            buf[randomOffset +1] = (byte)'u';
+            cbuf[randomOffset +1] = 'u';
+            rowCount = 0;
+            try {
+                psu.setAsciiStream(1, new ByteArrayInputStream(buf), len);
+                psu.setCharacterStream(2, new CharArrayReader(cbuf), len);
+                psu.setInt(3, 0);
+                rowCount += psu.executeUpdate();
+            } catch (SQLException sqle) {
+                System.out
+                        .println("EXPECTED EXCEPTION - streams cannot be re-used");
+                expectedException(sqle);
+            }
+            System.out.println("DERBY500 for varchar #1 Rows updated  ="
+                    + rowCount);
+
+            //verify data
+            verifyDerby500Test(pss, buf,cbuf, 0, 10, false);
+
+            PreparedStatement psu2 = conn
+                    .prepareStatement("update t1 set vc = ? "
+                            + ", lvc = ? where id = ?  ");
+
+            buf[randomOffset +1] = (byte)'h';
+            cbuf[randomOffset + 1] = 'h';
+            
+            rowCount = 0;
+            try {
+                psu2.setAsciiStream(1, new ByteArrayInputStream(buf), len);
+                psu2.setAsciiStream(2, new ByteArrayInputStream(buf), len);
+                psu2.setInt(3, 0);
+                rowCount += psu2.executeUpdate();
+            } catch (SQLException sqle) {
+                System.out
+                        .println("UNEXPECTED EXCEPTION - update should have actually gone
through");
+                dumpSQLExceptions(sqle);
+            }
+            conn.commit();
+            System.out.println("DERBY500 for varchar #2 Rows updated  ="
+                    + rowCount);
+            verifyDerby500Test(pss, buf,cbuf, 0, 1,false);
+            
+            // delete
+            // as currently we dont allow stream values to be re-used
+            PreparedStatement psd = conn
+                    .prepareStatement("delete from t1 where mvalue = ?");
+
+            rowCount = 0;
+            try {
+                psd.setInt(1, 0);
+                rowCount += psd.executeUpdate();
+                rowCount += psd.executeUpdate();
+            } catch (SQLException sqle) {
+                System.out
+                .println("UNEXPECTED EXCEPTION - delete should have actually gone through");
+                dumpSQLExceptions(sqle);
+            }
+            System.out.println("DERBY500 for varchar #3 Rows deleted ="
+                    + rowCount);
+
+            //verify data
+            verifyDerby500Test(pss, buf,cbuf, 0, 10,false);
+
+            PreparedStatement psd2 = conn
+                    .prepareStatement("delete from t1 where id = ?");
+            
+            rowCount = 0;
+            try {
+                psd2.setInt(1, 0);
+                rowCount += psd2.executeUpdate();
+            } catch (SQLException sqle) {
+                System.out
+                        .println("UNEXPECTED EXCEPTION - delete should have actually gone
through");
+                dumpSQLExceptions(sqle);
+            }
+            conn.commit();
+            System.out.println("DERBY500 for varchar #4 Rows deleted  ="
+                    + rowCount);
+            verifyDerby500Test(pss, buf,cbuf, 1, 2,false);
+
+            stmt.execute("drop table t1");
+            conn.commit();
+            stmt.close();
+            pss.close();
+            psu2.close();
+            psu.close();
+            psd.close();
+            psd2.close();
+            System.out.println("END  DERBY-500 TEST  for varchar");
+            System.out.println("======================================");
+
+        } catch (SQLException sqle) {
+            dumpSQLExceptions(sqle);
+        } catch (Exception e) {
+            System.out.println("DERBY-500 TEST for varchar FAILED!");
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * verify the data in the derby500Test
+     * @param ps select preparedstatement
+     * @param buf byte array to compare the blob data
+     * @param cbuf char array to compare the clob data
+     * @param startId start id of the row to check data for 
+     * @param endId end id of the row to check data for
+     * @param binaryType  flag to indicate if the second column in resultset
+     *                  is a binary type or not. true for binary type 
+     * @throws Exception
+     */
+    private static void verifyDerby500Test(PreparedStatement ps, byte[] buf,char[] cbuf,
+            int startId, int endId,boolean binaryType) throws Exception {
+        byte[] retrieveData = null;
+        int rowCount = 0;
+        ResultSet rs = null;
+        for (int i = startId; i < endId; i++) {
+            ps.setInt(1, i);
+            rs = ps.executeQuery();
+            if(rs.next())
+            {
+            compareCharArray(rs.getCharacterStream(1), cbuf,cbuf.length);
+            if(binaryType)
+                byteArrayEquals(rs.getBytes(2), 0, buf.length, buf, 0, buf.length);
+            else
+                compareCharArray(rs.getCharacterStream(2), cbuf,cbuf.length);
+                
+            rowCount++;
+            }
+        }
+        System.out.println("Rows selected =" + rowCount);
+        rs.close();
+    }
+    /**
+     * compare char data
+     * @param stream data from stream to compare 
+     * @param compare base data to compare against
+     * @param length compare length number of chars.
+     * @throws Exception
+     */
+    private static void compareCharArray(Reader stream, char[] compare,
+            int length) throws Exception {
+        int c1 = 0;
+        int i = 0;
+        do {
+            c1 = stream.read();
+            if (c1 != compare[i++]) {
+                System.out
+                        .println("FAIL -- MISMATCH in data stored versus data retrieved at
"
+                                + (i - 1));
+                break;
+            }
+            length--;
+        } while (c1 != -1 && length > 0);
+
+    }
+    
+    private static void expectedException(SQLException sqle) {
+
+        while (sqle != null) {
+            String sqlState = sqle.getSQLState();
+            if (sqlState == null) {
+                sqlState = "<NULL>";
+            }
+            System.out.println("EXPECTED SQL Exception: (" + sqlState + ") "
+                    + sqle.getMessage());
+
+            sqle = sqle.getNextException();
+        }
+    }
+
 	private static void streamTestDataVerification(ResultSet rs, int maxValueAllowed)
 	throws Exception{
 		ResultSetMetaData met;
@@ -1417,4 +1864,6 @@
 			se = se.getNextException();
 		}
 	}
+    
+    
 }

Modified: db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn_derby.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn_derby.properties?rev=327012&r1=327011&r2=327012&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn_derby.properties
(original)
+++ db/derby/code/branches/10.1/java/testing/org/apache/derbyTesting/functionTests/tests/store/streamingColumn_derby.properties
Thu Oct 20 15:18:36 2005
@@ -4,5 +4,5 @@
 derby.drda.debug=true
 derby.drda.traceAll=true
 derby.stream.error.logSeverityLevel=0
-derby.language.logStatementText=true
+#derby.language.logStatementText=true - this masks exceptions - DERBY595
 derby.infolog.append=true



Mime
View raw message