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 ma...@apache.org on 2013/06/03 21:38:39 UTC

svn commit: r1489123 - in /db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests: tests/jdbcapi/ParameterMappingTest.java util/streams/CharAlphabet.java

Author: mamta
Date: Mon Jun  3 19:38:39 2013
New Revision: 1489123

URL: http://svn.apache.org/r1489123
Log:
DERBY-6237(PreparedStatement.execute() fails starting 10.2 when multiple rows are updated and PreparedStatement.setCharacterStream(int, Reader, int) is used)

This commit tests setCharacterStream on CLOB and VARCHAR columns as 2 separate tests. This way failure of one data type will not mask the behavior of the other data type.

I found through these tests that in 10.5,
1)setCharacterStream on VARCHAR columns work fine(just like 10.1 through 10.4 releases) for both one row and multi-row update through prepared statement.
2)But setCharacterStream on CLOB column when update touches more than one row(both for embedded and network server) fails in 10.5 release.



Modified:
    db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
    db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java

Modified: db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java?rev=1489123&r1=1489122&r2=1489123&view=diff
==============================================================================
--- db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java (original)
+++ db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java Mon Jun  3 19:38:39 2013
@@ -20,6 +20,7 @@
 
 package org.apache.derbyTesting.functionTests.tests.jdbcapi;
 
+import java.io.CharArrayReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
@@ -38,6 +39,7 @@ import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
+import java.util.Arrays;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -48,6 +50,9 @@ import org.apache.derbyTesting.junit.JDB
 import org.apache.derbyTesting.junit.TestConfiguration;
 import org.apache.derbyTesting.junit.Utilities;
 
+import org.apache.derbyTesting.functionTests.util.streams.CharAlphabet;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
+
 /**
  * 
  */
@@ -3787,6 +3792,196 @@ public class ParameterMappingTest extend
                 out[0] = new BigDecimal(84.1);
         }
 
