You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by da...@apache.org on 2007/04/18 17:39:09 UTC

svn commit: r530070 - in /db/derby/code/trunk/java/client/org/apache/derby/client/am: Blob.java BlobOutputStream.java Clob.java ClobOutputStream.java ClobWriter.java Lob.java

Author: dag
Date: Wed Apr 18 08:39:08 2007
New Revision: 530070

URL: http://svn.apache.org/viewvc?view=rev&rev=530070
Log:
DERBY-2540 Restructure code for Blob/Clob length in client to prepare for locator implementation
Committed patch derby-2540_2. 

Contributed by Oystein Grovlen (Oystein.Grovlen@Sun.COM).

Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobOutputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobOutputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobWriter.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Lob.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java Wed Apr 18 08:39:08 2007
@@ -54,8 +54,7 @@
         
         binaryString_ = binaryString;
         dataType_ |= BINARY_STRING;
-        sqlLength_ = binaryString.length - dataOffset;
-        lengthObtained_ = true;
+        setSqlLength(binaryString.length - dataOffset);
         dataOffset_ = dataOffset;
     }
 
@@ -69,8 +68,7 @@
         
         binaryStream_ = binaryStream;
         dataType_ |= BINARY_STREAM;
-        sqlLength_ = length;
-        lengthObtained_ = true;
+        setSqlLength(length);
     }
 
     /**
@@ -100,9 +98,6 @@
         
         binaryStream_ = binaryStream;
         dataType_ |= BINARY_STREAM;
-        sqlLength_ = -1;
-        lengthObtained_ = false;
-        
     }
 
     // ---------------------------jdbc 2------------------------------------------
@@ -117,17 +112,10 @@
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceEntry(this, "length");
                 }
-                // Code to handle the lengthless constructor.
-                if (!lengthObtained_) {
-                    
-                    if( willBeLayerBStreamed() )
-                        throw new SqlException(agent_.logWriter_,
-                                               LOB_OBJECT_LENGTH_UNKNOWN_YET);
-                    
-                    binaryStream_ = super.materializeStream(binaryStream_,
-                                                            "java.sql.Blob");
-                }
+
+                checkForClosedConnection();
                 long retVal = super.sqlLength();
+
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceExit(this, "length", retVal);
                 }
@@ -178,7 +166,7 @@
                         new ClientMessageId(SQLState.BLOB_BAD_POSITION), 
                         new Long(pos));
                 }
-                if (pos > this.length() + 1) {
+                if (pos > sqlLength() + 1) {
                     throw new SqlException(agent_.logWriter_, 
                         new ClientMessageId(SQLState.BLOB_POSITION_TOO_LARGE), 
                         new Long(pos));
@@ -205,13 +193,9 @@
         checkForClosedConnection();
 
         long actualLength;
-        try {
-            // actual length is the lesser of the number of bytes requested
-            // and the number of bytes available from pos to the end
-            actualLength = Math.min(this.length() - pos + 1, (long) length);
-        } catch ( SQLException se ) {
-            throw new SqlException(se);
-        }
+        // actual length is the lesser of the number of bytes requested
+        // and the number of bytes available from pos to the end
+        actualLength = Math.min(sqlLength() - pos + 1, (long) length);
         byte[] retVal = new byte[(int) actualLength];
         System.arraycopy(binaryString_, (int) pos + dataOffset_ - 1, retVal, 0, (int) actualLength);
         return retVal;
@@ -326,7 +310,9 @@
         checkForClosedConnection();
 
         try {
-            return binaryStringPosition(pattern.getBytes(1L, (int) pattern.length()), start);
+            return binaryStringPosition(pattern.getBytes(1L, 
+                                                         (int)pattern.length()),
+                                        start);
         } catch (java.sql.SQLException e) {
             throw new SqlException(e);
         }
@@ -433,7 +419,7 @@
 
         System.arraycopy(bytes, offset, binaryString_, (int) pos + dataOffset_ - 1, length);
         binaryStream_ = new java.io.ByteArrayInputStream(binaryString_);
-        sqlLength_ = binaryString_.length - dataOffset_;
+        setSqlLength(binaryString_.length - dataOffset_);
         return length;
     }
 
@@ -464,12 +450,12 @@
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceEntry(this, " truncate", (int) len);
                 }
-                if (len < 0 || len > this.length()) {
+                if (len < 0 || len > sqlLength()) {
                     throw new SqlException(agent_.logWriter_,
                         new ClientMessageId(SQLState.INVALID_API_PARAMETER),
                         new Long(len), "len", "Blob.truncate()");
                 }
-                if (len == this.length()) {
+                if (len == this.sqlLength()) {
                     return;
                 }
                 long newLength = (int) len + dataOffset_;
@@ -477,7 +463,7 @@
                 System.arraycopy(binaryString_, 0, newbuf, 0, (int) newLength);
                 binaryString_ = newbuf;
                 binaryStream_ = new java.io.ByteArrayInputStream(binaryString_);
-                sqlLength_ = binaryString_.length - dataOffset_;
+                setSqlLength(binaryString_.length - dataOffset_);
             }
         }
         catch ( SqlException se )
@@ -609,4 +595,15 @@
                                                   .getSQLException();
     }
     
+
+    /**
+     * Materialize the stream used for input to the database.
+     *
+     * @throws SqlException
+     */
+    protected void materializeStream() throws SqlException 
+    {
+        binaryStream_ = super.materializeStream(binaryStream_, "java.sql.Blob");
+    }
+
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobOutputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobOutputStream.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobOutputStream.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobOutputStream.java Wed Apr 18 08:39:08 2007
@@ -39,15 +39,10 @@
         }
     }
 
