Author: rhillegas Date: Fri Sep 1 08:53:05 2006 New Revision: 439358 URL: http://svn.apache.org/viewvc?rev=439358&view=rev Log: DERBY-1725: Merge patches from trunk to 10.2 branch: No JIRA (436955), DERBY-883 (437070), DERBY-1555 (437009, 436965, 436957). Added: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubstituteExpressionVisitor.java - copied unchanged from r437071, db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubstituteExpressionVisitor.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/All.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/All.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/AllPackages.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/AllPackages.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/Client.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/Client.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/Embedded.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/Embedded.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GroupByExpressionTest.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GroupByExpressionTest.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/ChangeConfigurationSetup.java - copied unchanged from r437071, db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/ChangeConfigurationSetup.java Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/sql/compile/Visitor.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BaseColumnNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryListOperatorNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CastNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConditionalNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConstantNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentDatetimeOperatorNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentRowLocationNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/DefaultNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByColumn.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VerifyAggregateExpressionsVisitor.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VirtualColumnNode.java db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj db/derby/code/branches/10.2/java/engine/org/apache/derby/loc/messages_en.properties db/derby/code/branches/10.2/java/shared/org/apache/derby/shared/common/reference/SQLState.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/groupBy.out db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/build.xml db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/derbylang.runall db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURDataModelSetup.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/groupBy.sql db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/sql/compile/Visitor.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/sql/compile/Visitor.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/sql/compile/Visitor.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/sql/compile/Visitor.java Fri Sep 1 08:53:05 2006 @@ -91,5 +91,5 @@ * * @return true/false */ - boolean skipChildren(Visitable node); + boolean skipChildren(Visitable node) throws StandardException; } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BaseColumnNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BaseColumnNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BaseColumnNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BaseColumnNode.java Fri Sep 1 08:53:05 2006 @@ -171,4 +171,18 @@ { return Qualifier.SCAN_INVARIANT; } + + /** + * @inheritDoc + */ + protected boolean isEquivalent(ValueNode o) + { + if (isSameNodeType(o)) + { + BaseColumnNode other = (BaseColumnNode)o; + return other.tableName.equals(other.tableName) + && other.columnName.equals(columnName); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryListOperatorNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryListOperatorNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryListOperatorNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryListOperatorNode.java Fri Sep 1 08:53:05 2006 @@ -423,4 +423,36 @@ return returnNode; } + + /** + * @inheritDoc + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (!isSameNodeType(o)) + { + return false; + } + BinaryListOperatorNode other = (BinaryListOperatorNode)o; + if (!operator.equals(other.operator) + || !leftOperand.isEquivalent(other.getLeftOperand())) + { + return false; + } + + int sz = getRightOperandList().size(); + if (sz != other.rightOperandList.size()) + { + return false; + } + for (int i = 0; i < sz; i++) + { + ValueNode e = (ValueNode)rightOperandList.elementAt(i); + if (!e.isEquivalent((ValueNode)other.rightOperandList.elementAt(i))) + { + return false; + } + } + return true; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java Fri Sep 1 08:53:05 2006 @@ -870,6 +870,21 @@ return returnNode; } + /** + * @inheritDoc + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (!isSameNodeType(o)) + { + return false; + } + BinaryOperatorNode other = (BinaryOperatorNode)o; + return methodName.equals(other.methodName) + && leftOperand.isEquivalent(other.leftOperand) + && rightOperand.isEquivalent(other.rightOperand); + } + /** * Push the fields necessary to generate an instance of * SqlXmlExecutor, which will then be used at execution Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CastNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CastNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CastNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CastNode.java Fri Sep 1 08:53:05 2006 @@ -1031,6 +1031,21 @@ { return forDataTypeFunction; } + + /** + * {@inheritDoc} + * @throws StandardException + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) + { + CastNode other = (CastNode)o; + return castTarget.equals(other.castTarget) + && castOperand.isEquivalent(other.castOperand); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CoalesceFunctionNode.java Fri Sep 1 08:53:05 2006 @@ -34,9 +34,12 @@ import org.apache.derby.iapi.services.compiler.LocalField; import org.apache.derby.iapi.services.compiler.MethodBuilder; +import org.apache.derby.iapi.sql.compile.Visitable; +import org.apache.derby.iapi.sql.compile.Visitor; import java.lang.reflect.Modifier; +import java.util.Iterator; import java.util.Vector; /** @@ -306,7 +309,8 @@ /* print the non-node subfields */ - public String toString() { + public String toString() + { if (SanityManager.DEBUG) { return super.toString()+functionName+"("+argumentsList+")\n"; @@ -316,7 +320,53 @@ return ""; } } - + + /** + * {@inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (!isSameNodeType(o)) + { + return false; + } + + CoalesceFunctionNode other = (CoalesceFunctionNode)o; + if (other.argumentsList.size() != argumentsList.size()) + { + return false; + + } + + int size = argumentsList.size(); + for (int index = 0; index < size; index++) + { + ValueNode v1 = (ValueNode)argumentsList.elementAt(index); + ValueNode v2 = (ValueNode)other.argumentsList.elementAt(index); + if (!v1.isEquivalent(v2)) + { + return false; + } + } + return true; + } + public Visitable accept(Visitor v) throws StandardException + { + Visitable returnNode = v.visit(this); + + if (v.skipChildren(this) || v.stopTraversal()) + { + return returnNode; + } + + int size = argumentsList.size(); + for (int index = 0; index < size; index++) + { + argumentsList.setElementAt( + (QueryTreeNode)(argumentsList.elementAt(index)).accept(v), index); + } + return returnNode; + } /** * Preprocess an expression tree. We do a number of transformations * here (including subqueries, IN lists, LIKE and BETWEEN) plus Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java Fri Sep 1 08:53:05 2006 @@ -1120,6 +1120,16 @@ colNum[0] = -1; return null; } + + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (!isSameNodeType(o)) { + return false; + } + ColumnReference other = (ColumnReference)o; + return (tableNumber == other.tableNumber + && columnName.equals(other.getColumnName())); + } /** * Mark this column reference as "scoped", which means that it Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConditionalNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConditionalNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConditionalNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConditionalNode.java Fri Sep 1 08:53:05 2006 @@ -488,4 +488,32 @@ return returnNode; } + + /** + * @{inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) + { + ConditionalNode other = (ConditionalNode)o; + if (thenElseList.size() == other.thenElseList.size() + && (testCondition.isEquivalent(other.testCondition))) + { + int sz = thenElseList.size(); + for (int i = 0; i < sz; i++) + { + ValueNode v1 = (ValueNode)thenElseList.elementAt(i); + ValueNode v2 = (ValueNode)other.thenElseList.elementAt(i); + if (!v1.isEquivalent(v2)) + { + return false; + } + + } + return true; + } + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConstantNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConstantNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConstantNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ConstantNode.java Fri Sep 1 08:53:05 2006 @@ -277,4 +277,13 @@ // Constants are constant for the life of the query return Qualifier.CONSTANT; } + + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) { + ConstantNode other = (ConstantNode)o; + return other.getValue().compare(getValue()) == 0; + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentDatetimeOperatorNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentDatetimeOperatorNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentDatetimeOperatorNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentDatetimeOperatorNode.java Fri Sep 1 08:53:05 2006 @@ -180,4 +180,17 @@ return ""; } } + + /** + * {@inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) + { + if (isSameNodeType(o)) + { + CurrentDatetimeOperatorNode other = (CurrentDatetimeOperatorNode)o; + return other.whichType == whichType; + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentRowLocationNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentRowLocationNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentRowLocationNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/CurrentRowLocationNode.java Fri Sep 1 08:53:05 2006 @@ -162,4 +162,9 @@ mbex.pushThis(); mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), ClassName.DataValueDescriptor, 0); } + + protected boolean isEquivalent(ValueNode o) + { + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/DefaultNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/DefaultNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/DefaultNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/DefaultNode.java Fri Sep 1 08:53:05 2006 @@ -276,4 +276,12 @@ "generateExpression not expected to be called"); } } + + /** + * @inheritDoc + */ + protected boolean isEquivalent(ValueNode other) + { + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByColumn.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByColumn.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByColumn.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByColumn.java Fri Sep 1 08:53:05 2006 @@ -40,8 +40,8 @@ */ public class GroupByColumn extends OrderedColumn { - private ColumnReference colRef; - + private ValueNode columnExpression; + /** * Initializer. * @@ -49,7 +49,7 @@ */ public void init(Object colRef) { - this.colRef = (ColumnReference) colRef; + this.columnExpression = (ValueNode)colRef; } /** @@ -62,7 +62,7 @@ { if (SanityManager.DEBUG) { - return "Column Reference: "+colRef+super.toString(); + return "Column Expression: "+columnExpression+super.toString(); } else { @@ -83,10 +83,10 @@ { super.printSubNodes(depth); - if (colRef != null) + if (columnExpression != null) { printLabel(depth, "colRef: "); - colRef.treePrint(depth + 1); + columnExpression.treePrint(depth + 1); } } } @@ -98,49 +98,7 @@ */ public String getColumnName() { - return colRef.getColumnName(); - } - - /** - * Get the ColumnReference from this GroupByColumn. - * - * @return ColumnReference The ColumnReference from this node. - */ - public ColumnReference getColumnReference() - { - return colRef; - } - - /** - * Set the ColumnReference for this GroupByColumn. - * - * @param colRef The new ColumnReference for this node. - */ - public void setColumnReference(ColumnReference colRef) - { - this.colRef = colRef; - } - - /** - * Get the table number for this GroupByColumn. - * - * @return int The table number for this GroupByColumn - */ - - public int getTableNumber() - { - return colRef.getTableNumber(); - } - - /** - * Get the source this GroupByColumn - * - * @return The source of this GroupByColumn - */ - - public ResultColumn getSource() - { - return colRef.getSource(); + return columnExpression.getColumnName(); } /** @@ -162,12 +120,16 @@ throws StandardException { /* Bind the ColumnReference to the FromList */ - colRef = (ColumnReference) colRef.bindExpression(fromList, + columnExpression = (ValueNode) columnExpression.bindExpression(fromList, subqueryList, aggregateVector); // Verify that we can group on the column - + if (columnExpression.isParameterNode()) + { + throw StandardException.newException(SQLState.LANG_INVALID_COL_REF_GROUPED_SELECT_LIST, + columnExpression); + } /* * Do not check to see if we can map user types * to built-in types. The ability to do so does @@ -175,11 +137,22 @@ * as of version 2.0, ordering does not work on * user types. */ - TypeId ctid = colRef.getTypeId(); + TypeId ctid = columnExpression.getTypeId(); if (! ctid.orderable(getClassFactory())) { throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, ctid.getSQLTypeName()); } + } + + public ValueNode getColumnExpression() + { + return columnExpression; + } + + public void setColumnExpression(ValueNode cexpr) + { + this.columnExpression = cexpr; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java Fri Sep 1 08:53:05 2006 @@ -142,37 +142,26 @@ dummySubqueryList, aggregateVector); } - /* Verify that the columns in the GROUP BY list are unique. - * (Unique on table number and source ResultColumn.) - */ - verifyUniqueGroupingColumns(); - + + int rclSize = selectRCL.size(); for (int index = 0; index < size; index++) { boolean matchFound = false; GroupByColumn groupingCol = (GroupByColumn) elementAt(index); - String curName = groupingCol.getColumnName(); /* Verify that this entry in the GROUP BY list matches a * grouping column in the select list. */ - int groupingColTableNum = groupingCol.getTableNumber(); - ResultColumn groupingSource = groupingCol.getSource(); - int rclSize = selectRCL.size(); for (int inner = 0; inner < rclSize; inner++) { - ColumnReference selectListCR; ResultColumn selectListRC = (ResultColumn) selectRCL.elementAt(inner); - - if (! (selectListRC.getExpression() instanceof ColumnReference)) - { + if (!(selectListRC.getExpression() instanceof ColumnReference)) { continue; } - selectListCR = (ColumnReference) selectListRC.getExpression(); + + ColumnReference selectListCR = (ColumnReference) selectListRC.getExpression(); - if (groupingColTableNum == selectListCR.getTableNumber() && - groupingSource == selectListCR.getSource()) - { + if (selectListCR.isEquivalent(groupingCol.getColumnExpression())) { /* Column positions for grouping columns are 0-based */ groupingCol.setColumnPosition(inner + 1); @@ -182,19 +171,21 @@ break; } } - /* If no match found in the SELECT list, then add a matching * ResultColumn/ColumnReference pair to the SelectNode's RCL. */ - if (! matchFound) + if (! matchFound && + groupingCol.getColumnExpression() instanceof ColumnReference) { + // only add matching columns for column references not + // expressions yet. See DERBY-883 for details. ResultColumn newRC; /* Get a new ResultColumn */ newRC = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, groupingCol.getColumnName(), - groupingCol.getColumnReference().getClone(), + groupingCol.getColumnExpression().getClone(), getContextManager()); newRC.setVirtualColumnId(selectRCL.size() + 1); newRC.markGenerated(); @@ -231,125 +222,33 @@ numGroupingColsAdded+= numColsAddedHere; } + /** - * Check the uniqueness of the column names within a GROUP BY list. - * - * @exception StandardException Thrown on error + * Find the matching grouping column if any for the given expression + * + * @param node an expression for which we are trying to find a match + * in the group by list. + * + * @return the matching GroupByColumn if one exists, null otherwise. + * + * @throws StandardException */ - public void verifyUniqueGroupingColumns() throws StandardException + public GroupByColumn findGroupingColumn(ValueNode node) + throws StandardException { - int size = size(); - String colName; - - for (int outer = 0; outer < size; outer++) + int sz = size(); + for (int i = 0; i < sz; i++) { - GroupByColumn groupingCol = (GroupByColumn) elementAt(outer); - int outerTabNum = groupingCol.getTableNumber(); - ResultColumn outerRC = groupingCol.getSource(); - String curName = groupingCol.getColumnName(); - /* Verify that this column's name is unique within the list */ - colName = groupingCol.getColumnName(); - - for (int inner = outer + 1; inner < size; inner++) + GroupByColumn gbc = (GroupByColumn)elementAt(i); + if (gbc.getColumnExpression().isEquivalent(node)) { - GroupByColumn innerGBC = (GroupByColumn) elementAt(inner); - int innerTabNum = innerGBC.getTableNumber(); - ResultColumn innerRC = innerGBC.getSource(); - if (outerTabNum == innerTabNum && - outerRC == innerRC) - { - throw StandardException.newException(SQLState.LANG_AMBIGUOUS_GROUPING_COLUMN, colName); - } + return gbc; } } - - /* No duplicate column names */ - } - - /** - * Add any grouping columns which are not already in the appropriate RCL - * to the RCL. - * NOTE: The RC/VCNs in the SELECT list will point to the same pool of - * ResultColumns as the GroupByColumns in this list. - * - * @param selectNode The SelectNode whose RCL we add to. - * - * @exception StandardException Thrown on error - */ - public void addNewGroupingColumnsToRCL(SelectNode selectNode) - throws StandardException - { - FromList fromList = selectNode.getFromList(); - int size = size(); - ResultColumnList rcl = selectNode.getResultColumns(); - - if (SanityManager.DEBUG) - { - SanityManager.ASSERT(selectNode.getGroupByList() == this, - "selectNode.getGroupByList() expected to equal this"); - } - - for (int index = 0; index < size; index++) - { - GroupByColumn gbc = (GroupByColumn) elementAt(index); - ResultColumn newRC; - VirtualColumnNode newVCN; - - /* Skip over GBCs which have a match */ - if (gbc.getColumnPosition() != GroupByColumn.UNMATCHEDPOSITION) - { - continue; - } - - /* Get and bind a new VCN */ - newVCN = (VirtualColumnNode) getNodeFactory().getNode( - C_NodeTypes.VIRTUAL_COLUMN_NODE, - fromList.getFromTableByResultColumn(gbc.getSource()), - gbc.getSource(), - ReuseFactory.getInteger(rcl.size() + 2), - getContextManager()); - newVCN.setType(gbc.getColumnReference().getTypeServices()); - - /* Get and bind a new ResultColumn */ - newRC = (ResultColumn) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN, - gbc.getColumnName(), - newVCN, - getContextManager()); - newRC.setType(newVCN.getTypeServices()); - newRC.setVirtualColumnId(rcl.size() + 2); - - /* Add the new RC/VCN to the RCL */ - rcl.addElement(newRC); - - /* Set the columnPosition in the GroupByColumn, now that it - * has a matching entry in the SELECT list. - */ - gbc.setColumnPosition(rcl.size()); - } - } - - /** - * - */ - public GroupByColumn containsColumnReference(ColumnReference cr) - { - int size = size(); - for (int index = 0; index < size; index++) - { - GroupByColumn groupingCol = (GroupByColumn) elementAt(index); - - if (groupingCol.getSource() == cr.getSource() && - groupingCol.getTableNumber() == cr.getTableNumber()) - { - return groupingCol; - } - } - return null; } - + /** * Remap all ColumnReferences in this tree to be clones of the * underlying expression. @@ -371,7 +270,7 @@ ValueNode retVN; gbc = (GroupByColumn) elementAt(index); - retVN = gbc.getColumnReference().remapColumnReferencesToExpressions(); + retVN = gbc.getColumnExpression().remapColumnReferencesToExpressions(); if (SanityManager.DEBUG) { @@ -380,7 +279,7 @@ retVN.getClass().getName()); } - gbc.setColumnReference((ColumnReference) retVN); + gbc.setColumnExpression(retVN); } } @@ -405,5 +304,18 @@ { return ""; } + } + + public void preprocess( + int numTables, FromList fromList, SubqueryList whereSubquerys, + PredicateList wherePredicates) throws StandardException + { + for (int index = 0; index < size(); index++) + { + GroupByColumn groupingCol = (GroupByColumn) elementAt(index); + groupingCol.setColumnExpression( + groupingCol.getColumnExpression().preprocess( + numTables, fromList, whereSubquerys, wherePredicates)); + } } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/GroupByNode.java Fri Sep 1 08:53:05 2006 @@ -202,14 +202,25 @@ // Now populate the CR array and see if ordered int glSize = this.groupingList.size(); - for (int index = 0; index < glSize; index++) + int index; + for (index = 0; index < glSize; index++) { GroupByColumn gc = (GroupByColumn) this.groupingList.elementAt(index); - crs[index] = gc.getColumnReference(); + if (gc.getColumnExpression() instanceof ColumnReference) + { + crs[index] = (ColumnReference)gc.getColumnExpression(); + } + else + { + isInSortedOrder = false; + break; + } + + } + if (index == glSize) { + isInSortedOrder = childResult.isOrderedOn(crs, true, (Vector)null); } - - isInSortedOrder = childResult.isOrderedOn(crs, true, (Vector)null); } } @@ -314,6 +325,70 @@ } + /** + * In the query rewrite for group by, add the columns on which + * we are doing the group by. + + * @see #addNewColumnsForAggregation + */ + private void addUnAggColumns() throws StandardException + { + ResultColumnList bottomRCL = childResult.getResultColumns(); + ResultColumnList groupByRCL = resultColumns; + + int sz = groupingList.size(); + for (int i = 0; i < sz; i++) + { + GroupByColumn gbc = (GroupByColumn) groupingList.elementAt(i); + ResultColumn newRC = (ResultColumn) getNodeFactory().getNode( + C_NodeTypes.RESULT_COLUMN, + "##UnaggColumn", + gbc.getColumnExpression(), + getContextManager()); + + // add this result column to the bottom rcl + bottomRCL.addElement(newRC); + newRC.markGenerated(); + newRC.bindResultColumnToExpression(); + newRC.setVirtualColumnId(bottomRCL.size()); + + // now add this column to the groupbylist + ResultColumn gbRC = (ResultColumn) getNodeFactory().getNode( + C_NodeTypes.RESULT_COLUMN, + "##UnaggColumn", + gbc.getColumnExpression(), + getContextManager()); + groupByRCL.addElement(gbRC); + gbRC.markGenerated(); + gbRC.bindResultColumnToExpression(); + gbRC.setVirtualColumnId(groupByRCL.size()); + + /* + ** Reset the original node to point to the + ** Group By result set. + */ + VirtualColumnNode vc = (VirtualColumnNode) getNodeFactory().getNode( + C_NodeTypes.VIRTUAL_COLUMN_NODE, + this, // source result set. + gbRC, + new Integer(groupByRCL.size()), + getContextManager()); + + // we replace each group by expression + // in the projection list with a virtual column node + // that effectively points to a result column + // in the result set doing the group by + SubstituteExpressionVisitor se = + new SubstituteExpressionVisitor( + gbc.getColumnExpression(), + vc, + AggregateNode.class); + parent.getResultColumns().accept(se); + + // finally reset gbc to its new position. + gbc.setColumnPosition(bottomRCL.size()); + } + } /** * Add a whole slew of columns needed for @@ -357,19 +432,26 @@ private void addNewColumnsForAggregation() throws StandardException { - /* - ** Now we have two new nodes, the sort and a new PR above - ** it. They all map to the child result set. Now we must - ** find every aggregate and massage the tree. For now we - ** will examine every result column of the original select - ** list. - */ - DataDictionary dd; + aggInfo = new AggregatorInfoList(); + if (groupingList != null) + { + addUnAggColumns(); + } + addAggregateColumns(); + } + + /** + * In the query rewrite involving aggregates, add the columns for + * aggregation. + * + * @see #addNewColumnsForAggregation + */ + private void addAggregateColumns() throws StandardException + { + DataDictionary dd = getDataDictionary(); AggregateNode aggregate = null; ColumnReference newColumnRef; - ResultColumn rcBottom; ResultColumn newRC; - ResultColumn gbRC; ResultColumn tmpRC; ResultColumn aggInputRC; ResultColumnList bottomRCL = childResult.getResultColumns(); @@ -378,84 +460,21 @@ int aggregatorVColId; int aggInputVColId; int aggResultVColId; - - LanguageFactory lf = getLanguageConnectionContext().getLanguageFactory(); - dd = getDataDictionary(); - aggInfo = new AggregatorInfoList(); - - /* - ** Get a list of all column references in the - ** parent RCL, skipping (not going below) AggregateNodes - */ - CollectNodesVisitor getUnaggVisitor = new CollectNodesVisitor(ColumnReference.class, AggregateNode.class); - parent.getResultColumns().accept(getUnaggVisitor); - Vector colRefVector = getUnaggVisitor.getList(); - - /* - ** Walk the list of unaggregated column references - ** and push them down. - */ - int crvSize = colRefVector.size(); - for (int index = 0; index < crvSize; index++) - { - ColumnReference origColumnRef = (ColumnReference) colRefVector.elementAt(index); - newColumnRef = (ColumnReference)origColumnRef.getClone(); - - /* - ** Put the column reference in the bottom PR. - */ - newRC = (ResultColumn) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN, - "##UnaggColumn", - newColumnRef, - getContextManager()); - newRC.setExpression(newColumnRef); - bottomRCL.addElement(newRC); - newRC.markGenerated(); - newRC.bindResultColumnToExpression(); - newRC.setVirtualColumnId(bottomRCL.size()); - - /* - ** Reset the group by column position - */ - if (groupingList != null) - { - GroupByColumn gbColumn; - if ((gbColumn = - groupingList.containsColumnReference(newColumnRef)) - != null) - { - gbColumn.setColumnPosition(bottomRCL.size()); - } - } - /* - ** Add the column to the group by list - */ - gbRC = getColumnReference(newRC, dd); - groupByRCL.addElement(gbRC); - gbRC.markGenerated(); - gbRC.bindResultColumnToExpression(); - gbRC.setVirtualColumnId(groupByRCL.size()); - - /* - ** Reset the original node to point to the - ** Group By result set. - */ - origColumnRef.setSource(gbRC); - } /* - ** Now process all of the aggregates. Replace - ** every aggregate with an RC. We toss out - ** the list of RCs, we need to get each RC - ** as we process its corresponding aggregate. - */ + ** Now process all of the aggregates. Replace + ** every aggregate with an RC. We toss out + ** the list of RCs, we need to get each RC + ** as we process its corresponding aggregate. + */ + LanguageFactory lf = getLanguageConnectionContext().getLanguageFactory(); + ReplaceAggregatesWithCRVisitor replaceAggsVisitor = new ReplaceAggregatesWithCRVisitor( (ResultColumnList) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN_LIST, - getContextManager()), - ((FromTable) childResult).getTableNumber()); + C_NodeTypes.RESULT_COLUMN_LIST, + getContextManager()), + ((FromTable) childResult).getTableNumber()); parent.getResultColumns().accept(replaceAggsVisitor); /* @@ -471,10 +490,10 @@ ** bottom project restrict. */ newRC = (ResultColumn) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN, - "##aggregate result", - aggregate.getNewNullResultExpression(), - getContextManager()); + C_NodeTypes.RESULT_COLUMN, + "##aggregate result", + aggregate.getNewNullResultExpression(), + getContextManager()); newRC.markGenerated(); newRC.bindResultColumnToExpression(); bottomRCL.addElement(newRC); @@ -488,19 +507,19 @@ ** ReplaceAggregatesWithColumnReferencesVisitor() */ newColumnRef = (ColumnReference) getNodeFactory().getNode( - C_NodeTypes.COLUMN_REFERENCE, - newRC.getName(), - null, - getContextManager()); + C_NodeTypes.COLUMN_REFERENCE, + newRC.getName(), + null, + getContextManager()); newColumnRef.setSource(newRC); newColumnRef.setType(newRC.getExpressionType()); newColumnRef.setNestingLevel(this.getLevel()); newColumnRef.setSourceLevel(this.getLevel()); tmpRC = (ResultColumn) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN, - newRC.getColumnName(), - newColumnRef, - getContextManager()); + C_NodeTypes.RESULT_COLUMN, + newRC.getColumnName(), + newColumnRef, + getContextManager()); tmpRC.markGenerated(); tmpRC.bindResultColumnToExpression(); groupByRCL.addElement(tmpRC); @@ -559,8 +578,8 @@ ** to this agg if it is a user agg. */ aggRCL = (ResultColumnList) getNodeFactory().getNode( - C_NodeTypes.RESULT_COLUMN_LIST, - getContextManager()); + C_NodeTypes.RESULT_COLUMN_LIST, + getContextManager()); aggRCL.addElement(aggInputRC); /* @@ -568,14 +587,14 @@ ** so we have to subtract 1. */ aggInfo.addElement(new AggregatorInfo( - aggregate.getAggregateName(), - aggregate.getAggregatorClassName(), - aggInputVColId - 1, // aggregate input column - aggResultVColId -1, // the aggregate result column - aggregatorVColId - 1, // the aggregator column - aggregate.isDistinct(), - lf.getResultDescription(aggRCL.makeResultDescriptors(), "SELECT") - )); + aggregate.getAggregateName(), + aggregate.getAggregatorClassName(), + aggInputVColId - 1, // aggregate input column + aggResultVColId -1, // the aggregate result column + aggregatorVColId - 1, // the aggregator column + aggregate.isDistinct(), + lf.getResultDescription(aggRCL.makeResultDescriptors(), "SELECT") + )); } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/JavaToSQLValueNode.java Fri Sep 1 08:53:05 2006 @@ -354,4 +354,13 @@ return returnNode; } + + /** + * {@inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) + { + // anything in the java domain is not equiavlent. + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java Fri Sep 1 08:53:05 2006 @@ -485,4 +485,12 @@ { return true; } + + /** + * @inheritDoc + */ + protected boolean isEquivalent(ValueNode o) + { + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java Fri Sep 1 08:53:05 2006 @@ -1433,8 +1433,9 @@ if (isAutoincrement()) newResultColumn.setAutoincrement(); - - return newResultColumn; + if (isGroupingColumn()) + newResultColumn.markAsGroupingColumn(); + return newResultColumn; } /** @@ -1592,6 +1593,12 @@ { autoincrement = true; } + + public boolean isGroupingColumn() + { + return isGroupingColumn; + } + /** * @exception StandardException Thrown on error */ @@ -1815,6 +1822,18 @@ // reference nor a FromBaseTable beneath it--for example, // if it is of type BaseColumnNode. return -1; + } + + public boolean isEquivalent(ValueNode o) throws StandardException + { + if (o.getNodeType() == getNodeType()) + { + ResultColumn other = (ResultColumn)o; + if (expression != null) { + return expression.isEquivalent(other.expression); + } + } + return false; } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java Fri Sep 1 08:53:05 2006 @@ -282,16 +282,6 @@ } /** - * Return the groupByList for this SelectNode. - * - * @return GroupByList The groupByList for this SelectNode. - */ - public GroupByList getGroupByList() - { - return groupByList; - } - - /** * Find colName in the result columns and return underlying columnReference. * Note that this function returns null if there are more than one FromTable * for this SelectNode and the columnReference needs to be directly under @@ -612,14 +602,14 @@ "Unexpected Aggregate vector generated by Group By clause"); } } - /* If ungrouped query with aggregates in SELECT list, verify * that all result columns are valid aggregate expressions - * no column references outside of an aggregate. * If grouped query with aggregates in SELECT list, verify that all - * result columns are either grouping columns or valid - * grouped aggregate expressions - the only column references allowed - * outside of an aggregage are columns in the group by list. + * result columns are either grouping expressions or valid + * grouped aggregate expressions - the only column references + * allowed outside of an aggregate are columns in expressions in + * the group by list. */ if (groupByList != null || selectAggregates.size() > 0) { @@ -627,7 +617,7 @@ VerifyAggregateExpressionsVisitor visitor = new VerifyAggregateExpressionsVisitor(groupByList); resultColumns.accept(visitor); - } + } /* ** RESOLVE: for now, only one distinct aggregate is supported @@ -966,6 +956,15 @@ wherePredicates); } + /* Preprocess the group by list too. We need to compare + * expressions in the group by list with the select list and we + * can't rewrite one and not the other. + */ + if (groupByList != null) + { + groupByList.preprocess(numTables, fromList, whereSubquerys, wherePredicates); + } + /* Pull apart the expression trees */ if (whereClause != null) { Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java Fri Sep 1 08:53:05 2006 @@ -222,4 +222,14 @@ return ""; } } + + protected boolean isEquivalent(ValueNode o) + { + if (isSameNodeType(o)) + { + SpecialFunctionNode other = (SpecialFunctionNode)o; + return methodName.equals(other.methodName); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java Fri Sep 1 08:53:05 2006 @@ -2292,4 +2292,12 @@ } setType(dts); } + + /** + * {@inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) + { + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java Fri Sep 1 08:53:05 2006 @@ -915,4 +915,17 @@ private DataTypeDescriptor getVarcharDescriptor() { return new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.VARCHAR), true); } + + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) + { + TernaryOperatorNode other = (TernaryOperatorNode)o; + return (other.methodName.equals(methodName) + && other.receiver.isEquivalent(receiver) + && other.leftOperand.isEquivalent(leftOperand) + && other.rightOperand.isEquivalent(rightOperand)); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java Fri Sep 1 08:53:05 2006 @@ -857,4 +857,22 @@ mb.push(((Boolean)additionalArgs[0]).booleanValue()); return 3; } + + /** + * @throws StandardException + * {@inheritDoc} + */ + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) + { + // the first condition in the || covers the case when + // both operands are null. + UnaryOperatorNode other = (UnaryOperatorNode)o; + return (operator.equals(other.operator) && + ((operand == other.operand)|| + ((operand != null) && operand.isEquivalent(other.operand)))); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java Fri Sep 1 08:53:05 2006 @@ -1329,5 +1329,35 @@ { return false; } + + /** + * Tests if this node is equivalent to the specified ValueNode. Two + * ValueNodes are considered equivalent if they will evaluate to the same + * value during query execution. + * + * @param other the node to compare this ValueNode against. + * @return true if the two nodes are equivalent, + * false otherwise. + * + * @throws StandardException + */ + protected abstract boolean isEquivalent(ValueNode other) + throws StandardException; + /** + * Tests if this node is of the same type as the specified node as + * reported by {@link QueryTreeNode#getNodeType()}. + * + * @param other the node to compare this value node against. + * + * @return true if the two nodes are of the same type. + */ + protected final boolean isSameNodeType(ValueNode other) + { + if (other != null) { + return other.getNodeType() == getNodeType(); + } + return false; + } + } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VerifyAggregateExpressionsVisitor.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VerifyAggregateExpressionsVisitor.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VerifyAggregateExpressionsVisitor.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VerifyAggregateExpressionsVisitor.java Fri Sep 1 08:53:05 2006 @@ -64,8 +64,8 @@ * * @return me * - * @exception StandardException on ColumnReferernce not - * in group by list, ValueNode or + * @exception StandardException on ColumnReference not + * in group by list, ValueNode or * JavaValueNode that isn't under an * aggregate */ @@ -81,11 +81,12 @@ throw StandardException.newException(SQLState.LANG_INVALID_COL_REF_NON_GROUPED_SELECT_LIST, cr.getSQLColumnName()); } - if (groupByList.containsColumnReference(cr) == null) + if (groupByList.findGroupingColumn(cr) == null) { - throw StandardException.newException(SQLState.LANG_INVALID_COL_REF_GROUPED_SELECT_LIST, cr.getSQLColumnName()); + throw StandardException.newException(SQLState.LANG_INVALID_GROUPED_SELECT_LIST); } } + /* ** Subqueries are only valid if they do not have ** correlations and are expression subqueries. RESOLVE: @@ -119,22 +120,34 @@ SQLState.LANG_INVALID_NON_GROUPED_SELECT_LIST : SQLState.LANG_INVALID_GROUPED_SELECT_LIST); } + } else if (node instanceof JavaToSQLValueNode) + { + // disallow any expression which involves native java computation. + // Not possible to consider java expressions for equivalence. + throw StandardException.newException( (groupByList == null) ? + SQLState.LANG_INVALID_NON_GROUPED_SELECT_LIST : + SQLState.LANG_INVALID_GROUPED_SELECT_LIST); } return node; } /** - * Don't visit children under an aggregate + * Don't visit children under an aggregate, subquery or any node which + * is equivalent to any of the group by expressions. * * @param node the node to process * * @return true/false + * @throws StandardException */ - public boolean skipChildren(Visitable node) + public boolean skipChildren(Visitable node) throws StandardException { - return (node instanceof AggregateNode) || - (node instanceof SubqueryNode); + return ((node instanceof AggregateNode) || + (node instanceof SubqueryNode) || + (node instanceof ValueNode && + groupByList != null + && groupByList.findGroupingColumn((ValueNode)node) != null)); } public boolean stopTraversal() Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VirtualColumnNode.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VirtualColumnNode.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VirtualColumnNode.java (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/VirtualColumnNode.java Fri Sep 1 08:53:05 2006 @@ -288,4 +288,13 @@ } return dtd; } // end of getTypeServices + + protected boolean isEquivalent(ValueNode o) throws StandardException + { + if (isSameNodeType(o)) { + VirtualColumnNode other = (VirtualColumnNode)o; + return sourceColumn.isEquivalent(other.sourceColumn); + } + return false; + } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Fri Sep 1 08:53:05 2006 @@ -9408,15 +9408,26 @@ void groupingColumnReference(GroupByList groupingCols) throws StandardException : { - ColumnReference colRef; + ValueNode columnExpression; } { - colRef = columnReference() + columnExpression = additiveExpression(null, 0, false) { + if (columnExpression.isParameterNode()) + { + throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, "?"); + } + if (columnExpression instanceof AggregateNode) + { + AggregateNode agNode = (AggregateNode)columnExpression; + throw StandardException.newException( + SQLState.LANG_AGGREGATE_IN_GROUPBY_LIST, + agNode.getAggregateName()); + } groupingCols.addGroupByColumn( (GroupByColumn) nodeFactory.getNode( C_NodeTypes.GROUP_BY_COLUMN, - colRef, + columnExpression, getContextManager())); } } Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/loc/messages_en.properties URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/loc/messages_en.properties?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/engine/org/apache/derby/loc/messages_en.properties (original) +++ db/derby/code/branches/10.2/java/engine/org/apache/derby/loc/messages_en.properties Fri Sep 1 08:53:05 2006 @@ -633,20 +633,20 @@ 42Z99=String or Hex literal cannot exceed 64K. 42Y16=No public static method ''{0}'' was found in class ''{1}''. The method might exist, but it is not public, or it is not static. 42846=Cannot convert types ''{0}'' to ''{1}''. -42Y19=''{0}'' appears multiple times in the GROUP BY list. Columns in the GROUP BY list must be unambiguous. +#42Y19=''{0}'' appears multiple times in the GROUP BY list. Columns in the GROUP BY list must be unambiguous. 42Y22=Aggregate {0} cannot operate on type {1}. 42Y23=Incorrect JDBC type info returned for column {0}. 42Y24=View ''{0}'' is not updatable. (Views are currently not updatable.) 42Y25=''{0}'' is a system table. Users are not allowed to modify the contents of this table. -#42Y26=Parameters are not allowed in the WHEN clause of a trigger. +42Y26=Aggregates are not allowed in the GROUP BY list. 42Y27=Parameters are not allowed in the trigger action. 42Y29=The SELECT list of a non-grouped query contains at least one invalid expression. When the SELECT list contains at least one aggregate then all entries must be valid aggregate expressions. -42Y30=The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. +42Y30=The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. 42Y32=Aggregator class ''{0}'' for aggregate ''{1}'' on type {2} does not implement com.ibm.db2j.aggregates.Aggregator. 42Y33=Aggregate {0} contains one or more aggregates. 42Y34=Column name ''{0}'' matches more than one result column in table ''{1}''. 42Y35=Column reference ''{0}'' is invalid. When the SELECT list contains at least one aggregate then all entries must be valid aggregate expressions. -42Y36=Column reference ''{0}'' is invalid. For a SELECT list with a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. +42Y36=Column reference ''{0}'' is invalid. For a SELECT list with a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. 42Y37=''{0}'' is a Java primitive and cannot be used with this operator. 42Y38=insertMode = replace is not permitted on an insert where the target table, ''{0}'', is referenced in the SELECT. # NOTE: The parameter to this message is a keyword used as a noun phrase. Modified: db/derby/code/branches/10.2/java/shared/org/apache/derby/shared/common/reference/SQLState.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original) +++ db/derby/code/branches/10.2/java/shared/org/apache/derby/shared/common/reference/SQLState.java Fri Sep 1 08:53:05 2006 @@ -858,17 +858,18 @@ String LANG_NO_METHOD_MATCHING_ALIAS = "42Y16"; // String LANG_DROP_SYSTEM_TABLE_ATTEMPTED = "42Y17"; -- replaced by 42X62 String LANG_INVALID_CAST = "42846"; - String LANG_AMBIGUOUS_GROUPING_COLUMN = "42Y19"; + // String LANG_AMBIGUOUS_GROUPING_COLUMN = "42Y19"; -- unused post 883. // String LANG_UNMATCHED_GROUPING_COLUMN = // "42Y20"; -- not used String LANG_USER_AGGREGATE_BAD_TYPE = "42Y22"; String LANG_BAD_J_D_B_C_TYPE_INFO = "42Y23"; String LANG_VIEW_NOT_UPDATEABLE = "42Y24"; String LANG_UPDATE_SYSTEM_TABLE_ATTEMPTED = "42Y25"; - // String LANG_NO_PARAMS_IN_TRIGGER_WHEN = "42Y26"; -- not used. + String LANG_AGGREGATE_IN_GROUPBY_LIST = "42Y26"; String LANG_NO_PARAMS_IN_TRIGGER_ACTION = "42Y27"; // String LANG_NO_TRIGGER_ON_SYSTEM_TABLE = "42Y28"; -- replaced by 42X62 String LANG_INVALID_NON_GROUPED_SELECT_LIST = "42Y29"; String LANG_INVALID_GROUPED_SELECT_LIST = "42Y30"; + String LANG_TOO_MANY_ELEMENTS = "54004"; String LANG_BAD_AGGREGATOR_CLASS2 = "42Y32"; String LANG_USER_AGGREGATE_CONTAINS_AGGREGATE = "42Y33"; Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/groupBy.out URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/groupBy.out?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/groupBy.out (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/groupBy.out Fri Sep 1 08:53:05 2006 @@ -5,24 +5,20 @@ 0 rows inserted/updated/deleted ij> insert into t2 values (1,1,1), (2,2,2); 2 rows inserted/updated/deleted -ij> -- group by position +ij> -- group by constant. should compile but fail because +-- it is not a valid grouping expression. select * from t1 group by 1; -ERROR 42X01: Syntax error: Encountered "1" at line 2, column 27. +ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. ij> -- column in group by list not in from list select a as d from t1 group by d; ERROR 42X04: Column 'D' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'D' is not a column in the target table. ij> -- column in group by list not in select list select a as b from t1 group by b; -ERROR 42Y36: Column reference 'A' is invalid. For a SELECT list with a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. +ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. ij> select a from t1 group by b; -ERROR 42Y36: Column reference 'A' is invalid. For a SELECT list with a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. +ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. ij> select a, char(b) from t1 group by a; -ERROR 42Y36: Column reference 'B' is invalid. For a SELECT list with a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. -ij> -- columns in group by list must be unique -select a, b from t1 group by a, a; -ERROR 42Y19: 'A' appears multiple times in the GROUP BY list. Columns in the GROUP BY list must be unambiguous. -ij> select a, b from t1 group by a, t1.a; -ERROR 42Y19: 'A' appears multiple times in the GROUP BY list. Columns in the GROUP BY list must be unambiguous. +ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. ij> -- cursor with group by is not updatable get cursor c1 as 'select a from t1 group by a for update'; ERROR 42Y90: FOR UPDATE is not permitted in this type of statement. @@ -31,7 +27,7 @@ ERROR 21000: Scalar subquery is only allowed to return a single row. ij> -- correlation on outer table select t2.a, (select b from t1 where t1.b = t2.b) from t1 t2 group by t2.a; -ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain grouping columns and valid aggregate expressions. +ERROR 42Y30: The SELECT list of a grouped query contains at least one invalid expression. If a SELECT list has a GROUP BY, the list may only contain valid grouping expressions and valid aggregate expressions. ij> -- having clause -- cannot contain column references which are not grouping columns select a from t1 group by a having c = 1; @@ -40,7 +36,7 @@ ERROR 42X04: Column 'B.O' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'B.O' is not a column in the target table. ij> -- ?s in group by select a from t1 group by ?; -ERROR 42X01: Syntax error: Encountered "?" at line 2, column 27. +ERROR 42X01: Syntax error: ?. ij> -- group by on long varchar type create table unmapped(c1 long varchar); 0 rows inserted/updated/deleted Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/build.xml URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/build.xml?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/build.xml (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/build.xml Fri Sep 1 08:53:05 2006 @@ -36,13 +36,34 @@ - + - + + + + + + + + + Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/derbylang.runall URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/derbylang.runall?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/derbylang.runall (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/derbylang.runall Fri Sep 1 08:53:05 2006 @@ -1,6 +1,7 @@ jdbcapi/metadata.java jdbcapi/metadataMultiConn.java jdbcapi/odbc_metadata.java +lang/GroupByExpressionTest.junit lang/AIjdbc.java lang/AggregateClassLoading.java lang/CharUTF8.java Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc40.runall Fri Sep 1 08:53:05 2006 @@ -9,20 +9,5 @@ # JUnit tests jdbc4/AutoloadBooting.junit jdbc4/AutoloadTest.junit -jdbc4/BlobTest.junit -jdbc4/CallableStatementTest.junit -jdbc4/ClobTest.junit -jdbc4/ClosedObjectTest.junit -jdbc4/ConnectionTest.junit -jdbc4/DataSourceTest.junit -jdbc4/JDBC40TranslationTest.junit -jdbc4/ParameterMetaDataWrapperTest.junit -jdbc4/PreparedStatementTest.junit -jdbc4/ResultSetMetaDataTest.junit -jdbc4/ResultSetTest.junit -jdbc4/RowIdNotImplementedTest.junit -jdbc4/StatementEventsTest.junit -jdbc4/StatementTest.junit -jdbc4/UnsupportedVetter.junit jdbc4/VerifySignatures.junit -jdbc4/XA40Test.junit +jdbc4/_Suite.junit Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/_Suite.java Fri Sep 1 08:53:05 2006 @@ -46,8 +46,10 @@ TestSuite suite = new TestSuite(); + // These really need to run standalone. //suite.addTestSuite(AutoloadBooting.class); //suite.addTestSuite(AutoloadTest.class); + suite.addTest(BlobTest.suite()); suite.addTest(CallableStatementTest.suite()); suite.addTest(ClobTest.suite()); @@ -62,9 +64,13 @@ suite.addTest(RowIdNotImplementedTest.suite()); suite.addTest(StatementEventsTest.suite()); suite.addTest(StatementTest.suite()); - suite.addTestSuite(UnsupportedVetter.class); - suite.addTest(VerifySignatures.suite()); + suite.addTestSuite(UnsupportedVetter.class); suite.addTest(XA40Test.suite()); + + // This test is a little strange in its suite + // method in that it accesses + // the database to determine the set of tests to run. + // suite.addTest(VerifySignatures.suite()); return suite; } Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURDataModelSetup.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURDataModelSetup.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURDataModelSetup.java (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SURDataModelSetup.java Fri Sep 1 08:53:05 2006 @@ -22,6 +22,7 @@ import org.apache.derbyTesting.junit.BaseJDBCTestCase; import org.apache.derbyTesting.junit.BaseJDBCTestSetup; import org.apache.derbyTesting.junit.BaseTestCase; +import org.apache.derbyTesting.junit.TestConfiguration; import java.sql.Connection; import java.sql.PreparedStatement; @@ -71,7 +72,7 @@ TABLE_EXISTS_SQL_STATE, e.getSQLState()); // The net framework does not give any valuable error code - if (TestUtil.isNetFramework()) { + if (!TestConfiguration.getCurrent().getJDBCClient().isEmbedded()) { assertEquals("'drop table t1' failed with unexpected error code", NET_ERROR, e.getErrorCode()); Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/groupBy.sql URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/groupBy.sql?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/groupBy.sql (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/groupBy.sql Fri Sep 1 08:53:05 2006 @@ -5,7 +5,8 @@ create table t2 (a int, b int, c int); insert into t2 values (1,1,1), (2,2,2); --- group by position +-- group by constant. should compile but fail because +-- it is not a valid grouping expression. select * from t1 group by 1; -- column in group by list not in from list @@ -15,10 +16,6 @@ select a as b from t1 group by b; select a from t1 group by b; select a, char(b) from t1 group by a; - --- columns in group by list must be unique -select a, b from t1 group by a, a; -select a, b from t1 group by a, t1.a; -- cursor with group by is not updatable get cursor c1 as 'select a from t1 group by a for update'; Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/BaseJDBCTestCase.java Fri Sep 1 08:53:05 2006 @@ -28,6 +28,8 @@ import java.io.UnsupportedEncodingException; import java.sql.*; +import junit.framework.AssertionFailedError; + import org.apache.derby.tools.ij; @@ -358,7 +360,6 @@ /** * Assert that SQLState is as expected. - * The expected SQLState is truncated to five characters if required. * * @param message message to print on failure. * @param expected the expected SQLState. @@ -372,22 +373,29 @@ assertNotNull("Exception cannot be null when asserting on SQLState", exception); - String state = exception.getSQLState(); - - if ( state != null ) - assertTrue("The exception's SQL state must be five characters long", - exception.getSQLState().length() == 5); - - if ( expected != null ) - assertTrue("The expected SQL state must be five characters long", - expected.length() == 5); - - assertEquals(message, expected, state); + try { + String state = exception.getSQLState(); + + if ( state != null ) + assertTrue("The exception's SQL state must be five characters long", + state.length() == 5); + + if ( expected != null ) + assertTrue("The expected SQL state must be five characters long", + expected.length() == 5); + + assertEquals(message, expected, state); + } catch (AssertionFailedError e) { + + // Save the SQLException + // e.initCause(exception); + + throw e; + } } /** * Assert that SQLState is as expected. - * The expected SQLState is truncated to five characters if required. * * @param expected the expected SQLState. * @param exception the exception to check the SQLState of. @@ -395,5 +403,23 @@ public static void assertSQLState(String expected, SQLException exception) { assertSQLState("Unexpected SQL state.", expected, exception); } + /** + * Assert that the query does not compile and throws + * a SQLException with the expected state. + * + * @param sqlstate expected sql state. + * @param query the query to compile. + */ + public void assertCompileError(String sqlState, String query) { + + try { + prepareStatement(query).close(); + fail("expected compile error: " + sqlState); + } catch (SQLException se) { + assertSQLState(sqlState, se); + } + } } // End class BaseJDBCTestCase + + Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java?rev=439358&r1=439357&r2=439358&view=diff ============================================================================== --- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java (original) +++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java Fri Sep 1 08:53:05 2006 @@ -20,6 +20,7 @@ package org.apache.derbyTesting.junit; import java.io.File; +import java.lang.reflect.Method; import java.security.*; import java.sql.Connection; import java.sql.DriverManager; @@ -67,12 +68,11 @@ * Set this Thread's current configuration for running tests. * @param config Configuration to set it to. */ - private static void setCurrent(TestConfiguration config) + static void setCurrent(TestConfiguration config) { CURRENT_CONFIG.set(config); } /** - * WORK IN PROGRESS * Return a decorator for the passed in tests that sets the * configuration for the client to be Derby's JDBC client * and to start the network server at setUp and shut it @@ -84,19 +84,67 @@ * The previous TestConfiguration is restored at tearDown. * @param tests * @return + * @throws Exception */ - public static Test derbyClientServerDecorator(Test tests) + public static Test derbyClientServerDecorator(Class suite) throws Exception { TestConfiguration config = TestConfiguration.getCurrent(); - // Already in the correct configuration, do nothing. - if (config.getJDBCClient().isDerbyNetClient()) - return tests; + TestConfiguration derbyClientConfig = + new TestConfiguration(config, JDBCClient.DERBYNETCLIENT, + DEFAULT_HOSTNAME, DEFAULT_PORT); + + TestConfiguration.setCurrent(derbyClientConfig); - TestConfiguration derbyClientConfig = null; - // new TestConfiguration(config, JDBCClient.DERBYNETCLIENT); + Test test = addSuiteByReflection(suite); - return null; + TestConfiguration.setCurrent(config); + + test = new NetworkServerTestSetup(test); + + return new ChangeConfigurationSetup(derbyClientConfig, test); + + } + private static Test addSuiteByReflection(Class clz) throws Exception + { + Method sm = clz.getMethod("suite", null); + + return (Test) sm.invoke(null, null); + } + + + /** + * Default embedded configuration + * + */ + private TestConfiguration() { + this.dbName = DEFAULT_DBNAME; + this.userName = DEFAULT_USER_NAME; + this.userPassword = DEFAULT_USER_PASSWORD; + this.hostName = null; + this.port = -1; + this.singleLegXA = false; + + this.jdbcClient = JDBCClient.EMBEDDED; + url = createJDBCUrlWithDatabaseName(dbName); + + } + + private TestConfiguration(TestConfiguration copy, JDBCClient client, + String hostName, int port) + { + this.dbName = copy.dbName; + this.userName = copy.userName; + this.userPassword = copy.userPassword; + + this.isVerbose = copy.isVerbose; + this.singleLegXA = copy.singleLegXA; + this.port = port; + + this.jdbcClient = client; + this.hostName = hostName; + + this.url = createJDBCUrlWithDatabaseName(dbName); } /** @@ -106,7 +154,7 @@ */ private TestConfiguration(Properties props) throws NumberFormatException { - systemStartupProperties = props; + dbName = props.getProperty(KEY_DBNAME, DEFAULT_DBNAME); userName = props.getProperty(KEY_USER_NAME, DEFAULT_USER_NAME); userPassword = props.getProperty(KEY_USER_PASSWORD, @@ -141,14 +189,6 @@ } /** - * Get the given system property as specified at startup. - */ - private String getSystemStartupProperty( String key ) - { - return systemStartupProperties.getProperty( key ); - } - - /** * Get the system properties in a privileged block. * * @return the system properties. @@ -390,7 +430,6 @@ /** * Immutable data members in test configuration */ - private final Properties systemStartupProperties; private final String dbName; private final String url; private final String userName;