+    	private static boolean compareClobReader2CharArray
+    		(char[] cArray, Reader charReader) throws Exception {
+    		char[] clobChars = new char[cArray.length];
+
+    		int readChars = 0;
+    		int totalCharsRead = 0;
+
+    		do {
+    			readChars = charReader.read(clobChars, totalCharsRead, cArray.length - totalCharsRead);
+    			if (readChars != -1) 
+    				totalCharsRead += readChars;
+    		} while (readChars != -1 && totalCharsRead < cArray.length);
+    		charReader.close();
+    		if (!java.util.Arrays.equals(cArray, clobChars)) {
+    			return false;
+    		}
+
+    		return true;
+    	}
+
+	    /**
+	     * DERBY-6237(PreparedStatement.execute() fails starting 10.2 when 
+	     *  multiple rows are updated and 
+	     *  PreparedStatement.setCharacterStream(int, Reader, int) is used)  
+    	 * Test setCharacterStream on CLOB column 
+	     */
+    	public void testUpdateSetCharacterStreamClob() throws Exception
+        {
+    		helperTestClobOrVarchar(true);
+        }
+        
+	    /**
+	     * DERBY-6237(PreparedStatement.execute() fails starting 10.2 when 
+	     *  multiple rows are updated and 
+	     *  PreparedStatement.setCharacterStream(int, Reader, int) is used)  
+    	 * Test setCharacterStream on VARCHAR column 
+	     */
+    	public void testUpdateSetCharacterStreamVarchar() throws Exception
+        {
+    		helperTestClobOrVarchar(false);
+        }
+    	
+	    /**
+	     * DERBY-6237(PreparedStatement.execute() fails starting 10.2 when 
+	     *  multiple rows are updated and 
+	     *  PreparedStatement.setCharacterStream(int, Reader, int) is used) 
+	     * In 10.1, setCharacterStream to update CLOB and varchar columns
+	     *  work even when update is going to update more than one row
+	     *  
+	     *  @param 	conn - Connection object
+	     *  @param 	testCLOB - true means test setCharacterStream on CLOB
+	     *                   - false means test setCharacterStream on VARCHAR
+	     * @throws Exception
+	     */
+		private void helperTestClobOrVarchar(
+				boolean testCLOB) throws Exception
+		{
+	        Statement s = createStatement();
+	        dropTable("TESTUPDATECHARSTREAM");
+	        s.executeUpdate("CREATE TABLE TestUpdateCharStream ("+
+	                "c1 VARCHAR(64) NOT NULL, " +
+	          	    "c2 INTEGER, " +
+	                "c3 CLOB, " +
+	          	    "c4 VARCHAR(32000))"); 
+	        s.executeUpdate("INSERT INTO TestUpdateCharStream (c1, c2) " +
+	                "VALUES ('AAAAA', 1)");
+	        s.executeUpdate("INSERT INTO TestUpdateCharStream (c1, c2) " +
+	                "VALUES ('EEEEE', 1)");
+	        
+	        //update only one row and use short data
+	        helperTestDerby6237(1,1, testCLOB);
+	        //update only one row and use large data
+	        helperTestDerby6237(1,2, testCLOB);
+	        //update two rows and use short data
+	        //Once DERBY-6237 is fixed, we should remove following if condition
+	        // Following if condition will skip the test for 2 row update when
+	        //  testing CLOB columns in both embedded and network server with 
+	        //  short data. This results in failure in 10.4
+	        if ((!testCLOB))
+	            helperTestDerby6237(2,1, testCLOB);
+	        //update two rows and use large data
+	        //Once DERBY-6237 is fixed, we should remove following if condition
+	        // Following if condition will skip the test for 2 row update when
+	        //  testing CLOB columns in both embedded and network server with 
+	        //  large data. This results in failure in 10.4
+	        if (!(testCLOB))
+	            helperTestDerby6237(2,2, testCLOB);
+
+	        dropTable("TESTUPDATECHARSTREAM");
+	        s.close();
+        }
+
+    	//numberOfRowsToUpdate - value 1 or 2
+    	//testVariation - if 1 then update CLOB/VARCHAR with short data
+    	//                if 2 then update CLOB/VARCHAR with large data
+        //testCLOB - true means test setCharacterStream on CLOB
+        //         - false means test setCharacterStream on VARCHAR
+    	private void helperTestDerby6237(int numberOfRowsToUpdate, 
+                int testVariation,
+                boolean testCLOB) throws Exception
+        {
+            CharAlphabet a1 = CharAlphabet.singleChar('a');
+
+            //Following will update one or 2 rows depending on the 1st param
+            //Following will update CLOB column or VARCHAR column with short
+            // or large data depending on param 2
+            //Following will update CLOB column or VARCHAR column depending
+            // on 3rd param
+            PreparedStatement ps = prepareStatement(
+                    "UPDATE TestUpdateCharStream SET " +
+                    (testCLOB==true ? "c3" : "c4") + " = ?, " + 
+                    "c2 = c2 + 1 WHERE c1 IN (?, ?)");
+            switch (testVariation) {
+            case 1 :
+            	//test short data
+                ps.setCharacterStream(1,
+                        new LoopingAlphabetReader(50, a1), 50);
+                break;
+            case 2 :
+            	//test large data
+            	if (testCLOB) {
+            		//for CLOB column, use 50K data
+                    ps.setCharacterStream(1,
+                            new LoopingAlphabetReader(50000, a1), 50000);
+            	} else {
+            		//for VARCHAR column, use 32K data
+    	            ps.setCharacterStream(1,
+    	                    new LoopingAlphabetReader(32000, a1), 32000);
+            	}
+                break;
+            }
+
+            //First value in IN clause is getting set to 'AAAAA'
+            // Using setCharacterStream on VARCHAR to set the value
+            ps.setCharacterStream(2, new CharArrayReader("AAAAA".toCharArray()), 5);
+            
+            if (numberOfRowsToUpdate == 1 ) {
+                //Second value in IN clause is also getting set to 'AAAAA', which 
+                // means prepared statement will update only one row
+                ps.setObject(3, "AAAAA", Types.VARCHAR);
+            } else {
+                //Second value in IN clause is also getting set to 'EEEEE', which 
+                // means prepared statement will update two rows
+                ps.setObject(3, "EEEEE", Types.VARCHAR);
+            }        	
+            ps.execute();
+            
+            //verify updated data. Update happened to either CLOB column or VARCHAR
+            // column. It is decided by param 3
+            ResultSet rs;
+            ps = prepareStatement(
+                    "select " +
+                    (testCLOB==true ? "c3 " : "c4 ") + 
+                    "from TestUpdateCharStream " + 
+                    "WHERE c1 IN (?, ?)");
+            ps.setCharacterStream(1, new CharArrayReader("AAAAA".toCharArray()), 5);
+            if (numberOfRowsToUpdate == 1 ) {
+                ps.setObject(2, "AAAAA", Types.VARCHAR);
+            } else {
+                ps.setObject(2, "EEEEE", Types.VARCHAR);
+            }
+        	rs = ps.executeQuery();
+        	char[] c;
+        	if (testVariation == 1){
+            	//we are here to test short data 
+                c = new char[50];
+        	} else {
+            	//we are here to test large data 
+        		if (testCLOB)
+        			c = new char[50000];
+        		else
+                    c = new char[32000];
+        	}
+            Arrays.fill(c, 'a'); 
+        	for (int i=0;i<numberOfRowsToUpdate;i++) {
+            	rs.next();
+            	if (!compareClobReader2CharArray(c,rs.getCharacterStream(1))) {
+        			System.out.println("FAIL: " + 
+            	        (testCLOB ? "CLOB " : "VARCHAR ") + "data should have matched");
+        			rs.close();
+        			ps.close();
+        			return;
+            	}
+        	}
+        	rs.close();
+            ps.close();
+
+        }
+
+
 }
 
 

Modified: db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java?rev=1489123&r1=1489122&r2=1489123&view=diff
==============================================================================
--- db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java (original)
+++ db/derby/code/branches/10.5/java/testing/org/apache/derbyTesting/functionTests/util/streams/CharAlphabet.java Mon Jun  3 19:38:39 2013
@@ -92,6 +92,13 @@ public class CharAlphabet {
         return new CharAlphabet("Tamil", CharAlphabet.TAMIL);
     }
 
+    /**
+     * Get an alphabet consisting of a single character.
+     */
+    public static CharAlphabet singleChar(char ch) {
+        return new CharAlphabet("Single char: " + ch, new char[] { ch });
+    }
+
     /** Name of the alphabet. */
     private final String name;
     /** Characters in the alphabet. */