-    public void write(int b) throws java.io.IOException {
-
-        byte[] newbuf = new byte[(int) offset_ + blob_.dataOffset_];
-        System.arraycopy(blob_.binaryString_, 0, newbuf, 0, (int) offset_ - 1 + blob_.dataOffset_);
-        blob_.binaryString_ = newbuf;
-        blob_.binaryString_[(int) offset_ + blob_.dataOffset_ - 1] = (byte) b;
-        blob_.binaryStream_ = new java.io.ByteArrayInputStream(blob_.binaryString_);
-        blob_.sqlLength_ = blob_.binaryString_.length - blob_.dataOffset_;
-        offset_++;
+    public void write(int b) throws java.io.IOException 
+    {
+        byte ba[] = {(byte )b};
+        writeX(ba, 0, 1);
     }
 
     public void write(byte b[], int off, int len) throws java.io.IOException {
@@ -59,14 +54,21 @@
         } else if (len == 0) {
             return;
         }
+        writeX(b, off, len);
+    }
+
+    private void writeX(byte b[], int off, int len) 
+    {
         byte[] newbuf = new byte[(int) offset_ - 1 + len + blob_.dataOffset_];
-        System.arraycopy(blob_.binaryString_, 0, newbuf, 0, (int) offset_ - 1 + blob_.dataOffset_);
+        System.arraycopy(blob_.binaryString_, 0, 
+                         newbuf, 0, (int )offset_ - 1 + blob_.dataOffset_);
         blob_.binaryString_ = newbuf;
         for (int i = 0; i < len; i++, offset_++) {
-            blob_.binaryString_[(int) offset_ + blob_.dataOffset_ - 1] = b[off + i];
+            blob_.binaryString_[(int )offset_ + blob_.dataOffset_ - 1] 
+                = b[off + i];
         }
-        blob_.binaryStream_ = new java.io.ByteArrayInputStream(blob_.binaryString_);
-        blob_.sqlLength_ = blob_.binaryString_.length - blob_.dataOffset_;
+        blob_.binaryStream_ 
+            = new java.io.ByteArrayInputStream(blob_.binaryString_);
+        blob_.setSqlLength(blob_.binaryString_.length - blob_.dataOffset_);
     }
 }
-

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java Wed Apr 18 08:39:08 2007
@@ -44,9 +44,6 @@
     // Therefore, we always convert a String to UTF-8 before we flow it for input
     protected byte[] utf8String_;
 
-    // the length of the clob returned by the LENGTH function.
-    protected long lengthInBytes_ = 0;
-
     private PreparedStatement internalLengthStmt_ = null;
 
     protected String encoding_ = "UNICODE";
@@ -62,8 +59,7 @@
              false);
         
         string_ = string;
-        sqlLength_ = string_.length();
-        lengthObtained_ = true;
+        setSqlLength(string_.length());
         dataType_ |= STRING;
     }
 
@@ -91,8 +87,7 @@
                     dataOffset,
                     unconvertedBytes.length - dataOffset,
                     charsetName);
