db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r734630 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/jdbc/ testing/org/apache/derby/impl/jdbc/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Date Thu, 15 Jan 2009 08:48:44 GMT
Author: kristwaa
Date: Thu Jan 15 00:48:43 2009
New Revision: 734630

URL: http://svn.apache.org/viewvc?rev=734630&view=rev
Log:
DERBY-3907: Save useful length information for Clobs in store.
These changes make Derby start using the stream descriptor object to
correctly handle streams from store. This is done to be able to use
several header formats, where a varying number of bytes are used.
Description of changes:
 o EmbedClob
   Changed constructor to take a StringDataValue instead of a
   DataValueDescriptor. Updated call to the StoreStreamClob constructor.

 o EmbedResultSet
   Started using the getStreamWithDescriptor method and updated invocations of
   the UTF8Reader constructor.

 o StoreStreamClob
   Added a CharacterStreamDescriptor (CSD), and made the constructor take one
   as an argument. Adapted the class to use a CSD.

 o UTF8Reader
   Updated some comments.
   Fixed bug where the header length wasn't added to the byte length of the
   stream, and updated the class appropriately (adjusted utfCount, fixed the
   reset routine). Made sure the header bytes are skipped (either by skipping
   them in the constructor or by adjusting the position to on the next
   reposition).

 o ResultSetStreamTest
   Added a test for maxFieldSize, where truncation have to happen.

 o Various tests
   Adjusted tests to run with the new implementation.

Patch file: derby-3907-5a-use_getStreamWithDescriptor.diff


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerStoreStreamClobTest.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerTemporaryClobTest.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallStoreStreamClobTest.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallTemporaryClobTest.java
    db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/UTF8ReaderTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ResultSetStreamTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java Thu Jan 15 00:48:43
2009
@@ -25,15 +25,11 @@
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.jdbc.EngineLOB;
+import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 import org.apache.derby.iapi.services.sanity.SanityManager;
-import org.apache.derby.iapi.types.DataValueDescriptor;
 import org.apache.derby.iapi.types.Resetable;
-import org.apache.derby.impl.jdbc.ConnectionChild;
-import org.apache.derby.impl.jdbc.EmbedConnection;
-import org.apache.derby.impl.jdbc.Util;
-import org.apache.derby.impl.jdbc.ReaderToAscii;
+import org.apache.derby.iapi.types.StringDataValue;
 
-import java.io.InputStream;
 import java.io.Reader;
 import java.io.IOException;
 import java.io.EOFException;
@@ -101,11 +97,11 @@
      * The data value descriptor may provide a <code>String</code> or a stream
      * as the source of the Clob.
      *
-     * @param dvd data value descriptor providing the Clob source
+     * @param dvd string data value descriptor providing the Clob source
      * @param con associated connection for the Clob
      * @throws StandardException
      */
