db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mi...@apache.org
Subject svn commit: r1303226 - in /db/derby/code/branches/10.7/java: engine/org/apache/derby/iapi/types/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Date Wed, 21 Mar 2012 00:13:02 GMT
Author: mikem
Date: Wed Mar 21 00:13:01 2012
New Revision: 1303226

URL: http://svn.apache.org/viewvc?rev=1303226&view=rev
Log:
DERBY-4544: Don't use the SQLClob.getLength() optimization on non-resetable streams--this
fixes a data corruption. 

backport change #1091172 from 10.8 branch to 10.7.


Added:
    db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DummyReader.java
      - copied unchanged from r1091172, db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DummyReader.java
Modified:
    db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
    db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/SQLClob.java
    db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java

Modified: db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java?rev=1303226&r1=1303225&r2=1303226&view=diff
==============================================================================
--- db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
(original)
+++ db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
Wed Mar 21 00:13:01 2012
@@ -1,6 +1,6 @@
 /*
 
-   Derby - Class org.apache.derby.iapi.types.SQLClob
+   Derby - Class org.apache.derby.iapi.types.HarmonySerialClob
 
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -53,6 +53,8 @@ public class HarmonySerialClob implement
     // required by serialized form
     private long origLen;
 
+    public HarmonySerialClob( String raw ) { this( raw.toCharArray() ); }
+
     public HarmonySerialClob(char[] ch) {
         buf = new char[ch.length];
         origLen = ch.length;

Modified: db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/SQLClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/SQLClob.java?rev=1303226&r1=1303225&r2=1303226&view=diff
==============================================================================
--- db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/SQLClob.java (original)
+++ db/derby/code/branches/10.7/java/engine/org/apache/derby/iapi/types/SQLClob.java Wed Mar
21 00:13:01 2012
@@ -268,6 +268,12 @@ public class SQLClob
         if (stream == null) {
             return super.getLength();
         }
+        //
+        // The following check was put in to fix DERBY-4544. We seem to get
+        // confused if we have to re-use non-resetable streams.
+        //
+        if ( !(stream instanceof Resetable) ) { return super.getLength(); }
+        
         // The Clob is represented as a stream.
         // Make sure we have a stream descriptor.
         boolean repositionStream = (csd != null);

Modified: db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java?rev=1303226&r1=1303225&r2=1303226&view=diff
==============================================================================
--- db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java
(original)
+++ db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ClobTest.java
Wed Mar 21 00:13:01 2012
@@ -45,6 +45,8 @@ import java.util.Arrays;
 
 import junit.framework.Test;
 
+import org.apache.derby.iapi.types.HarmonySerialClob;
+
 import org.apache.derbyTesting.functionTests.util.streams.CharAlphabet;
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
@@ -686,6 +688,133 @@ public class ClobTest
         setAutoCommit(savedAutoCommitValue);
     }
 
+    /**
+     * Verify that generated columns don't interfere with streaming Clobs.
+     * See DERBY-4544.
+     */
+    public  void    test_4544() throws Exception
+    {
+        int     streamLength = 100;
+        String  tableName;
+
+        prepareStatement
+            ( "create table t_4544_0 ( myclob clob )" ).execute();
+        insertClob( streamLength, "t_4544_0" );
+        prepareStatement
+            (
+             "create function replace_4544( inclob clob, target varchar( 32672 ), replacement
varchar( 32672 ) )\n" +
+             "returns clob\n" +
+             "language java parameter style java no sql deterministic\n" +
+             "external name '" + getClass().getName() + ".replace'"
+             ).execute();
+
+        vetTable
+            (
+             streamLength,
+             "generated always as (length(myclob))",
+             Integer.toString( streamLength )
+             );
+        vetTable
+            (
+             streamLength,
+             "varchar( 3 ) generated always as ( substr(myclob, 1, 3) )",
+             " ab"
+             );
+        vetTable
+            (
+             streamLength,
+             "generated always as (locate( 'def', myclob ))",
+             "5"
+             );
+        vetTable
+            (
+             streamLength,
+             "clob generated always as (upper( myclob ))",
+             (new DummyReader( streamLength )).toString().toUpperCase()
+             );
+        vetTable
+            (
+             streamLength,
+             "clob generated always as (trim( myclob ))",
+             (new DummyReader( streamLength )).toString().trim()
+             );
+        vetTable
+            (
+             streamLength,
+             "clob generated always as (replace_4544( myclob, 'b', 'B' ))",
+             (new DummyReader( streamLength )).toString().replace( 'b', 'B' )
+             );
+
+        dropTable( "t_4544_0" );
+        prepareStatement( "drop function replace_4544" ).execute();
+    }
+    private void    vetTable( int streamLength, String gencol, String expectedValue ) throws
Exception
+    {
+        String tableName = "t_4544_1";
+        
+        prepareStatement
+            ( "create table " + tableName + "( myclob clob, gencol " + gencol + " )" ).execute();
+
+        insertClob( streamLength, tableName );
+        vetTable( tableName, expectedValue );
+        vetClob( streamLength, tableName );
+        
+        prepareStatement( "delete from " + tableName ).executeUpdate();
+
+        prepareStatement( "insert into " + tableName + "( myclob ) select myclob from t_4544_0"
).executeUpdate();
+        vetTable( tableName, expectedValue );
+        vetClob( streamLength, tableName );
+        
+        dropTable( tableName );
+    }
+    private void    vetTable( String tableName, String expectedValue ) throws Exception
+    {
+        ResultSet   rs = prepareStatement( "select gencol from " + tableName ).executeQuery();
+        rs.next();
+        assertEquals( expectedValue, rs.getString( 1 ) );
+        rs.close();
+    }
+    private void    insertClob( int streamLength, String tableName ) throws Exception
+    {
+        PreparedStatement   insert = prepareStatement( "insert into " + tableName + "( myclob
) values ( ? )" );
+        insert.setCharacterStream( 1, new DummyReader( streamLength ), streamLength );
+        insert.executeUpdate();
+    }
+    private void    vetClob( int streamLength, String tableName ) throws Exception
+    {
+        PreparedStatement   select = prepareStatement( "select myclob from " + tableName
);
+        ResultSet               rs = select.executeQuery();
+        rs.next();
+        Reader      actualReader = rs.getCharacterStream( 1 );
+        Reader      expectedReader = new DummyReader( streamLength );
+
+        for ( int i = 0; i < streamLength; i++ )
+        {
+            int actual = actualReader.read();
+            if ( actual < 0 )
+            {
+                fail( "    Read stream was only " + i + " characters long." );
+            }
+            
+            int    expected = expectedReader.read();
+            
+            assertEquals( expected, actual );
+        }
+        assertTrue( actualReader.read() < 0 );
+
+        rs.close();
+    }
+    public  static  Clob    replace( Clob clob, String target, String replacement )
+        throws Exception
+    {
+        char    targetChar = target.charAt( 0 );
+        char    replacementChar = replacement.charAt( 0 );
+        String  originalString = clob.getSubString( 1, (int) clob.length() );
+        String  resultString = originalString.replace( targetChar, replacementChar );
+
+        return new HarmonySerialClob( resultString );
+    }
+
     /* Test ideas for more tests
      *
      * truncate:



Mime
View raw message