-            sqlLength_ = string_.length();
-            lengthObtained_ = true;
+            setSqlLength(string_.length());
             dataType_ |= STRING;
         } catch (java.io.UnsupportedEncodingException e) {
             throw new SqlException(agent_.logWriter_, 
@@ -112,8 +107,7 @@
         this(agent,
              false);
 
-        sqlLength_ = length;
-        lengthObtained_ = true;
+        setSqlLength(length);
 
         if (encoding.equals("US-ASCII")) {
             asciiStream_ = inputStream;
@@ -131,7 +125,7 @@
                     "UnicodeBigUnmarked", "InputStreamReader", e);
             }
             dataType_ |= CHARACTER_STREAM;
-            sqlLength_ = length / 2;
+            setSqlLength(length / 2);
         }
     }
 
@@ -154,8 +148,6 @@
         this(agent,
              isLayerBStreamingPossible( agent ));
         
-        lengthObtained_ = false;
-        
         if (encoding.equals("US-ASCII")) {
             asciiStream_ = inputStream;
             dataType_ |= ASCII_STREAM;
@@ -173,8 +165,7 @@
         this(agent,
              false);
         
-        sqlLength_ = length;
-        lengthObtained_ = true;
+        setSqlLength(length);
         characterStream_ = reader;
         dataType_ |= CHARACTER_STREAM;
     }
@@ -194,7 +185,6 @@
         this(agent,
              isLayerBStreamingPossible( agent ) );
         
-        lengthObtained_ = false;
         // Wrap reader in stream to share code.
         unicodeStream_ = EncodedInputStream.createUTF8Stream(reader);
         // Override type to share logic with the other stream types.
@@ -229,21 +219,12 @@
                     agent_.logWriter_.traceEntry(this, "length");
                 }
 
-                if (lengthObtained_) {
-                    return sqlLength_;
-                }
-
-                if( willBeLayerBStreamed() )
-                    throw new SqlException(agent_.logWriter_,
-                                           LOB_OBJECT_LENGTH_UNKNOWN_YET);
-                
-                materializeStream();
-                lengthInBytes_ = super.sqlLength();
+                long length = super.sqlLength();
 
                 if (agent_.loggingEnabled()) {
-                    agent_.logWriter_.traceExit(this, "length", sqlLength_);
+                    agent_.logWriter_.traceExit(this, "length", length);
                 }
-                return sqlLength_;
+                return length;
             }
         }
         catch ( SqlException se )
@@ -301,7 +282,7 @@
                         new Integer(length));
                 }
 
-                if (pos > this.length() + 1) {
+                if (pos > sqlLength() + 1) {
                     throw new SqlException(agent_.logWriter_, 
                         new ClientMessageId(SQLState.BLOB_POSITION_TOO_LARGE), 
                         new Long(pos));                    
@@ -320,19 +301,13 @@
         }
     }
 
-    private String getSubStringX(long pos, int length) throws SqlException {
-        try
-        {
-            checkForClosedConnection();
-            // actual length is the lesser of the length requested
-            // and the number of characters available from pos to the end
-            long actualLength = Math.min(this.length() - pos + 1, (long) length);
-            return string_.substring((int) pos - 1, (int) (pos - 1 + actualLength));
-        }
-        catch ( SQLException se )
-        {
-            throw new SqlException(se);
-        }
+    private String getSubStringX(long pos, int length) throws SqlException 
+    {
+        checkForClosedConnection();
+        // actual length is the lesser of the length requested
+        // and the number of characters available from pos to the end
+        long actualLength = Math.min(this.sqlLength() - pos + 1, (long) length);
+        return string_.substring((int) pos - 1, (int) (pos - 1 + actualLength));
     }
 
     public java.io.Reader getCharacterStream() throws SQLException {
@@ -514,11 +489,13 @@
         // if the searchstr is longer than the source, no match
         int index;
         try {
-            if (searchstr.length() > length()) {
+            if (searchstr.length() > sqlLength()) {
                 return -1;
             }
 
-            index = string_.indexOf(searchstr.getSubString(1L, (int) searchstr.length()), (int) start - 1);
+            index = string_.indexOf(searchstr.getSubString(1L, 
+                                                      (int) searchstr.length()),
+                                    (int) start - 1);
         } catch (java.sql.SQLException e) {
             throw new SqlException(e);
         }
@@ -586,7 +563,7 @@
                 new ClientMessageId(SQLState.BLOB_BAD_POSITION), 
                 new Long(pos));
         }
-        if ( pos - 1 > sqlLength_) {
+        if ( pos - 1 > sqlLength()) {
             throw new SqlException(agent_.logWriter_,
                 new ClientMessageId(SQLState.BLOB_POSITION_TOO_LARGE),
                 new Long(pos));
@@ -614,7 +591,7 @@
         asciiStream_ = new java.io.StringBufferInputStream(string_);
         unicodeStream_ = new java.io.StringBufferInputStream(string_);
         characterStream_ = new java.io.StringReader(string_);
-        sqlLength_ = string_.length();
+        setSqlLength(string_.length());
         return length;
     }
 
@@ -688,13 +665,13 @@
                         new Long(len));
                 }
                 
