db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r535319 - in /db/derby/code/trunk/java/client/org/apache/derby/client: am/Clob.java am/ClobLocatorInputStream.java am/ClobLocatorOutputStream.java am/ClobLocatorReader.java am/ClobLocatorWriter.java net/NetCursor.java
Date Fri, 04 May 2007 16:32:43 GMT
Author: rhillegas
Date: Fri May  4 09:32:39 2007
New Revision: 535319

URL: http://svn.apache.org/viewvc?view=rev&rev=535319
Log:
DERBY-2604: Commit Naryayan's ClobLocatorWork_v1.diff, adding locator support to clobs.

Added:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
  (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java
  (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java   (with
props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java   (with
props)
Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java

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=535319&r1=535318&r2=535319
==============================================================================
--- 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 Fri May  4 09:32:39
2007
@@ -169,6 +169,20 @@
         characterStream_ = reader;
         dataType_ |= CHARACTER_STREAM;
     }
+    
+    /**
+     * Create a <code>Clob</code> object for a Clob value stored 
+     * on the server and indentified by <code>locator</code>.
+     * @param agent context for this <code>Clob</code> 
+     *              object (incl. connection).
+     * @param locator reference id to <code>Clob</code> value on server.
+     */
+    public Clob(Agent agent, int locator)  
+    {
+        super(agent, false);
+        locator_ = locator;
+        dataType_ |= LOCATOR;
+    }
 
     /**
      * Create a <code>Clob</code> of unknown length.
@@ -307,7 +321,18 @@
         // 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));
+        //Check to see if the Clob object is locator enabled.
+        if (isLocator()) {
+            //The Clob object is locator enabled. Hence call the stored
+            //procedure CLOBGETLENGTH to determine the length of the Clob.
+            return agent_.connection_.locatorProcedureCall()
+                .clobGetSubString(locator_, pos, (int)actualLength);
+        }
+        else {
+            //The Clob object is not locator enabled.
+            return string_.substring
+                    ((int) pos - 1, (int) (pos - 1 + actualLength));
+        }
     }
 
     public java.io.Reader getCharacterStream() throws SQLException {
@@ -339,7 +364,13 @@
     private java.io.Reader getCharacterStreamX() throws SqlException {
         checkForClosedConnection();
 
-        if (isCharacterStream())  // this Lob is used for input
+        //check is this Lob is locator enabled
+        if (isLocator()) {
+            //The Lob is locator enabled. Return an instance of the Locator
+            //enabled Writer implementation
+            return new ClobLocatorReader(agent_.connection_, this);
+        }
+        else if (isCharacterStream())  // this Lob is used for input
         {
             return characterStream_;
         }
@@ -380,8 +411,15 @@
         {
             return asciiStream_;
         }
-
-        return new AsciiStream(string_, new java.io.StringReader(string_));
+        else if(isLocator()) { // Check to see if this Lob is locator enabled
+            //The Lob is locator enabled. Return an instance
+            //of the Locator enabled Clob specific InputStream
+            //implementation.
+            return new ClobLocatorInputStream(agent_.connection_,this);
+        }
+        else {
+            return new AsciiStream(string_, new java.io.StringReader(string_));
+        }
     }
 
     public long position(String searchstr, long start) throws SQLException {
@@ -425,18 +463,28 @@
     private long positionX(String searchstr, long start) throws SqlException {
         checkForClosedConnection();
 
-
+        long index = -1;
         if (start <= 0) {
             throw new SqlException(agent_.logWriter_, 
                 new ClientMessageId(SQLState.INVALID_API_PARAMETER),
                 new Long(start), "start", "Clob.position()");
         }
-
-        int index = string_.indexOf(searchstr, (int) start - 1);
-        if (index != -1) {
-            index++; // api index starts at 1
+        
+        //Check is locator support is available for this LOB.
+        if (isLocator()) {
+            //Locator support is available. Hence call 
+            //CLOBGETPOSITIONFROMSTRING to determine the position 
+            //of the given substring inside the LOB.
+            index = agent_.connection_.locatorProcedureCall()
+                .clobGetPositionFromString(locator_, searchstr, start);
+        } else {
+            //Locator support is not available.
+            index = string_.indexOf(searchstr, (int) start - 1);
+            if (index != -1) {
+                index++; // api index starts at 1
+            }
         }
-        return (long) index;
+        return index;
     }
 
     public long position(java.sql.Clob searchstr, long start) throws SQLException {
@@ -586,12 +634,26 @@
 
         int length = 0;
         length = Math.min((str.length() - offset), len);
-        String newString = string_.substring(0, (int) pos - 1);
-        string_ = newString.concat(str.substring(offset, offset + length));
-        asciiStream_ = new java.io.StringBufferInputStream(string_);
-        unicodeStream_ = new java.io.StringBufferInputStream(string_);
-        characterStream_ = new java.io.StringReader(string_);
-        setSqlLength(string_.length());
+        //check if the Clob object is locator enabled
+        if (isLocator()) {
+            //The Clob is locator enabled. Call the CLOBSETSTRING
+            //stored procedure to set the given string in the Clob.
+            agent_.connection_.locatorProcedureCall().clobSetString
+                (locator_, pos, length, str.substring(offset, offset + length));
+            if (pos+length-1 > sqlLength()) { // Wrote beyond the old end
+                // Update length
+                setSqlLength(pos + length - 1);
+            }
+        }
+        else {
+            //The Clob is not locator enabled.
+            String newString = string_.substring(0, (int) pos - 1);
+            string_ = newString.concat(str.substring(offset, offset + length));
+            asciiStream_ = new java.io.StringBufferInputStream(string_);
+            unicodeStream_ = new java.io.StringBufferInputStream(string_);
+            characterStream_ = new java.io.StringReader(string_);
+            setSqlLength(string_.length());
+        }
         return length;
     }
 
@@ -607,8 +669,19 @@
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceEntry(this, "setAsciiStream", (int) pos);
                 }
-                ClobOutputStream outStream = new ClobOutputStream(this, pos);
-
+                java.io.OutputStream outStream = null;
+                
+                if(isLocator()) { // Check to see if the Lob is locator enabled
+                    //The Lob is locator enabled. Return an instance of the
+                    //Locator enabled Clob specific OutputStream implementation.
+                    outStream = new ClobLocatorOutputStream
+                            (agent_.connection_, this, pos);
+                }
+                else {
+                    //The Lob is not locator enabled.
+                    outStream = new 
+                            ClobOutputStream(this, pos);
+                }
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceExit(this, "setAsciiStream", outStream);
                 }
@@ -633,7 +706,16 @@
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceEntry(this, "setCharacterStream", (int) pos);
                 }
-                ClobWriter writer = new ClobWriter(this, pos);
+                java.io.Writer writer = null;
+                //Check to see if this Clob is locator enabled.
+                if (isLocator()) {
+                    //return an instance of the locator enabled implementation
+                    //of the writer interface
+                    writer = new ClobLocatorWriter(agent_.connection_, this, pos);
+                }
+                else {//The Lob is not locator enabled.
+                    writer = new ClobWriter(this, pos);
+                }
 
                 if (agent_.loggingEnabled()) {
                     agent_.logWriter_.traceExit(this, "setCharacterStream", writer);
@@ -674,12 +756,23 @@
                 if (len == sqlLength()) {
                     return;
                 }
-                String newstr = string_.substring(0, (int) len);
-                string_ = newstr;
-                asciiStream_ = new java.io.StringBufferInputStream(string_);
-                unicodeStream_ = new java.io.StringBufferInputStream(string_);
-                characterStream_ = new java.io.StringReader(string_);
-                setSqlLength(string_.length());
+                
+                //check whether the Lob is locator enabled.
+                if (isLocator()) {
+                    //The Lob is locator enabled then call the stored
+                    //procedure CLOBTRUNCATE to truncate this Lob.
+                    agent_.connection_.locatorProcedureCall().
+                            clobTruncate(locator_, len);
+                }
+                else {
+                    //The Lob is not locator enabled.
+                    String newstr = string_.substring(0, (int) len);
+                    string_ = newstr;
+                    asciiStream_ = new java.io.StringBufferInputStream(string_);
+                    unicodeStream_ = new java.io.StringBufferInputStream(string_);
+                    characterStream_ = new java.io.StringReader(string_);
+                    setSqlLength(string_.length());
+                }
             }
         }
         catch ( SqlException se )
@@ -778,16 +871,27 @@
                     (int) pos, length);
             }
             checkPosAndLength(pos, length);
-            String retVal_str = null;
-            try {
-                retVal_str = getSubStringX(pos, (int)length);
-            }
-            catch(SqlException sqle) {
-                throw sqle.getSQLException();
-            }
-            Reader retVal = new java.io.StringReader(retVal_str);
-            if (agent_.loggingEnabled()) {
-                agent_.logWriter_.traceExit(this, "getCharacterStream", retVal);
+            Reader retVal = null;
+            //check if the Lob is locator enabled.
+            if(isLocator()) {
+                //The Lob is locator enabled. Return the locator enabled
+                //Implementation of a Clob Reader.
+                retVal = new ClobLocatorReader(agent_.connection_, this, 
+                        pos, length);
+            }
+            else {
+                //The Lob is not locator enabled.
+                String retVal_str = null;
+                try {
+                    retVal_str = getSubStringX(pos, (int)length);
+                }
+                catch(SqlException sqle) {
+                    throw sqle.getSQLException();
+                }
+                retVal = new java.io.StringReader(retVal_str);
+                if (agent_.loggingEnabled()) {
+                    agent_.logWriter_.traceExit(this, "getCharacterStream", retVal);
+                }
             }
             return retVal;
         }
@@ -906,4 +1010,21 @@
         dataType_ = UNICODE_STREAM;
     }
     
+    /*---------------------------------------------------------------------
+      Methods used in the locator implementation.
+     ----------------------------------------------------------------------*/
+    
+    /**
+     * Get the length in bytes of the <code>Clob</code> value represented by
+     * this locator based <code>Clob</code> object.
+     *
+     * A stored procedure call will be made to get it from the server.
+     * @throws org.apache.derby.client.am.SqlException
+     * @return length of <code>Clob</code> in bytes
+     */
+    long getLocatorLength() throws SqlException
+    {
+        return agent_.connection_.locatorProcedureCall()
+            .clobGetLength(locator_);
+    }
 }

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java?view=auto&rev=535319
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
(added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
Fri May  4 09:32:39 2007
@@ -0,0 +1,139 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.ClobLocatorInputStream
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ 
+ */
+
+package org.apache.derby.client.am;
+
+import java.sql.CallableStatement;
+import java.sql.SQLException;
+
+import java.io.IOException;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+/**
+ * An <code>InputStream</code> that will use an locator to fetch the
+ * Clob value from the server.
+ * <p>
+ * Closing a <code>ByteArrayInputStream</code> has no effect. The methods in
+ * this class can be called after the stream has been closed without
+ * generating an <code>IOException</code>.
+ * <p>
+ * This <code>InputStream</code> implementation is pretty basic.  No
+ * buffering of data is done.  Hence, for efficieny #read(byte[])
+ * should be used instead of #read().  Marks are not supported, but it
+ * should be pretty simple to extend the implementation to support
+ * this.  A more efficient skip implementation should also be
+ * straight-forward.
+ */
+
+public class ClobLocatorInputStream extends java.io.InputStream {
+    
+    /**
+     * Connection used to read Clob from server.
+     */
+    private Connection connection;
+    
+    /**
+     * The Clob to be accessed.
+     */
+    private Clob clob;
+    
+    /**
+     * Current position in the underlying Clob.
+     * Clobs are indexed from 1
+     */
+    private long currentPos = 1;
+    
+    /**
+     * Create an <code>InputStream</code> for reading the
+     * <code>Clob</code> value represented by the given locator based
+     * <code>Clob</code> object.
+     * @param connection connection to be used to read the
+     *        <code>Clob</code> value from the server
+     * @param clob <code>Clob</code> object that contains locator for
+     *        the <code>Clob</code> value on the server.
+     */
+    public ClobLocatorInputStream(Connection connection, Clob clob) {
+        SanityManager.ASSERT(clob.isLocator());
+        
+        this.connection = connection;
+        this.clob = clob;
+    }
+    
+    /**
+     * @see java.io.InputStream#read()
+     *
+     * This method fetches one byte at a time from the server. For more
+     * efficient retrieval, use #read(byte[]).
+     */
+    public int read() throws IOException {
+        byte[] bytes = readBytes(1);
+        if (bytes.length == 0) { // EOF
+            return -1;
+        } else {
+            return bytes[0];
+        }
+    }
+    
+    /**
+     * @see java.io.InputStream#read(byte[], int, int)
+     */
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (len == 0) return 0;
+        if ((off < 0) || (len < 0) || (off+len > b.length)) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        byte[] bytes = readBytes(len);
+        if (bytes.length == 0) { // EOF
+            return -1;
+        } else {
+            System.arraycopy(bytes, 0, b, off, bytes.length);
+            return bytes.length;
+        }
+    }
+    
+    /**
+     * Read the next <code>len</code> bytes of the <code>Clob</code>
+     * value from the server.
+     *
+     * @param len number of bytes to read
+     * @throws java.io.IOException Wrapped SqlException if reading
+     *         from server fails.
+     * @return <code>byte[]</code> containing the read bytes
+     */
+    private byte[] readBytes(int len) throws IOException {
+        try {
+            int actualLength
+                    = (int )Math.min(len, clob.sqlLength() - currentPos + 1);
+            String resultStr = connection.locatorProcedureCall().
+                    clobGetSubString(clob.getLocator(),
+                    currentPos, actualLength);
+            byte[] result = resultStr.getBytes();
+            currentPos += result.length;
+            return result;
+        } catch (SqlException ex) {
+            IOException ioEx = new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java?view=auto&rev=535319
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java
(added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java
Fri May  4 09:32:39 2007
@@ -0,0 +1,149 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.ClobLocatorOutputStream
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ 
+ */
+
+package org.apache.derby.client.am;
+
+import java.io.IOException;
+
+/**
+ * An <code>OutputStream</code> that will use an locator to write
+ * bytes to the Clob value on the server.
+ * <p>
+ * Closing a <code>ByteArrayInputStream</code> has no effect. The methods in
+ * this class can be called after the stream has been closed without
+ * generating an <code>IOException</code>.
+ * <p>
+ * This <code>OutputStream</code> implementation is pretty basic.  No
+ * buffering of data is done.  Hence, for efficieny #write(byte[])
+ * should be used instead of #write(int).
+ */
+public class ClobLocatorOutputStream extends java.io.OutputStream {
+    
+    /**
+     * Connection used to read Clob from server.
+     */
+    private Connection connection;
+    
+    /**
+     * The Clob to be accessed.
+     */
+    private Clob clob;
+    
+    /**
+     * Current position in the underlying Clob.
+     * Clobs are indexed from 1
+     */
+    private long currentPos;
+    
+    
+    /**
+     * Create an <code>OutputStream</code> for writing to the
+     * <code>Clob</code> value represented by the given locator based
+     * <code>Clob</code> object.
+     * @param connection connection to be used to write to the
+     *        <code>Clob</code> value on the server
+     * @param clob <code>Clob</code> object that contains locator for
+     *        the <code>Clob</code> value on the server.
+     * @param pos the position in the <code>CLOB</code> value at which
+     *        to start writing; the first position is 1
+     * @throws org.apache.derby.client.am.SqlException
+     */
+    public ClobLocatorOutputStream(Connection connection, Clob clob, long pos)
+    throws SqlException {
+        if (pos-1 > clob.sqlLength()) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        this.connection = connection;
+        this.clob = clob;
+        this.currentPos = pos;
+    }
+    
+    /**
+     * @see java.io.OutputStream#write(int)
+     *
+     * This method writes one byte at a time to the server. For more
+     * efficient writing, use #write(byte[]).
+     */
+    public void write(int b) throws IOException {
+        byte[] ba = {(byte )b};
+        writeBytes(ba);
+    }
+    
+    /**
+     * @see java.io.OutputStream#write(byte[])
+     */
+    public void write(byte[] b) throws IOException {
+        writeBytes(b);
+    }
+    
+    /**
+     * @see java.io.OutputStream#write(byte[], int, int)
+     */
+    public void write(byte[] b, int off, int len) throws IOException {
+        if (len == 0) return;
+        if ((off < 0) || (off > b.length) || (len < 0) ||
+                (off+len > b.length) || (off+len < 0)) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        byte[] ba = b;
+        if ((off > 0) || (len < b.length)) { // Copy the part we will use
+            ba = new byte[len];
+            System.arraycopy(b, off, ba, 0, len);
+        }
+        writeBytes(ba);
+    }
+    
+    /**
+     * @see java.io.OutputStream#flush()
+     */
+    public void flush() {
+        //There is no necessity to flush since each write
+        //automatically calls the stored procedure to write
+        //the Bytes to the locator on the server.
+    }
+    
+    /**
+     * Write the <code>byte[]</code> to the <code>Clob</code> value
on
+     * the server; starting from the current position of this stream.
+     *
+     * @param b The byte array containing the bytes to be written
+     * @throws java.io.IOException Wrapped SqlException if writing
+     *         to server fails.
+     */
+    private void writeBytes(byte[] b) throws IOException {
+        try {
+            String clobStr = new String(b);
+            connection.locatorProcedureCall().clobSetString
+                    (clob.locator_, currentPos, b.length, clobStr);
+            currentPos += b.length;
+            if (currentPos-1 > clob.sqlLength()) {
+                // Wrote past the old end of the Clob value, update length
+                clob.setSqlLength(currentPos - 1);
+            }
+        } catch (SqlException ex) {
+            IOException ioEx= new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java?view=auto&rev=535319
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java Fri
May  4 09:32:39 2007
@@ -0,0 +1,216 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.ClobLocatorReader
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ 
+ */
+
+package org.apache.derby.client.am;
+
+import java.io.IOException;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+/**
+ * An <code>Reader</code> that will use an locator to fetch the
+ * Clob value from the server.
+ * <p>
+ * This <code>Reader</code> implementation is pretty basic.  No
+ * buffering of data is done.  Hence, for efficieny #read(char[])
+ * should be used instead of #read().  Marks are not supported, but it
+ * should be pretty simple to extend the implementation to support
+ * this.  A more efficient skip implementation should also be
+ * straight-forward.
+ */
+public class ClobLocatorReader extends java.io.Reader {
+    /**
+     * Connection used to read Clob from server.
+     */
+    private Connection connection;
+    
+    /**
+     * The Clob to be accessed.
+     */
+    private Clob clob;
+    
+    /**
+     * Current position in the underlying Clob.
+     * Clobs are indexed from 1
+     */
+    private long currentPos = 1;
+    
+    /**
+     * The length in characters of the partial value to be retrieved.
+     */
+    private long length = -1;
+    
+    /**
+     * Stores the information to whether this Reader has been
+     * closed or not. Is set to true if close() has been
+     * called. Is false otherwise.
+     */
+    private boolean isClosed = false;
+    
+    /**
+     * Create an <code>Reader</code> for reading the
+     * <code>Clob</code> value represented by the given locator based
+     * <code>Clob</code> object.
+     * @param connection connection to be used to read the
+     *        <code>Clob</code> value from the server
+     * @param clob <code>Clob</code> object that contains locator for
+     *        the <code>Clob</code> value on the server.
+     */
+    public ClobLocatorReader(Connection connection, Clob clob) {
+        SanityManager.ASSERT(clob.isLocator());
+        
+        this.connection = connection;
+        this.clob = clob;
+    }
+    
+    /**
+     * Create an <code>Reader</code> for reading the
+     * <code>Clob</code> value represented by the given locator based
+     * <code>Clob</code> object.
+     * @param connection connection to be used to read the
+     *        <code>Clob</code> value from the server
+     * @param clob <code>Clob</code> object that contains locator for
+     *        the <code>Clob</code> value on the server.
+     * @param pos The offset to the first character of the partial value to be
+     *            retrieved.
+     * @param len The length in characters of the partial value to be retrieved.
+     */
+    public ClobLocatorReader(Connection connection, Clob clob, 
+            long pos, long len) {
+        this(connection, clob);
+        currentPos = pos;
+        length = len;
+    }
+    
+    /**
+     * @see java.io.Reader#read()
+     *
+     * This method fetches one character at a time from the server. For more
+     * efficient retrieval, use #read(char[]).
+     */
+    public int read() throws IOException {
+        checkClosed();
+        char[] chars = readCharacters(1);
+        if (chars.length == 0) { // EOF
+            return -1;
+        } else {
+            return chars[0];
+        }
+    }
+    
+    /**
+     * @see java.io.Reader#read(char[], int, int)
+     */
+    public int read(char[] c, int off, int len) throws IOException {
+        checkClosed();
+        if (len == 0) return 0;
+        if ((off < 0) || (len < 0) || (off+len > c.length)) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        char[] chars = readCharacters(len);
+        if (chars.length == 0) { // EOF
+            return -1;
+        } else {
+            System.arraycopy(chars, 0, c, off, chars.length);
+            return chars.length;
+        }
+    }
+    
+    /**
+     * @see java.io.Reader#close()
+     */
+    public void close() throws IOException {
+        if (isClosed) {
+            return;
+        }
+        isClosed = true;
+        connection = null;
+        clob = null;
+    }
+    
+    /**
+     * Check to see if this <code>Reader</code> is closed. If it
+     * is closed throw an <code>IOException</code> that states that
+     * the stream is closed.
+     *
+     * @throws IOException if isClosed = true.
+     */
+    private void checkClosed() throws IOException {
+        //if isClosed=true this means that close() has
+        //been called on this Reader already.
+        if(isClosed) {
+            //since this method would be used from the read method
+            //implementations throw an IOException that states that
+            //these operations cannot be done once close has been
+            //called.
+            throw new IOException("This operation is not " +
+                    "permitted because the" +
+                    "Reader has been closed");
+        }
+    }
+    
+    /**
+     * Read the next <code>len</code> characters of the <code>Clob</code>
+     * value from the server.
+     *
+     * @param len number of characters to read.
+     * @throws java.io.IOException Wrapped SqlException if reading
+     *         from server fails.
+     * @return <code>char[]</code> containing the read characters.
+     */
+    private char[] readCharacters(int len) throws IOException {
+        try {
+            int actualLength
+                    = (int )Math.min(len, getStreamLength() - currentPos + 1);
+            String resultStr = connection.locatorProcedureCall().
+                    clobGetSubString(clob.getLocator(),
+                    currentPos, actualLength);
+            char[] result = resultStr.toCharArray();
+            currentPos += result.length;
+            return result;
+        } catch (SqlException ex) {
+            IOException ioEx = new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+    
+    /**
+     * Return the length of the stream.
+     *
+     * @return the length of the stream.
+     */
+    private long getStreamLength() throws SqlException {
+        //check to see if the length of the stream has been set
+        //during initialization
+        if(length != -1) {
+            //The length has been set. Hence return this as the
+            //length
+            return length;
+        }
+        else {
+            //The length has not been set. Obtain the length from
+            //the Clob.
+            return clob.sqlLength();
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java?view=auto&rev=535319
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java Fri
May  4 09:32:39 2007
@@ -0,0 +1,181 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.ClobLocatorWriter
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ 
+ */
+
+package org.apache.derby.client.am;
+
+import java.io.IOException;
+
+/**
+ * An <code>Writer</code> that will use an locator to write the
+ * Clob value into the server.
+ * <p>
+ * This <code>Writer</code> implementation is pretty basic.  No
+ * buffering of data is done.  Hence, for efficieny #write(char[])
+ * should be used instead of #write(int).
+ */
+public class ClobLocatorWriter extends java.io.Writer {
+    /**
+     * Connection used to read Clob from server.
+     */
+    private Connection connection;
+    
+    /**
+     * The Clob to be accessed.
+     */
+    private Clob clob;
+    
+    /**
+     * Current position in the underlying Clob.
+     * Clobs are indexed from 1
+     */
+    private long currentPos;
+    
+    /**
+     * Stores the information to whether this Writer has been
+     * closed or not. Is set to true if close() has been
+     * called. Is false otherwise.
+     */
+    private boolean isClosed = false;
+    
+    /**
+     * Create a <code>Writer</code> for writing to the
+     * <code>Clob</code> value represented by the given locator based
+     * <code>Clob</code> object.
+     * @param connection connection to be used to write to the
+     *        <code>Clob</code> value on the server
+     * @param clob <code>Clob</code> object that contains locator for
+     *        the <code>Clob</code> value on the server.
+     * @param pos the position in the <code>CLOB</code> value at which
+     *        to start writing; the first position is 1
+     * @throws org.apache.derby.client.am.SqlException
+     */
+    public ClobLocatorWriter(Connection connection, Clob clob, long pos)
+    throws SqlException {
+        if (pos-1 > clob.sqlLength()) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        this.connection = connection;
+        this.clob = clob;
+        this.currentPos = pos;
+    }
+    
+    /**
+     * @see java.io.Writer#close()
+     */
+    public void close() throws IOException {
+        if (isClosed) {
+            return;
+        }
+        isClosed = true;
+        connection = null;
+        clob = null;
+    }
+    
+    /**
+     * Check to see if this <code>Writer</code> is closed. If it
+     * is closed throw an <code>IOException</code> that states that
+     * the stream is closed.
+     *
+     * @throws IOException if isClosed = true.
+     */
+    private void checkClosed() throws IOException {
+        //if isClosed=true this means that close() has
+        //been called on this Writer already.
+        if(isClosed) {
+            //since this method would be used from the write method
+            //implementations throw an IOException that states that
+            //these operations cannot be done once close has been
+            //called.
+            throw new IOException("This operation is not " +
+                    "permitted because the" +
+                    "Writer has been closed");
+        }
+    }
+    
+    /**
+     * @see java.io.Writer#write(int)
+     *
+     * This method writes one Character at a time to the server. For more
+     * efficient writing, use #write(char[]).
+     */
+    public void write(int c) throws IOException {
+        char[] ca = {(char )c};
+        writeCharacters(ca, 0, ca.length);
+    }
+    
+    /**
+     * @see java.io.Writer#write(char[])
+     */
+    public void write(char[] c) throws IOException {
+        checkClosed();
+        writeCharacters(c, 0, c.length);
+    }
+    
+    /**
+     * @see java.io.Writer#flush()
+     */
+    public void flush() {
+        //There is no necessity to flush since each write
+        //automatically calls the stored procedure to write
+        //the characters to the locator on the server.
+    }
+    
+    
+    /**
+     * @see java.io.Writer#write(char[], int, int)
+     */
+    public void write(char[] c, int off, int len) throws IOException {
+        checkClosed();
+        if (len == 0) return;
+        if ((off < 0) || (off > c.length) || (len < 0) ||
+                (off+len > c.length) || (off+len < 0)) {
+            throw new IndexOutOfBoundsException();
+        }
+        writeCharacters(c, off, len);
+    }
+    
+    /**
+     * Write the <code>char[]</code> to the <code>Clob</code> value
on
+     * the server; starting from the current position of this stream.
+     *
+     * @param c The character array containing the chars to be written
+     * @throws java.io.IOException Wrapped SqlException if writing
+     *         to server fails.
+     */
+    private void writeCharacters(char[] c, int off, int len)
+    throws IOException {
+        try {
+            connection.locatorProcedureCall().clobSetString
+                    (clob.locator_, currentPos, c.length, 
+                    new String(c, off, len));
+            currentPos += c.length;
+            if (currentPos-1 > clob.sqlLength()) {
+                // Wrote past the old end of the Clob value, update length
+                clob.setSqlLength(currentPos - 1);
+            }
+        } catch (SqlException ex) {
+            IOException ioEx= new IOException();
+            ioEx.initCause(ex);
+            throw ioEx;
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClobLocatorWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java?view=diff&rev=535319&r1=535318&r2=535319
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java Fri May  4
09:32:39 2007
@@ -1103,6 +1103,13 @@
 
 
     public Clob getClobColumn_(int column, Agent agent) throws SqlException {
+        // Check for locator
+        int locator = locator(column);
+        if (locator > 0) { // Create locator-based LOB object
+            return new Clob(agent, locator);
+        }
+        
+        // The Clob value has been sent instead of locator 
         int index = column - 1;
         int dataOffset;
         byte[] data;



Mime
View raw message