Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / GroupByList.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/GroupByList.java
new file mode 100644 (file)
index 0000000..f473e5d
--- /dev/null
@@ -0,0 +1,338 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.GroupByList\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package        org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.reference.Limits;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A GroupByList represents the list of expressions in a GROUP BY clause in\r
+ * a SELECT statement.\r
+ *\r
+ */\r
+\r
+public class GroupByList extends OrderedColumnList\r
+{\r
+       int             numGroupingColsAdded = 0;\r
+\r
+       /**\r
+               Add a column to the list\r
+\r
+               @param column   The column to add to the list\r
+        */\r
+       public void addGroupByColumn(GroupByColumn column)\r
+       {\r
+               addElement(column);\r
+       }\r
+\r
+       /**\r
+               Get a column from the list\r
+\r
+               @param position The column to get from the list\r
+        */\r
+       public GroupByColumn getGroupByColumn(int position)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(position >=0 && position < size(),\r
+                                       "position (" + position +\r
+                                       ") expected to be between 0 and " + size());\r
+               }\r
+               return (GroupByColumn) elementAt(position);\r
+       }\r
+\r
+       /**\r
+               Print the list.\r
+\r
+               @param depth            The depth at which to indent the sub-nodes\r
+        */\r
+       public void printSubNodes(int depth)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       for (int index = 0; index < size(); index++)\r
+                       {\r
+                               ( (GroupByColumn) elementAt(index) ).treePrint(depth);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Get the number of grouping columns that need to be added to the SELECT list.\r
+        *\r
+        * @return int  The number of grouping columns that need to be added to\r
+        *                              the SELECT list.\r
+        */\r
+       public int getNumNeedToAddGroupingCols()\r
+       {\r
+               return numGroupingColsAdded;\r
+       }\r
+\r
+       /**\r
+        *  Bind the group by list.  Verify:\r
+        *              o  Number of grouping columns matches number of non-aggregates in\r
+        *                 SELECT's RCL.\r
+        *              o  Names in the group by list are unique\r
+        *              o  Names of grouping columns match names of non-aggregate\r
+        *                 expressions in SELECT's RCL.\r
+        *\r
+        * @param select                The SelectNode\r
+        * @param aggregateVector       The aggregate vector being built as we find AggregateNodes\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void bindGroupByColumns(SelectNode select,\r
+                                                                  Vector       aggregateVector)\r
+                                       throws StandardException\r
+       {\r
+               FromList                 fromList = select.getFromList();\r
+               ResultColumnList selectRCL = select.getResultColumns();\r
+               SubqueryList     dummySubqueryList =\r
+                                                                       (SubqueryList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.SUBQUERY_LIST,\r
+                                                                                                       getContextManager());\r
+               int                              numColsAddedHere = 0;\r
+               int                              size = size();\r
+\r
+               /* Only 32677 columns allowed in GROUP BY clause */\r
+               if (size > Limits.DB2_MAX_ELEMENTS_IN_GROUP_BY)\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_TOO_MANY_ELEMENTS);\r
+               }\r
+\r
+               /* Bind the grouping column */\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       GroupByColumn groupByCol = (GroupByColumn) elementAt(index);\r
+                       groupByCol.bindExpression(fromList,\r
+                                                                         dummySubqueryList, aggregateVector);\r
+               }\r
+\r
+               \r
+               int                             rclSize = selectRCL.size();\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       boolean                         matchFound = false;\r
+                       GroupByColumn           groupingCol = (GroupByColumn) elementAt(index);\r
+\r
+                       /* Verify that this entry in the GROUP BY list matches a\r
+                        * grouping column in the select list.\r
+                        */\r
+                       for (int inner = 0; inner < rclSize; inner++)\r
+                       {\r
+                               ResultColumn selectListRC = (ResultColumn) selectRCL.elementAt(inner);\r
+                               if (!(selectListRC.getExpression() instanceof ColumnReference)) {\r
+                                       continue;\r
+                               }\r
+                               \r
+                               ColumnReference selectListCR = (ColumnReference) selectListRC.getExpression();\r
+\r
+                               if (selectListCR.isEquivalent(groupingCol.getColumnExpression())) { \r
+                                       /* Column positions for grouping columns are 0-based */\r
+                                       groupingCol.setColumnPosition(inner + 1);\r
+\r
+                                       /* Mark the RC in the SELECT list as a grouping column */\r
+                                       selectListRC.markAsGroupingColumn();\r
+                                       matchFound = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       /* If no match found in the SELECT list, then add a matching\r
+                        * ResultColumn/ColumnReference pair to the SelectNode's RCL.\r
+                        * However, don't add additional result columns if the query\r
+                        * specified DISTINCT, because distinct processing considers\r
+                        * the entire RCL and including extra columns could change the\r
+                        * results: e.g. select distinct a,b from t group by a,b,c\r
+                        * should not consider column c in distinct processing (DERBY-3613)\r
+                        */\r
+                       if (! matchFound && !select.hasDistinct() &&\r
+                           groupingCol.getColumnExpression() instanceof ColumnReference) \r
+                       {\r
+                               // only add matching columns for column references not \r
+                               // expressions yet. See DERBY-883 for details. \r
+                               ResultColumn newRC;\r
+\r
+                               /* Get a new ResultColumn */\r
+                               newRC = (ResultColumn) getNodeFactory().getNode(\r
+                                                               C_NodeTypes.RESULT_COLUMN,\r
+                                                               groupingCol.getColumnName(),\r
+                                                               groupingCol.getColumnExpression().getClone(),\r
+                                                               getContextManager());\r
+                               newRC.setVirtualColumnId(selectRCL.size() + 1);\r
+                               newRC.markGenerated();\r
+                               newRC.markAsGroupingColumn();\r
+\r
+                               /* Add the new RC/CR to the RCL */\r
+                               selectRCL.addElement(newRC);\r
+\r
+                               /* Set the columnPosition in the GroupByColumn, now that it\r
+                               * has a matching entry in the SELECT list.\r
+                               */\r
+                               groupingCol.setColumnPosition(selectRCL.size());\r
+                               \r
+                               // a new hidden or generated column is added to this RCL\r
+                               // i.e. that the size() of the RCL != visibleSize(). \r
+                               // Error checking done later should be aware of this \r
+                               // special case.\r
+                               selectRCL.setCountMismatchAllowed(true);\r
+\r
+                               /*\r
+                               ** Track the number of columns that we have added\r
+                               ** in this routine.  We track this separately\r
+                               ** than the total number of columns added by this\r
+                               ** object (numGroupingColsAdded) because we\r
+                               ** might be bound (though not gagged) more than\r
+                               ** once (in which case numGroupingColsAdded will\r
+                               ** already be set).\r
+                               */\r
+                               numColsAddedHere++;\r
+                       }\r
+                       if (groupingCol.getColumnExpression() instanceof JavaToSQLValueNode) \r
+                       {\r
+                               // disallow any expression which involves native java computation. \r
+                               // Not possible to consider java expressions for equivalence.\r
+                               throw StandardException.newException(                                   \r
+                                               SQLState.LANG_INVALID_GROUPED_SELECT_LIST);\r
+                       }\r
+               }\r
+\r
+               /* Verify that no subqueries got added to the dummy list */\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(dummySubqueryList.size() == 0,\r
+                               "dummySubqueryList.size() is expected to be 0");\r
+               }\r
+\r
+               numGroupingColsAdded+= numColsAddedHere;\r
+       }\r
+\r
+       \r
+\r
+       /**\r
+        * Find the matching grouping column if any for the given expression\r
+        * \r
+        * @param node an expression for which we are trying to find a match\r
+        * in the group by list.\r
+        * \r
+        * @return the matching GroupByColumn if one exists, null otherwise.\r
+        * \r
+        * @throws StandardException\r
+        */\r
+       public GroupByColumn findGroupingColumn(ValueNode node)\r
+               throws StandardException\r
+       {\r
+               int sz = size();\r
+               for (int i = 0; i < sz; i++) \r
+               {\r
+                       GroupByColumn gbc = (GroupByColumn)elementAt(i);\r
+                       if (gbc.getColumnExpression().isEquivalent(node))\r
+                       {\r
+                               return gbc;\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       /**\r
+        * Remap all ColumnReferences in this tree to be clones of the\r
+        * underlying expression.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public void remapColumnReferencesToExpressions() throws StandardException\r
+       {\r
+               GroupByColumn   gbc;\r
+               int                             size = size();\r
+\r
+               /* This method is called when flattening a FromTable.  We should\r
+                * not be flattening a FromTable if the underlying expression that\r
+                * will get returned out, after chopping out the redundant ResultColumns,\r
+                * is not a ColumnReference.  (See ASSERT below.)\r
+                */\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       ValueNode       retVN;\r
+                       gbc = (GroupByColumn) elementAt(index);\r
+\r
+                       retVN = gbc.getColumnExpression().remapColumnReferencesToExpressions();\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               SanityManager.ASSERT(retVN instanceof ColumnReference,\r
+                                       "retVN expected to be instanceof ColumnReference, not " +\r
+                                       retVN.getClass().getName());\r
+                       }\r
+\r
+                       gbc.setColumnExpression(retVN);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Print it out, baby\r
+        */\r
+       public String toString()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       StringBuffer    buf = new StringBuffer();\r
+\r
+                       for (int index = 0; index < size(); index++)\r
+                       {\r
+                               GroupByColumn   groupingCol = (GroupByColumn) elementAt(index);\r
+\r
+                               buf.append(groupingCol.toString());\r
+                       }\r
+                       return buf.toString();\r
+               }\r
+               else\r
+               {\r
+                       return "";\r
+               }\r
+       }\r
+\r
+       public void preprocess(\r
+                       int numTables, FromList fromList, SubqueryList whereSubquerys, \r
+                       PredicateList wherePredicates) throws StandardException \r
+       {\r
+               for (int index = 0; index < size(); index++)\r
+               {\r
+                       GroupByColumn   groupingCol = (GroupByColumn) elementAt(index);\r
+                       groupingCol.setColumnExpression(\r
+                                       groupingCol.getColumnExpression().preprocess(\r
+                                                       numTables, fromList, whereSubquerys, wherePredicates));\r
+               }               \r
+       }\r
+}\r