-                if ( len > this.length()) {
+                if ( len > sqlLength()) {
                     throw new SqlException(agent_.logWriter_, 
                         new ClientMessageId(SQLState.BLOB_LENGTH_TOO_LONG),
                         new Long(len));
                 }
                 
-                if (len == this.length()) {
+                if (len == sqlLength()) {
                     return;
                 }
                 String newstr = string_.substring(0, (int) len);
@@ -702,7 +679,7 @@
                 asciiStream_ = new java.io.StringBufferInputStream(string_);
                 unicodeStream_ = new java.io.StringBufferInputStream(string_);
                 characterStream_ = new java.io.StringReader(string_);
-                sqlLength_ = string_.length();
+                setSqlLength(string_.length());
             }
         }
         catch ( SqlException se )
@@ -760,8 +737,6 @@
             }
         }
         
-        lengthInBytes_ = 0;
-        
         if (internalLengthStmt_ != null) {
             try {
                 internalLengthStmt_.closeX();
@@ -903,17 +878,7 @@
         }
     }
 
-    // this method is primarily for mixed clob length calculations.
-    // it was introduced to prevent recursion in the actual char length calculation
-    public long getByteLength() throws SQLException {
-            if (lengthObtained_ == true) {
-                return lengthInBytes_;
-            }
 
-            length();
-            return lengthInBytes_;
-    }
-    
     /*
      * Checks is isValid is true. If it is not true throws 
      * a SQLException stating that a method has been called on
@@ -929,8 +894,10 @@
 
     /**
      * Materialize the stream used for input to the database.
+     *
+     * @throws SqlException
      */
-    private void materializeStream()
+    protected void materializeStream()
         throws SqlException {
         unicodeStream_ = super.materializeStream(isAsciiStream() ? 
                                                         asciiStream_ : 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobOutputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobOutputStream.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobOutputStream.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobOutputStream.java Wed Apr 18 08:39:08 2007
@@ -35,7 +35,7 @@
             in the case of a empty Clob hence check from
             offset_-1
          */
-        if ((offset_-1) > clob_.sqlLength_) {
+        if ((offset_-1) > clob_.sqlLength()) {
             throw new IndexOutOfBoundsException();
         }
     }
@@ -43,15 +43,7 @@
     public void write(int b) throws java.io.IOException {
         byte[] newByte = new byte[1];
         newByte[0] = (byte)b;
-        clob_.string_ = clob_.string_.substring(0, (int) offset_ - 1);
-        // Since this is an OutputStream returned by Clob.setAsciiStream 
-        // use Ascii encoding when creating the String from bytes
-        clob_.string_ = clob_.string_.concat(new String(newByte, "US-ASCII"));
-        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_++;
+        writeBytes(newByte);
     }
 
 
@@ -67,16 +59,23 @@
 
         byte[] newByte = new byte[len];
         System.arraycopy(b, off, newByte, 0, len);
+        writeBytes(newByte);
+    }
+
+
+    private void writeBytes(byte b[])  throws java.io.IOException
+    {
         // Since this is an OutputStream returned by Clob.setAsciiStream 
         // use Ascii encoding when creating the String from bytes
-        String str = new String(newByte, "US-ASCII");
+        String str = new String(b, "US-ASCII");
         clob_.string_ = clob_.string_.substring(0, (int) offset_ - 1);
         clob_.string_ = clob_.string_.concat(str);
         clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
+        clob_.unicodeStream_ 
+            = new java.io.StringBufferInputStream(clob_.string_);
         clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_ += len;
+        clob_.setSqlLength(clob_.string_.length());
+        offset_ += b.length;
     }
 }
 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobWriter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobWriter.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobWriter.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobWriter.java Wed Apr 18 08:39:08 2007
@@ -35,7 +35,7 @@
         clob_ = clob;
         offset_ = offset;
 
