db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r546404 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/jdbc/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Date Tue, 12 Jun 2007 07:19:57 GMT
Author: kristwaa
Date: Tue Jun 12 00:19:56 2007
New Revision: 546404

URL: http://svn.apache.org/viewvc?view=rev&rev=546404
Log:
DERBY-2800: Implement Clob.truncate for embedded driver. Also added a test.
Patch file: derby-2800v2.diff

Patch contributed by Anurag Shekhar.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java
  (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java?view=diff&rev=546404&r1=546403&r2=546404
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/ClobStreamControl.java Tue
Jun 12 00:19:56 2007
@@ -77,6 +77,27 @@
         newClob.copyClobContent(clob);
         return newClob;
     }
+    
+    /**
+     * Clones the content of another internal Clob.
+     *
+     * @param dbName name of the assoicated database
+     * @param conChild assoiated connection child
+     * @param clob the Clob whose content to clone
+     * @param length number of chars in new InternalClob
+     * @return A read-write Clob.
+     * @throws IOException if accessing the I/O resources fail (read or write)
+     * @throws SQLException if accessing underlying resources fail
+     */
+    static InternalClob cloneClobContent(String dbName,
+                                         ConnectionChild conChild,
+                                         InternalClob clob,
+                                         long length)
+            throws IOException, SQLException {
+        ClobStreamControl newClob = new ClobStreamControl(dbName, conChild);
+        newClob.copyClobContent(clob, length);
+        return newClob;
+    }
 
     /**
      * Constructs a <code>ClobStreamControl</code> object used to perform
@@ -314,16 +335,20 @@
 
     /**
      * Truncate the Clob to the specifiec size.
-     *
-     * @param newLength the new length, in characters, of the Clob
+     * 
+     * 
+     * @param newCharLength the new length, in characters, of the Clob
      * @throws IOException if accessing the underlying I/O resources fails
      */
-    public synchronized void truncate(long newLength)
+    public synchronized void truncate(long newCharLength)
             throws IOException, SQLException {
         checkIfValid();
         try {
-            this.bytes.truncate(newLength);
-            if (newLength <= this.posCache.getCharPos()) {
+            //get the byteLength in bytes
+            long byteLength = UTF8Util.skipFully (
+                    new BufferedInputStream (getRawByteStream()), newCharLength);
+            this.bytes.truncate(byteLength);
+            if (newCharLength <= this.posCache.getCharPos()) {
                 // Reset the cache if last cached position has been cut away.
                 this.posCache.reset();
             }
@@ -378,6 +403,26 @@
             throw Util.generateCsSQLException(se);
         }
     }
+    
+    /**
+     * Copies the content of another Clob into this one.
+     * 
+     * @param clob the Clob to copy from
+     * @param charLength number of chars to copy
+     * @throws IOException if accessing I/O resources fail (both read and write)
+     * @throws SQLException if accessing underlying resources fail
+     */
+    private void copyClobContent(InternalClob clob, long charLength)
+            throws IOException, SQLException {
+        try {
+            long byteLength = UTF8Util.skipFully (
+                    new BufferedInputStream(clob.getRawByteStream()), charLength);
+            this.bytes.copyData(
+                    new BufferedInputStream(clob.getRawByteStream()), byteLength);
+        } catch (StandardException se) {
+            throw Util.generateCsSQLException(se);
+        }
+    }    
 
     /**
      * Makes sure the Clob has not been released.

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?view=diff&rev=546404&r1=546403&r2=546404
==============================================================================
--- 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 Tue Jun 12 00:19:56
2007
@@ -604,7 +604,25 @@
      */
     public void truncate(long len) throws SQLException
     {
-        throw Util.notImplemented();
+        checkValidity();
+        if (len < 1)
+            throw Util.generateCsSQLException(
+                SQLState.BLOB_BAD_POSITION, new Long(len));
+        try {
+            if (!clob.isWritable()) {
+                makeWritableClobClone(len);
+            }
+            else {
+                clob.truncate (len);
+            }
+        }
+        catch (EOFException eofe) {
+            throw Util.generateCsSQLException(
+                        SQLState.BLOB_POSITION_TOO_LARGE,
+                        new Long(len));
+        } catch (IOException e) {
+            throw Util.setStreamFailure(e);
+        }
     }
 
     /////////////////////////////////////////////////////////////////////////
@@ -673,4 +691,24 @@
                         this, toBeAbandoned);
         toBeAbandoned.release();
     }