-    protected EmbedClob(EmbedConnection con, DataValueDescriptor dvd)
+    protected EmbedClob(EmbedConnection con, StringDataValue dvd)
         throws StandardException
     {
         super(con);
@@ -115,9 +111,9 @@
             SanityManager.ASSERT(!dvd.isNull(),
                                  "clob is created on top of a null column");
 
-        InputStream storeStream = dvd.getStream();
+        CharacterStreamDescriptor csd = dvd.getStreamWithDescriptor();
         // See if a String or a stream will be the source of the Clob.
-        if (storeStream == null) {
+        if (csd == null) {
             try {
                 clob = new TemporaryClob(dvd.getString(),
                         this);
@@ -144,10 +140,10 @@
              should not break the ASSERT below.
              */
             if (SanityManager.DEBUG)
-                SanityManager.ASSERT(storeStream instanceof Resetable);
+                SanityManager.ASSERT(csd.getStream() instanceof Resetable);
 
             try {
-                this.clob = new StoreStreamClob(storeStream, this);
+                this.clob = new StoreStreamClob(csd, this);
             } catch (StandardException se) {
                 if (se.getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED)) {
                     throw StandardException

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?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- 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 Thu Jan
15 00:48:43 2009
@@ -75,6 +75,8 @@
 
 import java.util.Arrays;
 import java.util.Calendar;
+
+import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 import org.apache.derby.iapi.types.StringDataValue;
 
 /**
@@ -1123,18 +1125,16 @@
 
 		    useStream(columnIndex);
 
-			DataValueDescriptor dvd = getColumn(columnIndex);
+            StringDataValue dvd = (StringDataValue)getColumn(columnIndex);
 
 			if (wasNull = dvd.isNull()) { return null; }
 
 			pushStack = true;
 			setupContextStack();
 
-			StreamStorable ss = (StreamStorable) dvd;
-
-			InputStream stream = ss.returnStream();
+            CharacterStreamDescriptor csd = dvd.getStreamWithDescriptor();
 
-			if (stream == null) {
+            if (csd == null) {
 
 				String val = dvd.getString();
 				if (lmfs > 0) {
@@ -1146,7 +1146,12 @@
 				return ret;
 			}
 
-			java.io.Reader ret = new UTF8Reader(stream, lmfs, this, syncLock);
+            // See if we have to enforce a max field size.
+            if (lmfs > 0) {
+                csd = new CharacterStreamDescriptor.Builder().copyState(csd).
+                        maxCharLength(lmfs).build();
+            }
+            java.io.Reader ret = new UTF8Reader(csd, this, syncLock);
 			currentStream = ret;
 			return ret;
 
@@ -4020,13 +4025,13 @@
 			boolean pushStack = false;
 			try {
 
-				DataValueDescriptor dvd = getColumn(columnIndex);
+				StringDataValue dvd = (StringDataValue)getColumn(columnIndex);
 
 				if (wasNull = dvd.isNull())
 					return null;
 
 				// should set up a context stack if we have a long column,
-				// since a blob may keep a pointer to a long column in the
+				// since a Clob may keep a pointer to a long column in the
 				// database
 				if (dvd.getStream() != null)
 					pushStack = true;
@@ -4034,7 +4039,7 @@
 				if (pushStack)
 					setupContextStack();
 
-				return new EmbedClob(getEmbedConnection(), dvd);
+                return new EmbedClob(getEmbedConnection(), dvd);
 			} catch (Throwable t) {
 				throw handleException(t);
 			} finally {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/StoreStreamClob.java Thu Jan
15 00:48:43 2009
@@ -34,8 +34,8 @@
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.sanity.SanityManager;
 import org.apache.derby.iapi.types.Resetable;
-import org.apache.derby.iapi.types.TypeId;
 import org.apache.derby.iapi.util.UTF8Util;
 
 /**
@@ -44,10 +44,8 @@
  * <p>
  * Note that the streams from the store are expected to have the following
  * properties:
- * <ol> <li>The first two bytes are used for length encoding. Note that due to
- *          the inadequate max number of this format, it is always ignored. This
- *          is also true if there actually is a length encoded there. The two
- *          bytes are excluded from the length of the stream.
+ * <ol> <li>The first few bytes are used for length encoding. Currently the
+ *          number of bytes is either 2 or 5.
  *      <li>A Derby-specific end-of-stream marker at the end of the stream can
  *          be present. The marker is expected to be <code>0xe0 0x00 0x00</code>
  * </ol>
@@ -66,14 +64,8 @@
      */
     //@GuardedBy("synchronizationObject")
     private final PositionedStoreStream positionedStoreStream;
-    /**
-     * The cached length of the store stream in number of characters.
-     * A value of {@code 0} means the length is unknown, and zero is an invalid
-     * length for a store stream Clob. It is set to zero because that is the
-     * value encoded as length in the store stream (on disk format) when the
-     * length is unknown or cannot be represented.
-     */
-    private long cachedCharLength = 0;
+    /** The descriptor used to describe the underlying source stream. */
+    private CharacterStreamDescriptor csd;
     /** The connection (child) this Clob belongs to. */
     private final ConnectionChild conChild;
     /** Object used for synchronizing access to the store stream. */
@@ -94,28 +86,26 @@
     /**
      * Creates a new Clob based on a stream from store.
      * <p>
-     * Note that the stream passed in have to fulfill certain requirements,
-     * which are not currently totally enforced by Java (the language).
+     * The stream used as a source for this Clob has to implement the interface
+     * {@code Resetable}, as the stream interface from store only allows for
+     * movement forwards. If the stream has been advanced too far with regards
+     * to the user request, the stream must be reset and we start from the
+     * beginning.
      *
-     * @param stream the stream containing the Clob value. This stream is
-     *      expected to implement {@link Resetable} and to be a
-     *      {@link org.apache.derby.iapi.services.io.FormatIdInputStream} with
-     *      an ${link org.apache.derby.impl.store.raw.data.OverflowInputStream}
-     *      inside. However, the available interfaces does not guarantee this.
-     *      See the class JavaDoc for more information about this stream.
+     * @param csd descriptor for the source stream, including a reference to it
      * @param conChild the connection (child) this Clob belongs to
-     * @throws StandardException if initializing the store stream fails
-     * @throws NullPointerException if <code>stream</code> or
-     *      <code>conChild</code> is null
-     * @throws ClassCastException if <code>stream</code> is not an instance
-     *      of <code>Resetable</code>
-     * @see org.apache.derby.iapi.services.io.FormatIdInputStream
-     * @see org.apache.derby.impl.store.raw.data.OverflowInputStream
      */
-    public StoreStreamClob(InputStream stream, ConnectionChild conChild)
+    public StoreStreamClob(CharacterStreamDescriptor csd,
+                           ConnectionChild conChild)
             throws StandardException {
+        if (SanityManager.DEBUG) {
+            // We create a position aware stream below, the stream is not
+            // supposed to be a position aware stream already!
+            SanityManager.ASSERT(!csd.isPositionAware());
+        }
         try {
-            this.positionedStoreStream = new PositionedStoreStream(stream);
+            this.positionedStoreStream = 
+                    new PositionedStoreStream(csd.getStream());
         } catch (StandardException se) {
             if (se.getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED)) {
                 throw StandardException
@@ -129,6 +119,16 @@
         }
         this.conChild = conChild;
         this.synchronizationObject = conChild.getConnectionSynchronization();
+        if (SanityManager.DEBUG) {
+            // Creating the positioned stream should reset the stream.
+            SanityManager.ASSERT(positionedStoreStream.getPosition() == 0);
+        }
+        this.csd = new CharacterStreamDescriptor.Builder().copyState(csd).
+                stream(positionedStoreStream). // Replace with positioned stream
+                positionAware(true). // Update description
+                curBytePos(0L).
+                curCharPos(CharacterStreamDescriptor.BEFORE_FIRST).
+                build();
     }
 
     /**
@@ -154,12 +154,13 @@
     public long getCharLength()
             throws SQLException {
         checkIfValid();
-        if (this.cachedCharLength == 0) {
+        if (this.csd.getCharLength() == 0) {
             // Decode the stream to find the length.
+            long charLength = 0;
             synchronized (this.synchronizationObject) {
                 this.conChild.setupContextStack();
                 try {
-                    this.cachedCharLength = UTF8Util.skipUntilEOF(
+                    charLength = UTF8Util.skipUntilEOF(
                             new BufferedInputStream(getRawByteStream()));
                 } catch (Throwable t) {
                     throw noStateChangeLOB(t);
@@ -167,8 +168,11 @@
                     this.conChild.restoreContextStack();
                 }
             }
+            // Update the stream descriptor.
+            this.csd = new CharacterStreamDescriptor.Builder().
+                    copyState(this.csd).charLength(charLength).build();
         }
-        return this.cachedCharLength;
+        return this.csd.getCharLength();
     }
 
     /**
@@ -188,7 +192,7 @@
         checkIfValid();
         try {
             // Skip the encoded length.
-            this.positionedStoreStream.reposition(2L);
+            this.positionedStoreStream.reposition(this.csd.getDataOffset());
         } catch (StandardException se) {
             throw Util.generateCsSQLException(se);
         }
@@ -213,15 +217,6 @@
         } catch (StandardException se) {
             throw Util.generateCsSQLException(se);
         }
-        // Describe the stream to allow the reader to configure itself.
-        CharacterStreamDescriptor csd =
-                new CharacterStreamDescriptor.Builder().
-                stream(positionedStoreStream).bufferable(false).
-                positionAware(true).dataOffset(2L). // TODO
-                curCharPos(CharacterStreamDescriptor.BEFORE_FIRST).
-                maxCharLength(TypeId.CLOB_MAXWIDTH).
-                charLength(cachedCharLength). // 0 means unknown.
-                build();
         Reader reader = new UTF8Reader(
                 csd, this.conChild, this.synchronizationObject);
         long leftToSkip = pos -1;
@@ -258,15 +253,6 @@
                     throw Util.generateCsSQLException(se);
                 }
             }
-            // Describe the stream to allow the reader to configure itself.
-            CharacterStreamDescriptor csd =
-                    new CharacterStreamDescriptor.Builder().
-                    stream(positionedStoreStream).bufferable(false).
-                    positionAware(true).dataOffset(2L). // TODO: Fix offset.
-                    curCharPos(CharacterStreamDescriptor.BEFORE_FIRST).
-                    maxCharLength(TypeId.CLOB_MAXWIDTH).
-                    charLength(cachedCharLength). // 0 means unknown.
-                    build();
             this.internalReader =
                     new UTF8Reader(csd, conChild, synchronizationObject);
             this.unclosableInternalReader =

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java Thu Jan 15
00:48:43 2009
@@ -62,11 +62,14 @@
 
     /** The underlying data stream. */
     private InputStream in;
-    /** Stream that can reposition itself on request. */
+    /** Stream that can reposition itself on request (may be {@code null}). */
     private final PositionedStream positionedIn;
-    /** Store last visited position in the store stream. */
+    /**
+     * Store the last visited position in the store stream, if it is capable of
+     * repositioning itself ({@code positionedIn != null}).
+     */
     private long rawStreamPos = 0L;
-    /** Number of bytes read from the stream. */
+    /** Number of bytes read from the stream, including any header bytes. */
     private long       utfCount;        // bytes
     /** Number of characters read from the stream. */
     private long       readerCharCount; // characters
@@ -170,13 +173,16 @@
         }
         this.csd = new CharacterStreamDescriptor.Builder().
                 bufferable(positionedIn == null).
-                positionAware(positionedIn != null).byteLength(utfLen).
+                positionAware(positionedIn != null).
+                byteLength(utfLen == 0 ? 0 : utfLen +2). // Add header bytes
                 dataOffset(2).curBytePos(2).stream(in).
                 build();
+        utfCount = 2;
     }
 
     public UTF8Reader(CharacterStreamDescriptor csd, ConnectionChild conChild,
-            Object sync) {
+            Object sync)
+            throws IOException {
         super(sync);
         this.csd = csd;
         this.positionedIn =
@@ -186,17 +192,23 @@
         int buffersize = calculateBufferSize(csd);
         this.buffer = new char[buffersize];
 
-        // Check and save the stream state.
-        if (SanityManager.DEBUG) { 
-            if (csd.isPositionAware()) {
+        if (csd.isPositionAware()) {
+            // Check and save the stream state.
+            if (SanityManager.DEBUG) {
                 SanityManager.ASSERT(
                         csd.getCurBytePos() == positionedIn.getPosition());
             }
-        }
-        this.rawStreamPos = positionedIn.getPosition();
-        // Make sure we start at the first data byte, not in the header.
-        if (rawStreamPos < csd.getDataOffset()) {
-            rawStreamPos = csd.getDataOffset();
+            this.rawStreamPos = positionedIn.getPosition();
+            // Make sure we start at the first data byte, not in the header.
+            // The position will be changed on the next buffer fill.
+            if (rawStreamPos < csd.getDataOffset()) {
+                rawStreamPos = csd.getDataOffset();
+            }
+        } else {
+            // Skip the header if required.
+            if (csd.getCurBytePos() < csd.getDataOffset()) {
+                csd.getStream().skip(csd.getDataOffset() - csd.getCurBytePos());
+            }
         }
 
         // Buffer stream for improved performance, if appropriate.
@@ -205,6 +217,8 @@
         } else {
             this.in = csd.getStream();
         }
+        // Add the header portion to the utfCount.
+        utfCount = csd.getDataOffset();
     }
 
     /*
@@ -462,8 +476,8 @@
                 }
             }
             // Keep track of how much we are allowed to read.
-            long utfLen = csd.getByteLength();
-            long maxFieldSize = csd.getMaxCharLength();
+            final long utfLen = csd.getByteLength();
+            final long maxFieldSize = csd.getMaxCharLength();
 readChars:
         while (
                 (charactersInBuffer < buffer.length) &&
@@ -601,12 +615,12 @@
             throws IOException, StandardException {
         // Skip the length encoding bytes.
         this.positionedIn.reposition(csd.getDataOffset());
-        this.rawStreamPos = this.positionedIn.getPosition();
+        this.utfCount = this.rawStreamPos = this.positionedIn.getPosition();
         // If bufferable, discard buffered stream and create a new one.
         if (csd.isBufferable()) {
             this.in = new BufferedInputStream(csd.getStream(), buffer.length);
         }
-        this.readerCharCount = this.utfCount = 0L;
+        this.readerCharCount = 0L;
         this.charactersInBuffer = this.readPositionInBuffer = 0;
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerStoreStreamClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerStoreStreamClobTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerStoreStreamClobTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerStoreStreamClobTest.java
Thu Jan 15 00:48:43 2009
@@ -22,8 +22,10 @@
  */
 package org.apache.derby.impl.jdbc;
 
+import java.io.InputStream;
 import junit.framework.Test;
 import junit.framework.TestSuite;
+import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 
 /**
  * Tests basic operations on a bigger read-only Clob from the store module.
@@ -41,10 +43,18 @@
     public void setUp()
             throws Exception {
         super.initialCharLength = CLOBLENGTH;
-        super.initialByteLength = CLOBLENGTH; // The fake stream uses ascii.
+        super.headerLength = 2 +3;
+        // The fake stream uses ascii. Add header and EOF marker.
+        super.initialByteLength = CLOBLENGTH + headerLength;
         super.bytesPerChar = BYTES_PER_CHAR;
         EmbedStatement embStmt = (EmbedStatement)createStatement();
-        iClob = new StoreStreamClob(new FakeStoreStream(CLOBLENGTH), embStmt);
+        InputStream is = new FakeStoreStream(CLOBLENGTH);
+        CharacterStreamDescriptor csd =
+                new CharacterStreamDescriptor.Builder().stream(is).
+                    charLength(initialCharLength).byteLength(0L).
+                    curCharPos(CharacterStreamDescriptor.BEFORE_FIRST).
+                    dataOffset(2L).build();
+        iClob = new StoreStreamClob(csd, embStmt);
         assertEquals(CLOBLENGTH, iClob.getCharLength());
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerTemporaryClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerTemporaryClobTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerTemporaryClobTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/BiggerTemporaryClobTest.java
Thu Jan 15 00:48:43 2009
@@ -49,10 +49,11 @@
     public void setUp()
             throws Exception {
         super.initialCharLength = CLOBLENGTH;
-        super.initialByteLength = CLOBLENGTH *3; // Only Tamil characters.
+        super.headerLength = 2 + 3;
+       // All tamil letters. Also add the header bytes.
+        super.initialByteLength = CLOBLENGTH *3 + headerLength;
         super.bytesPerChar = BYTES_PER_CHAR;
         EmbedStatement embStmt = (EmbedStatement)createStatement();
-        EmbedConnection embCon =(EmbedConnection)getConnection();
         iClob = new TemporaryClob(embStmt);
         transferData(
             new LoopingAlphabetReader(CLOBLENGTH, CharAlphabet.cjkSubset()),

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/InternalClobTest.java Thu
Jan 15 00:48:43 2009
@@ -78,6 +78,7 @@
     protected long initialByteLength = Long.MIN_VALUE;
     protected long initialCharLength = Long.MIN_VALUE;
     protected long bytesPerChar = Long.MIN_VALUE;
+    protected long headerLength = Long.MIN_VALUE;
 
     InternalClobTest(String name) {
         super(name);
@@ -116,7 +117,8 @@
      * when using UTF-8 as encoding.
      */
     public void testSanity() {
-        assertEquals(initialByteLength, initialCharLength * bytesPerChar);
+        assertEquals(initialByteLength,
+                initialCharLength * bytesPerChar + headerLength);
         assertTrue(initialCharLength > 25);
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallStoreStreamClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallStoreStreamClobTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallStoreStreamClobTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallStoreStreamClobTest.java
Thu Jan 15 00:48:43 2009
@@ -22,8 +22,10 @@
  */
 package org.apache.derby.impl.jdbc;
 
+import java.io.InputStream;
 import junit.framework.Test;
 import junit.framework.TestSuite;
+import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor;
 
 /**
  * Tests basic operations on a small read-only Clob from the store module.
@@ -41,10 +43,18 @@
     public void setUp()
             throws Exception {
         super.initialCharLength = CLOBLENGTH;
-        super.initialByteLength = CLOBLENGTH; // The fake stream uses ascii.
+        super.headerLength = 2 + 3;
+        // The fake stream uses ascii. Add header and EOF marker.
+        super.initialByteLength = CLOBLENGTH + headerLength;
         super.bytesPerChar = BYTES_PER_CHAR;
         EmbedStatement embStmt = (EmbedStatement)createStatement();
-        iClob = new StoreStreamClob(new FakeStoreStream(CLOBLENGTH), embStmt);
+        InputStream is = new FakeStoreStream(CLOBLENGTH);
+        CharacterStreamDescriptor csd =
+                new CharacterStreamDescriptor.Builder().stream(is).
+                    charLength(initialCharLength).byteLength(0L).
+                    curCharPos(CharacterStreamDescriptor.BEFORE_FIRST).
+                    dataOffset(2L).build();
+        iClob = new StoreStreamClob(csd, embStmt);
         assertEquals(CLOBLENGTH, iClob.getCharLength());
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallTemporaryClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallTemporaryClobTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallTemporaryClobTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/SmallTemporaryClobTest.java
Thu Jan 15 00:48:43 2009
@@ -51,10 +51,11 @@
     public void setUp()
             throws Exception {
         super.initialCharLength = CLOBLENGTH;
-        super.initialByteLength = CLOBLENGTH *3; // All tamil letters.
+        super.headerLength = 2 + 3;
+       // All tamil letters. Also add the header bytes.
+        super.initialByteLength = CLOBLENGTH *3 + headerLength;
         super.bytesPerChar = BYTES_PER_CHAR;
         EmbedStatement embStmt = (EmbedStatement)createStatement();
-        EmbedConnection embCon =(EmbedConnection)getConnection();
         iClob = new TemporaryClob(embStmt);
         transferData(
             new LoopingAlphabetReader(CLOBLENGTH, CharAlphabet.tamil()),

Modified: db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/UTF8ReaderTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/UTF8ReaderTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/UTF8ReaderTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derby/impl/jdbc/UTF8ReaderTest.java Thu Jan
15 00:48:43 2009
@@ -34,7 +34,7 @@
 import junit.framework.TestSuite;
 
 import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.types.StringDataValue;
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
@@ -60,9 +60,10 @@
                 "select * from Utf8ReaderTest where id = 101");
         rs.next();
         final int size = rs.getInt(2);
-        DataValueDescriptor dvd = ((EmbedResultSet)rs).getColumn(3);
+        StringDataValue dvd = (StringDataValue)
+                                            ((EmbedResultSet)rs).getColumn(3);
         StoreStreamClob ssClob = new StoreStreamClob(
-                dvd.getStream(), (EmbedResultSet)rs);
+                dvd.getStreamWithDescriptor(), (EmbedResultSet)rs);
         Reader reader = ssClob.getInternalReader(1);
         assertEquals('a', reader.read());
         // Get internal readers and do stuff.
@@ -90,9 +91,10 @@
         ResultSet rs = stmt.executeQuery(
                 "select * from Utf8ReaderTest where id = 100");
         rs.next();
-        DataValueDescriptor dvd = ((EmbedResultSet)rs).getColumn(3);
+        StringDataValue dvd = (StringDataValue)
+                                            ((EmbedResultSet)rs).getColumn(3);
         StoreStreamClob ssClob = new StoreStreamClob(
-                dvd.getStream(), (EmbedResultSet)rs);
+                dvd.getStreamWithDescriptor(), (EmbedResultSet)rs);
         Reader reader = ssClob.getInternalReader(1);
         assertEquals('a', reader.read());
         int bufSize = 26000;
@@ -129,9 +131,10 @@
                 // See insertTestData
                 "select * from Utf8ReaderTest where id = 1");
         rs.next();
-        DataValueDescriptor dvd = ((EmbedResultSet)rs).getColumn(3);
+        StringDataValue dvd = (StringDataValue)
+                                            ((EmbedResultSet)rs).getColumn(3);
         StoreStreamClob ssClob = new StoreStreamClob(
-                dvd.getStream(), (EmbedResultSet)rs);
+                dvd.getStreamWithDescriptor(), (EmbedResultSet)rs);
         Reader reader = ssClob.getInternalReader(1);
         assertEquals('B', reader.read());
         reader = ssClob.getInternalReader(24);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ResultSetStreamTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ResultSetStreamTest.java?rev=734630&r1=734629&r2=734630&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ResultSetStreamTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ResultSetStreamTest.java
Thu Jan 15 00:48:43 2009
@@ -43,7 +43,7 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
-import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
 import org.apache.derbyTesting.junit.SupportFilesSetup;
@@ -408,6 +408,74 @@
         
     }
     
+    /**
+     * Tests that the max field size limit is handled correctly when accessing
+     * values as streams. The limit should apply for VARCHAR, but not for CLOB.
+     *
+     * @throws IOException if something goes wrong
+     * @throws SQLException if something goes wrong
+     */
+    public void testSetMaxFieldSizeLarge()
+            throws IOException, SQLException {
+        // Insert test data.
+        int id = 1;
+        int clobSize = 2*1024*1024; // 2 MB
+        int vcSize = 32672;
+        int limit = 10;
+        PreparedStatement ps = prepareStatement(
+                "insert into setMaxFieldSize values (?,?,?)");
+        ps.setInt(1, id);
+        ps.setCharacterStream(2, new LoopingAlphabetReader(vcSize), vcSize);
+        ps.setCharacterStream(3, new LoopingAlphabetReader(clobSize), clobSize);
+        ps.executeUpdate();
+
+        // Fetch data back with a limit.
+        Statement stmt = createStatement();
+        stmt.setMaxFieldSize(limit);
+        ResultSet rs = stmt.executeQuery("select dVarchar, dClob from " +
+                "setMaxFieldSize where id = " + id);
+        assertTrue(rs.next());
+        String vcStr = drainStringFromSource(rs.getCharacterStream(1));
+        // Limit should apply to VARCHAR.
+        assertEquals(limit, vcStr.length());
+        // Limit should *not* apply to CLOB.
+        String vsClob = drainStringFromSource(rs.getCharacterStream(2));
+        assertEquals(clobSize, vsClob.length());
+        rs.close();
+
+        // Again, but without a limit.
+        stmt = createStatement();
+        rs = stmt.executeQuery("select dVarchar, dClob from " +
+                "setMaxFieldSize where id = " + id);
+        assertTrue(rs.next());
+        vcStr = drainStringFromSource(rs.getCharacterStream(1));
+        assertEquals(vcSize, vcStr.length());
+        vsClob = drainStringFromSource(rs.getCharacterStream(2));
+        assertEquals(clobSize, vsClob.length());
+        rs.close();
+    }
+
+    /**
+     * Drains the specified reader and returns a string.
+     *
+     * @param src the reader to drain
+     * @return The reader content as a string.
+     * @throws IOException if reading from the source fails
+     */
+    private static String drainStringFromSource(Reader src)
+            throws IOException {
+        StringBuffer str = new StringBuffer();
+        char[] buf = new char[1024];
+        while (true) {
+            int read = src.read(buf);
+            if (read == -1) {
+                break;
+            }
+            str.append(buf, 0, read);
+        }
+        return str.toString();
+    }
+
     public static Test basesuite(String name) {
         TestSuite suite = new TestSuite(ResultSetStreamTest.class, name);
         Test test = new SupportFilesSetup(suite, new String[] {
@@ -420,6 +488,8 @@
 
                 s.execute("create table t2 (len int, data LONG VARCHAR FOR BIT DATA)");
                 s.execute("create table t3(text_data clob)");
+                s.execute("create table setMaxFieldSize(id int unique, " +
+                        "dVarchar VARCHAR(32672), dClob clob)");
 
             }
         };



Mime
View raw message