-        if (offset_ - 1 > clob_.sqlLength_) {
+        if (offset_ - 1 > clob_.sqlLength()) {
             throw new SqlException(clob_.agent_.logWriter_, 
                 new ClientMessageId(SQLState.BLOB_INVALID_OFFSET),
                 new Long(offset));
@@ -45,12 +45,7 @@
     public void write(int c) {
         StringBuffer sb = new StringBuffer(clob_.string_.substring(0, (int) offset_ - 1));
         sb.append((char)c);
-        clob_.string_ = sb.toString();
-        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_ = clob_.sqlLength_ + 1;
+        updateClob(sb);
     }
 
     public void write(char cbuf[], int off, int len) {
@@ -62,42 +57,38 @@
         }
         StringBuffer sb = new StringBuffer(clob_.string_.substring(0, (int) offset_ - 1));
         sb.append(cbuf, off, len);
-        clob_.string_ = sb.toString();
-        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_ = clob_.sqlLength_ + 1;
+        updateClob(sb);
     }
 
 
     public void write(String str) {
         StringBuffer sb = new StringBuffer(clob_.string_.substring(0, (int) offset_ - 1));
         sb.append(str);
-        clob_.string_ = sb.toString();
-        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_ = clob_.sqlLength_ + 1;
+        updateClob(sb);
     }
 
 
     public void write(String str, int off, int len) {
         StringBuffer sb = new StringBuffer(clob_.string_.substring(0, (int) offset_ - 1));
         sb.append(str.substring(off, off + len));
-        clob_.string_ = sb.toString();
-        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.unicodeStream_ = new java.io.StringBufferInputStream(clob_.string_);
-        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
-        clob_.sqlLength_ = clob_.string_.length();
-        offset_ = clob_.sqlLength_ + 1;
+        updateClob(sb);
     }
 
     public void flush() {
     }
 
     public void close() throws java.io.IOException {
+    }
+    
+    private void updateClob(StringBuffer sb) 
+    {
+        clob_.string_ = sb.toString();
+        clob_.asciiStream_ = new java.io.StringBufferInputStream(clob_.string_);
+        clob_.unicodeStream_ 
+            = new java.io.StringBufferInputStream(clob_.string_);
+        clob_.characterStream_ = new java.io.StringReader(clob_.string_);
+        clob_.setSqlLength(clob_.string_.length());
+        offset_ = clob_.string_.length() + 1;
     }
 }
 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Lob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Lob.java?view=diff&rev=530070&r1=530069&r2=530070
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Lob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Lob.java Wed Apr 18 08:39:08 2007
@@ -47,8 +47,8 @@
     //-----------------------------state------------------------------------------
     protected int dataType_ = 0;      // data type(s) the LOB instance currently contains
 
-    protected long sqlLength_;      // length of the LOB value, as defined by the server
-    protected boolean lengthObtained_;
+    private long sqlLength_;// length of the LOB value, as defined by the server
+    private boolean lengthObtained_;
     
     final private boolean willBeLayerBStreamed_;
 
@@ -71,16 +71,40 @@
 
     // ---------------------------jdbc 2------------------------------------------
 
-    // should only be called by a synchronized method.
-
-
-    // should only be called by a synchronized method.
-    public long sqlLength() throws SqlException {
-        checkForClosedConnection();
+    /**
+     * Return the length of the Lob value represented by this Lob object.
+     * If length is not already known, Lob will first be materialized.
+     * NOTE: The caller needs to deal with synchronization.
+     *
+     * @throws SqlException on execution errors while materializing the stream, 
+     *         or if Layer B streaming is used and length not already obtained.
+     * @return length of Lob value
+     */
+    long sqlLength() throws SqlException 
+    {
+        if (lengthObtained_) return sqlLength_;
+        
+        if (willBeLayerBStreamed()) {
+            throw new SqlException(agent_.logWriter_,
+                                   LOB_OBJECT_LENGTH_UNKNOWN_YET);
+        }
 
+        materializeStream();  // Will set sqlLength_
         return sqlLength_;
     }
 
+    /**
+     * Update the registered length of the Lob value.  To be called by
+     * methods that make changes to the length of the Lob.
+     * NOTE: The caller needs to deal with synchronization.
+     *
+     * @param the new length of the Lob value
+     */
+    void setSqlLength(long length)
+    {
+        sqlLength_ = length;
+        lengthObtained_ = true;
+    }
 
     //-----------------------event callback methods-------------------------------
 
@@ -119,6 +143,17 @@
     void completeLocalCommit() {
         ;
     }
+
+    
+    /**
+     * Method to be implemented by subclasses, so that
+     * #materializedStream(InputStream, String) can be called with subclass
+     * specific parameters and the result assigned to the right stream.
+     *
+     * @throws SqlException
+     */
+    protected abstract void materializeStream() throws SqlException;
+
 
     /**
      * Materialize the given stream into memory and update the internal