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/11/22 01:50:54 UTC

svn commit: r597278 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java

Author: dag
Date: Wed Nov 21 16:50:51 2007
New Revision: 597278

URL: http://svn.apache.org/viewvc?rev=597278&view=rev
Log:
DERBY-2016 ArrayIndexOutOfBoundsException for COALESCE with aggregate functions

Patch DERBY-2016d.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java?rev=597278&r1=597277&r2=597278&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java Wed Nov 21 16:50:51 2007
@@ -105,7 +105,12 @@
 {
 	String	functionName; //Are we here because of COALESCE function or VALUE function
 	ValueNodeList	argumentsList; //this is the list of arguments to the function. We are interested in the first not-null argument
-	ValueNode firstNonParameterNode;//The generated method will generate code to call coalesce on this non-parameter argument
+
+	/**
+	 * The generated method will generate code to call coalesce on
+	 * this non-parameter argument.
+	 */
+	private int firstNonParameterNodeIdx = -1;
 
 	/**
 	 * Initializer for a CalesceFunctionNode
@@ -152,7 +157,7 @@
 		{
 			if (!(((ValueNode) argumentsList.elementAt(index)).requiresTypeFromContext()))
 			{
-				firstNonParameterNode = (ValueNode) argumentsList.elementAt(index);
+				firstNonParameterNodeIdx = index;
 				break;
 			}
 		}
@@ -279,7 +284,10 @@
 		**	Next, if we are dealing with result type that is variable length, then generate a call to setWidth.
 		*/
 
-		firstNonParameterNode.generateExpression(acb, mb); //coalesce will be called on this non-parameter argument
+		// coalesce will be called on this non-parameter argument
+		((ValueNode) argumentsList.elementAt(firstNonParameterNodeIdx)).
+			generateExpression(acb, mb);
+
 		mb.upCast(ClassName.DataValueDescriptor);
 
 		mb.getField(arrayField); // first arg to the coalesce function
@@ -411,7 +419,8 @@
 		if (SanityManager.DEBUG)
 		{
 			super.printSubNodes(depth);
-			printLabel(depth, "argumentsList: ");
+			printLabel(depth, "argumentsList: [firstNonParameterNodeIdx=" +
+					   firstNonParameterNodeIdx + "]" );
 			int argumentsListSize = argumentsList.size();
 			for (int i=0; i < argumentsListSize; i++) {
 			    ((ValueNode)argumentsList.elementAt(i)).treePrint(depth+1);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java?rev=597278&r1=597277&r2=597278&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CoalesceTest.java Wed Nov 21 16:50:51 2007
@@ -170,6 +170,7 @@
         "create table tD (c1 int, c2 char(254))",
         "create table tB (c1 char(254), c2 char(40), vc1 varchar(253), vc2 varchar(2000), lvc1 long varchar, lvc2 long varchar, clob1 CLOB(200), clob2 CLOB(33K))",
         "create table tC (cbd1 char(254) for bit data, cbd2 char(40) for bit data, vcbd1 varchar(253) for bit data, vcbd2 varchar(2000) for bit data, lvcbd1 long varchar for bit data, lvcbd2 long varchar for bit data, blob1 BLOB(200), blob2 BLOB(33K))",	
+        "create table tAggr (i int)"
     };
 
     /* Public constructor required for running test as standalone JUnit. */    
@@ -1131,7 +1132,43 @@
 
         dumpRS(s.executeQuery("select coalesce(blob1,blob2) from tC"), expectedValues[index++]);
         dumpRS(s.executeQuery("select value(blob1,blob2) from tC"), expectedValues[index++]);	
-    }    
+    }
+
+
+    public void testAggregateDerby2016() throws SQLException
+    {
+        String[] expectedValues = {
+            "COL1(datatype : INTEGER, precision : 10, scale : 0) 2 ",
+            "COL1(datatype : INTEGER, precision : 10, scale : 0) 55 ",
+            "COL1(datatype : INTEGER, precision : 10, scale : 0) 1 ",
+        };
+
+        int index = 0;
+
+        // let aggregate max return a non-null: should give 2
+        ps = prepareStatement("insert into tAggr values ?");
+        for (int i=0; i<3; i++) {
+            ps.setInt(1, i);
+            ps.executeUpdate();
+        }
+
+        dumpRS(s.executeQuery("select coalesce(max(i), 55) from tAggr"),
+               expectedValues[index++]);
+
+        s.executeUpdate("delete from tAggr");
+
+        // let aggregate max return a null
+        ps.setNull(1, Types.INTEGER);
+        ps.executeUpdate();
+
+        dumpRS(s.executeQuery("select coalesce(max(i), 55) from tAggr"),
+               expectedValues[index++]);
+
+        // two aggregates
+        dumpRS(s.executeQuery(
+                   "select coalesce(max(i), count(*), 55) from tAggr"),
+               expectedValues[index++]);
+    }
 
 
     /**************supporting methods *******************/