+    
+    /**
+     * Makes a writable clone of the current Clob.
+     * <p>
+     * This is called when we have a {@link StoreStreamClob} and the user calls
+     * a method updating the content of the Clob. A temporary Clob will then be
+     * created to hold the updated content.
+     * @param len number of chars to be cloned (should be smaller 
+     *      than clob lenght)
+     * @throws IOException if accessing underlying I/O resources fail
+     * @throws SQLException if accessing underlying resources fail
+     */
+    private void makeWritableClobClone(long len)
+            throws IOException, SQLException {
+        InternalClob toBeAbandoned = this.clob;
+        this.clob = ClobStreamControl.cloneClobContent(
+                        getEmbedConnection().getDBName(),
+                        this, toBeAbandoned, len);
+        toBeAbandoned.release();
+    }    
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?view=diff&rev=546404&r1=546403&r2=546404
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Tue Jun
12 00:19:56 2007
@@ -384,7 +384,10 @@
         long sz = 0;
         while (sz < length) {
             int len = (int) Math.min (length - sz, bufferSize);
-            inStream.read(data, 0, len);
+            len = inStream.read(data, 0, len);
+            if (len < 0)
+                throw new EOFException("Reached end-of-stream " +
+                        "prematurely at " + sz);
             write(data, 0, len, sz);
             sz += len;
         }

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java?view=auto&rev=546404
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java
Tue Jun 12 00:19:56 2007
@@ -0,0 +1,120 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.jdbcapi.ClobTruncateTest
+
+   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.derbyTesting.functionTests.tests.jdbcapi;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.sql.Clob;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import junit.framework.Test;
+import org.apache.derbyTesting.functionTests.util.streams.CharAlphabet;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test case for Clob.truncate
+ */
+public class ClobTruncateTest extends BaseJDBCTestCase {
+    
+    public ClobTruncateTest (String name) {
+        super (name);
+    }
+    
+    private void insertClobs () throws SQLException, IOException {
+        PreparedStatement ps = prepareStatement (
+                "insert into truncateclob" +
+                " values (?,?,?)");
+        //insert a small clob
+        StringBuffer sb = new StringBuffer ();
+        for (int i = 0; i < 100; i++)
+            sb.append ("small clob");
+        int length = sb.length();
+        ps.setInt (1, length);
+        ps.setCharacterStream (2, new StringReader (sb.toString()), length);
+        ps.setInt (3, length/2);
+        ps.execute();
+        
+        //insert a large clob
+        LoopingAlphabetReader reader = new LoopingAlphabetReader (1024 * 1024);
+        ps.setInt (1, 1024 * 1024);
+        ps.setCharacterStream (2, reader, 1024 * 1024);
+        ps.setInt (3, 1024 * 1024 / 2);
+        ps.execute();
+        
+        //insert a non ascii clob
+        LoopingAlphabetReader uReader = 
+                new LoopingAlphabetReader (300000, CharAlphabet.tamil());        
+        ps.setInt (1, 300000);
+        ps.setCharacterStream (2, uReader, 300000);
+        ps.setInt (3, 150000);
+        ps.execute();        
+    }
+    
+    private void checkTruncate (int size, Clob clob, int newSize) throws SQLException {
+        assertEquals ("unexpected clob size", size, clob.length());
+        clob.truncate (newSize);
+        assertEquals ("truncate failed ", newSize, clob.length());
+        //try once more
+        clob.truncate (newSize/2);
+        assertEquals ("truncate failed ", newSize/2, clob.length());
+    }
+    
+    public void testTruncateOnClob () throws SQLException, IOException {
+        insertClobs();
+        getConnection().setAutoCommit (false);
+        ResultSet rs = createStatement().executeQuery("select size, data," +
+                " newsize from truncateclob");
+        try {
+            while (rs.next()) {
+                checkTruncate (rs.getInt (1), rs.getClob(2), rs.getInt(3));
+            }
+        }
+        finally {
+            rs.close();
+            getConnection().commit();
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        Statement stmt = createStatement();
+        stmt.executeUpdate ("drop table truncateclob");
+        super.tearDown();
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        Statement stmt = createStatement();
+        stmt.executeUpdate ("create table truncateclob " +
+                "(size integer, data clob, newSize integer)");
+    }
+    
+    public static Test suite() {
+        //client code is caching clob length so this test will fail
+        return TestConfiguration.embeddedSuite(ClobTruncateTest.class);
+    }       
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTruncateTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java?view=diff&rev=546404&r1=546403&r2=546404
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
Tue Jun 12 00:19:56 2007
@@ -114,6 +114,9 @@
 
             //suite to test updateable reader for clob in embedded driver
             suite.addTest (ClobUpdateableReaderTest.suite());
+            
+            //truncate test for clob
+            suite.addTest (ClobTruncateTest.suite());
         }
 		
         return suite;



Mime
View raw message