Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / ColumnReference.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java
new file mode 100644 (file)
index 0000000..9ae71dd
--- /dev/null
@@ -0,0 +1,1194 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.ColumnReference\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
+import org.apache.derby.iapi.sql.compile.NodeFactory;\r
+\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A ColumnReference represents a column in the query tree.  The parser generates a\r
+ * ColumnReference for each column reference.  A column refercence could be a column in\r
+ * a base table, a column in a view (which could expand into a complex\r
+ * expression), or a column in a subquery in the FROM clause.\r
+ *\r
+ */\r
+\r
+public class ColumnReference extends ValueNode\r
+{\r
+       String  columnName;\r
+\r
+       /*\r
+       ** This is the user-specified table name.  It will be null if the\r
+       ** user specifies a column without a table name.  Leave it null even\r
+       ** when the column is bound as it is only used in binding.\r
+       */\r
+       TableName       tableName;\r
+       /* The table this column reference is bound to */\r
+       private int                     tableNumber;    \r
+       /* The column number in the underlying base table */\r
+       private int                     columnNumber;   \r
+       /* This is where the value for this column reference will be coming from */\r
+       private ResultColumn    source;\r
+\r
+       /* For unRemapping */\r
+       ResultColumn    origSource;\r
+       private String  origName;\r
+       int                             origTableNumber = -1;\r
+       int                             origColumnNumber = -1;\r
+\r
+       /* Reuse generated code where possible */\r
+       //Expression genResult;\r
+\r
+       private boolean         replacesAggregate;\r
+\r
+       private int                     nestingLevel = -1;\r
+       private int                     sourceLevel = -1;\r
+\r
+       /* Whether or not this column reference been scoped for the\r
+          sake of predicate pushdown.\r
+        */\r
+       private boolean         scoped;\r
+\r
+       /* List of saved remap data if this ColumnReference is scoped\r
+          and has been remapped multiple times.\r
+        */\r
+       private java.util.ArrayList remaps;\r
+\r
+       /**\r
+        * Initializer.\r
+        * This one is called by the parser where we could\r
+        * be dealing with delimited identifiers.\r
+        *\r
+        * @param columnName    The name of the column being referenced\r
+        * @param tableName             The qualification for the column\r
+        * @param tokBeginOffset begin position of token for the column name \r
+        *                                      identifier from parser.\r
+        * @param tokEndOffset  end position of token for the column name \r
+        *                                      identifier from parser.\r
+        */\r
+\r
+       public void init(Object columnName, \r
+                                        Object tableName,\r
+                                        Object tokBeginOffset,\r
+                                        Object tokEndOffset\r
+                                        )\r
+       {\r
+               this.columnName = (String) columnName;\r
+               this.tableName = (TableName) tableName;\r
+               this.setBeginOffset(((Integer) tokBeginOffset).intValue());\r
+               this.setEndOffset(((Integer) tokEndOffset).intValue());\r
+               tableNumber = -1;\r
+               remaps = null;\r
+       }\r
+\r
+       /**\r
+        * Initializer.\r
+        *\r
+        * @param columnName    The name of the column being referenced\r
+        * @param tableName             The qualification for the column\r
+        */\r
+\r
+       public void init(Object columnName, Object tableName)\r
+       {\r
+               this.columnName = (String) columnName;\r
+               this.tableName = (TableName) tableName;\r
+               tableNumber = -1;\r
+               remaps = null;\r
+       }\r
+\r
+       /**\r
+        * Convert this object to a String.  See comments in QueryTreeNode.java\r
+        * for how this should be done for tree printing.\r
+        *\r
+        * @return      This object as a String\r
+        */\r
+\r
+       public String toString()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       return "columnName: " + columnName + "\n" +\r
+                               "tableNumber: " + tableNumber + "\n" +\r
+                               "columnNumber: " + columnNumber + "\n" +\r
+                               "replacesAggregate: " + replacesAggregate + "\n" +\r
+                               "tableName: " + ( ( tableName != null) ? tableName.toString() : "null") + "\n" +\r
+                               "nestingLevel: " + nestingLevel + "\n" +\r
+                               "sourceLevel: " + sourceLevel + "\n" +\r
+                               super.toString();\r
+               }\r
+               else\r
+               {\r
+                       return "";\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Prints the sub-nodes of this object.  See QueryTreeNode.java for\r
+        * how tree printing is supposed to work.\r
+        *\r
+        * @param depth         The depth of this node in the tree\r
+        */\r
+\r
+       public void printSubNodes(int depth)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       super.printSubNodes(depth);\r
+\r
+                       if (source != null)\r
+                       {\r
+                               printLabel(depth, "source: ");\r
+                               source.treePrint(depth + 1);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this CR is correlated.\r
+        *\r
+        * @return Whether or not this CR is correlated.\r
+        */\r
+       boolean getCorrelated()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(nestingLevel != -1,\r
+                               "nestingLevel on "+columnName+" is not expected to be -1");\r
+                       SanityManager.ASSERT(sourceLevel != -1,\r
+                               "sourceLevel on "+columnName+" is not expected to be -1");\r
+               }\r
+               return sourceLevel != nestingLevel;\r
+       }\r
+\r
+       /**\r
+        * Set the nesting level for this CR.  (The nesting level\r
+        * at which the CR appears.)\r
+        *\r
+        * @param nestingLevel  The Nesting level at which the CR appears.\r
+        */\r
+       void setNestingLevel(int nestingLevel)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(nestingLevel != -1,\r
+                               "nestingLevel is not expected to be -1");\r
+               }\r
+               this.nestingLevel = nestingLevel;\r
+       }\r
+\r
+       /**\r
+        * Get the nesting level for this CR.\r
+        *\r
+        * @return      The nesting level for this CR.\r
+        */\r
+       private int getNestingLevel()\r
+       {\r
+               return nestingLevel;\r
+       }\r
+\r
+       /**\r
+        * Set the source level for this CR.  (The nesting level\r
+        * of the source of the CR.)\r
+        *\r
+        * @param sourceLevel   The Nesting level of the source of the CR.\r
+        */\r
+       void setSourceLevel(int sourceLevel)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(sourceLevel != -1,\r
+                               "sourceLevel is not expected to be -1");\r
+               }\r
+               this.sourceLevel = sourceLevel;\r
+       }\r
+\r
+       /**\r
+        * Get the source level for this CR.\r
+        *\r
+        * @return      The source level for this CR.\r
+        */\r
+       int getSourceLevel()\r
+       {\r
+               return sourceLevel;\r
+       }\r
+\r
+       /**\r
+        * Mark this node as being generated to replace an aggregate.\r
+        * (Useful for replacing aggregates in the HAVING clause with \r
+        * column references to the matching aggregate in the \r
+        * user's SELECT.\r
+        */\r
+       public void markGeneratedToReplaceAggregate()\r
+       {\r
+               replacesAggregate = true;\r
+       }\r
+\r
+       /**\r
+        * Determine whether or not this node was generated to\r
+        * replace an aggregate in the user's SELECT.\r
+        *\r
+        * @return boolean      Whether or not this node was generated to replace\r
+        *                                      an aggregate in the user's SELECT.\r
+        */\r
+       public boolean getGeneratedToReplaceAggregate()\r
+       {\r
+               return replacesAggregate;\r
+       }\r
+\r
+       /**\r
+        * Return a clone of this node.\r
+        *\r
+        * @return ValueNode    A clone of this node.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public ValueNode getClone()\r
+               throws StandardException\r
+       {\r
+               ColumnReference newCR = (ColumnReference) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.COLUMN_REFERENCE,\r
+                                                                       columnName,\r
+                                                                       tableName,\r
+                                                                       getContextManager());\r
+\r
+               newCR.copyFields(this);\r
+               return newCR;\r
+       }\r
+\r
+       /**\r
+        * Copy all of the "appropriate fields" for a shallow copy.\r
+        *\r
+        * @param oldCR         The ColumnReference to copy from.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public void copyFields(ColumnReference oldCR)\r
+               throws StandardException\r
+       {\r
+               super.copyFields(oldCR);\r
+\r
+               tableName = oldCR.getTableNameNode();\r
+               tableNumber = oldCR.getTableNumber();\r
+               columnNumber = oldCR.getColumnNumber();\r
+               source = oldCR.getSource();\r
+               nestingLevel = oldCR.getNestingLevel();\r
+               sourceLevel = oldCR.getSourceLevel();\r
+               replacesAggregate = oldCR.getGeneratedToReplaceAggregate();\r
+               scoped = oldCR.isScoped();\r
+       }\r
+\r
+       /**\r
+        * Bind this expression.  This means binding the sub-expressions,\r
+        * as well as figuring out what the return type is for this expression.\r
+        *\r
+        * NOTE: We must explicitly check for a null FromList here, column reference\r
+        * without a FROM list, as the grammar allows the following:\r
+        *                      insert into t1 values(c1)\r
+        *\r
+        * @param fromList              The FROM list for the query this\r
+        *                              expression is in, for binding columns.\r
+        * @param subqueryList          The subquery list being built as we find SubqueryNodes\r
+        * @param aggregateVector       The aggregate vector being built as we find AggregateNodes\r
+        *\r
+        * @return      The new top of the expression tree.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,\r
+                       Vector aggregateVector) \r
+                               throws StandardException\r
+       {\r
+               ResultColumn matchingRC;\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(fromList != null, "fromList is expected to be non-null");\r
+               }\r
+\r
+               if (fromList.size() == 0)\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_ILLEGAL_COLUMN_REFERENCE, columnName);\r
+               }\r
+\r
+               matchingRC = fromList.bindColumnReference(this);\r
+\r
+               /* Error if no match found in fromList */\r
+               if (matchingRC == null)\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, getSQLColumnName());\r
+               }\r
+\r
+               /* Set the columnNumber from the base table.\r
+                * Useful for optimizer and generation.\r
+                */\r
+               columnNumber = matchingRC.getColumnPosition();\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Get the column name for purposes of error\r
+        * messages or debugging. This returns the column\r
+        * name as used in the SQL statement. Thus if it was qualified\r
+        * with a table, alias name that will be included.\r
+        *\r
+        * @return      The  column name in the form [[schema.]table.]column\r
+        */\r
+\r
+       public String getSQLColumnName()\r
+       {\r
+               if (tableName == null)\r
+                       return columnName;\r
+               \r
+               return tableName.toString() + "." + columnName;\r
+       }\r
+\r
+       /**\r
+        * Get the name of this column\r
+        *\r
+        * @return      The name of this column\r
+        */\r
+\r
+       public String getColumnName()\r
+       {\r
+               return columnName;\r
+       }\r
+\r
+       /**\r
+        * Set the name of this column\r
+        *\r
+        * @param columnName    The name of this column\r
+        */\r
+\r
+       public void setColumnName(String columnName)\r
+       {\r
+               this.columnName = columnName;\r
+       }\r
+\r
+       /**\r
+        * Get the table number for this ColumnReference.\r
+        *\r
+        * @return      int The table number for this ColumnReference\r
+        */\r
+\r
+       public int getTableNumber()\r
+       {\r
+               return tableNumber;\r
+       }\r
+\r
+       /**\r
+        * Set this ColumnReference to refer to the given table number.\r
+        *\r
+        * @param tableNumber   The table number this ColumnReference will refer to\r
+        */\r
+\r
+       public void setTableNumber(int tableNumber)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(tableNumber != -1,\r
+                               "tableNumber not expected to be -1");\r
+               }\r
+               this.tableNumber = tableNumber;\r
+       }\r
+\r
+       /**\r
+        * Get the user-supplied table name of this column.  This will be null\r
+        * if the user did not supply a name (for example, select a from t).\r
+        * The method will return B for this example, select b.a from t as b\r
+        * The method will return T for this example, select t.a from t\r
+        *\r
+        * @return      The user-supplied name of this column.  Null if no user-\r
+        *              supplied name.\r
+        */\r
+\r
+       public String getTableName()\r
+       {\r
+               return ( ( tableName != null) ? tableName.getTableName() : null );\r
+       }\r
+\r
+       /**\r
+        * Get the name of the underlying(base) table this column comes from, if any.\r
+        * Following example queries will all return T\r
+        * select a from t\r
+        * select b.a from t as b\r
+        * select t.a from t\r
+        *\r
+        * @return      The name of the base table that this column comes from.\r
+        *                      Null if not a ColumnReference.\r
+        */\r
+\r
+       public String getSourceTableName()\r
+       {\r
+               return ((source != null) ? source.getTableName() : null);\r
+       }\r
+\r
+       /**\r
+        * Get the name of the schema for the Column's base table, if any.\r
+        * Following example queries will all return APP (assuming user is in schema APP)\r
+        * select t.a from t\r
+        * select b.a from t as b\r
+        * select app.t.a from t\r
+        *\r
+        * @return      The name of the schema for Column's base table. If the column\r
+        *              is not in a schema (i.e. is a derived column), it returns NULL.\r
+        */\r
+       public String getSourceSchemaName() throws StandardException\r
+       {\r
+               return ((source != null) ? source.getSchemaName() : null);\r
+       }\r
+\r
+       /**\r
+        * Is the column wirtable by the cursor or not. (ie, is it in the list of FOR UPDATE columns list)\r
+        *\r
+        * @return TRUE, if the column is a base column of a table and is \r
+        * writable by cursor.\r
+        */\r
+       public boolean updatableByCursor()\r
+       {\r
+               return ((source != null) ? source.updatableByCursor() : false);\r
+       }\r
+\r
+       /**\r
+         Return the table name as the node it is.\r
+         @return the column's table name.\r
+        */\r
+       public TableName getTableNameNode()\r
+       {\r
+               return tableName;\r
+       }\r
+\r
+       public void setTableNameNode(TableName tableName)\r
+       {\r
+               this.tableName = tableName;\r
+       }\r
+\r
+       /**\r
+        * Get the column number for this ColumnReference.\r
+        *\r
+        * @return      int The column number for this ColumnReference\r
+        */\r
+\r
+       public int getColumnNumber()\r
+       {\r
+               return columnNumber;\r
+       }\r
+\r
+       /**\r
+        * Set the column number for this ColumnReference.  This is\r
+        * used when scoping predicates for pushdown.\r
+        *\r
+        * @param colNum The new column number.\r
+        */\r
+\r
+       public void setColumnNumber(int colNum)\r
+       {\r
+               this.columnNumber = colNum;\r
+       }\r
+\r
+       /**\r
+        * Get the source this columnReference\r
+        *\r
+        * @return      The source of this columnReference\r
+        */\r
+\r
+       public ResultColumn getSource()\r
+       {\r
+               return source;\r
+       }\r
+\r
+       /**\r
+        * Set the source this columnReference\r
+        *\r
+        * @param source        The source of this columnReference\r
+        */\r
+\r
+       public void setSource(ResultColumn source)\r
+       {\r
+               this.source = source;\r
+       }\r
+\r
+       /**\r
+        * Do the 1st step in putting an expression into conjunctive normal\r
+        * form.  This step ensures that the top level of the expression is\r
+        * a chain of AndNodes.\r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode putAndsOnTop() \r
+                                       throws StandardException\r
+       {\r
+               BinaryComparisonOperatorNode            equalsNode;\r
+               BooleanConstantNode     trueNode;\r
+               NodeFactory             nodeFactory = getNodeFactory();\r
+               ValueNode               andNode;\r
+\r
+        trueNode = (BooleanConstantNode) nodeFactory.getNode(\r
+                                                                               C_NodeTypes.BOOLEAN_CONSTANT_NODE,\r
+                                                                               Boolean.TRUE,\r
+                                                                               getContextManager());\r
+               equalsNode = (BinaryComparisonOperatorNode) \r
+                                               nodeFactory.getNode(\r
+                                                                               C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,\r
+                                                                               this,\r
+                                                                               trueNode,\r
+                                                                               getContextManager());\r
+               /* Set type info for the operator node */\r
+               equalsNode.bindComparisonOperator();\r
+               andNode = (ValueNode) nodeFactory.getNode(\r
+                                                                       C_NodeTypes.AND_NODE,\r
+                                                                       equalsNode,\r
+                                                                       trueNode,\r
+                                                                       getContextManager());\r
+               ((AndNode) andNode).postBindFixup();\r
+               return andNode;\r
+       }\r
+\r
+       /**\r
+        * Categorize this predicate.  Initially, this means\r
+        * building a bit map of the referenced tables for each predicate.\r
+        * If the source of this ColumnReference (at the next underlying level) \r
+        * is not a ColumnReference or a VirtualColumnNode then this predicate\r
+        * will not be pushed down.\r
+        *\r
+        * For example, in:\r
+        *              select * from (select 1 from s) a (x) where x = 1\r
+        * we will not push down x = 1.\r
+        * NOTE: It would be easy to handle the case of a constant, but if the\r
+        * inner SELECT returns an arbitrary expression, then we would have to copy\r
+        * that tree into the pushed predicate, and that tree could contain\r
+        * subqueries and method calls.\r
+        *\r
+        * Also, don't allow a predicate to be pushed down if it contains a\r
+        * ColumnReference that replaces an aggregate.  This can happen if\r
+        * the aggregate is in the HAVING clause.  In this case, we would be\r
+        * pushing the predicate into the SelectNode that evaluates the aggregate,\r
+        * which doesn't make sense, since the having clause is supposed to be\r
+        * applied to the result of the SelectNode.\r
+        *\r
+        * RESOLVE - revisit this issue once we have views.\r
+        *\r
+        * @param referencedTabs        JBitSet with bit map of referenced FromTables\r
+        * @param simplePredsOnly       Whether or not to consider method\r
+        *                                                      calls, field references and conditional nodes\r
+        *                                                      when building bit map\r
+        *\r
+        * @return boolean              Whether or not source.expression is a ColumnReference\r
+        *                                              or a VirtualColumnNode or a ConstantNode.\r
+        */\r
+       public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(tableNumber >= 0,\r
+                                                        "tableNumber is expected to be non-negative");\r
+               referencedTabs.set(tableNumber);\r
+\r
+               return ( ! replacesAggregate ) &&\r
+                          ( (source.getExpression() instanceof ColumnReference) ||\r
+                            (source.getExpression() instanceof VirtualColumnNode) ||\r
+                                (source.getExpression() instanceof ConstantNode));\r
+       }\r
+\r
+       /**\r
+        * Remap all of the ColumnReferences in this expression tree\r
+        * to point to the ResultColumn that is 1 level under their\r
+        * current source ResultColumn.\r
+        * This is useful for pushing down single table predicates.\r
+        *\r
+        * RESOLVE: Once we start pushing join clauses, we will need to walk the\r
+        * ResultColumn/VirtualColumnNode chain for them to remap the references.\r
+        */\r
+       public void remapColumnReferences()\r
+       {\r
+               ValueNode expression = source.getExpression();\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       // SanityManager.ASSERT(origSource == null,\r
+                       //              "Trying to remap ColumnReference twice without unremapping it.");\r
+               }\r
+\r
+               if ( ! ( (expression instanceof VirtualColumnNode) ||\r
+                                (expression instanceof ColumnReference) )\r
+                       )\r
+               {\r
+                       return;\r
+               }\r
+\r
+               /* Scoped column references are a special case: they can be\r
+                * remapped several times (once for every ProjectRestrictNode\r
+                * through which the scoped ColumnReference is pushed before\r
+                * reaching its target result set) and will be un-remapped\r
+                * several times, as well (as the scoped predicate is "pulled"\r
+                * back up the query tree to it's original location).  So we\r
+                * have to keep track of the "orig" info for every remap\r
+                * operation, not just for the most recent one.\r
+                */\r
+               if (scoped && (origSource != null))\r
+               {\r
+                       if (remaps == null)\r
+                               remaps = new java.util.ArrayList();\r
+                       remaps.add(new RemapInfo(\r
+                               columnNumber, tableNumber, columnName, source));\r
+               }\r
+               else\r
+               {\r
+                       origSource = source;\r
+                       origName = columnName;\r
+                       origColumnNumber = columnNumber;\r
+                       origTableNumber = tableNumber;\r
+               }\r
+\r
+               /* Find the matching ResultColumn */\r
+               source = getSourceResultColumn();\r
+               columnName = source.getName();\r
+               columnNumber = source.getColumnPosition();\r
+\r
+               if (source.getExpression() instanceof ColumnReference)\r
+               {\r
+                       ColumnReference cr = (ColumnReference) source.getExpression();\r
+                       tableNumber = cr.getTableNumber();\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               // if dummy cr generated to replace aggregate, it may not have table number\r
+                               // because underneath can be more than 1 table.\r
+                               if (tableNumber == -1 && ! cr.getGeneratedToReplaceAggregate())\r
+                               {\r
+                                       SanityManager.THROWASSERT(\r
+                                               "tableNumber not expected to be -1, origName = " + origName);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       public void unRemapColumnReferences()\r
+       {\r
+               if (origSource == null)\r
+                       return;\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       // SanityManager.ASSERT(origSource != null,\r
+                       //      "Trying to unremap a ColumnReference that was not remapped.");\r
+               }\r
+\r
+               if ((remaps == null) || (remaps.size() == 0))\r
+               {\r
+                       source = origSource;\r
+                       origSource = null;\r
+                       columnName = origName;\r
+                       origName = null;\r
+                       tableNumber = origTableNumber;\r
+                       columnNumber = origColumnNumber;\r
+               }\r
+               else\r
+               {\r
+                       // This CR is multiply-remapped, so undo the most\r
+                       // recent (and only the most recent) remap operation.\r
+                       RemapInfo rI = (RemapInfo)remaps.remove(remaps.size() - 1);\r
+                       source = rI.getSource();\r
+                       columnName = rI.getColumnName();\r
+                       tableNumber = rI.getTableNumber();\r
+                       columnNumber = rI.getColumnNumber();\r
+                       rI = null;\r
+                       if (remaps.size() == 0)\r
+                               remaps = null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if this ColumnReference has been remapped; false\r
+        * otherwise.\r
+        *\r
+        * @return Whether or not this ColumnReference has been remapped.\r
+        */\r
+       protected boolean hasBeenRemapped()\r
+       {\r
+               return (origSource != null);\r
+       }\r
+\r
+       /*\r
+        * Get the ResultColumn that the source points to.  This is useful for\r
+        * getting what the source will be after this ColumnReference is remapped.\r
+        */\r
+       public ResultColumn getSourceResultColumn()\r
+       {\r
+        /* RESOLVE - If expression is a ColumnReference, then we are hitting\r
+         * the top of a query block (derived table or view.)\r
+         * In order to be able to push the expression down into the next\r
+         * query block, it looks like we should reset the contents of the\r
+         * current ColumnReference to be the same as expression.  (This probably\r
+         * only means names and tableNumber.)  We would then "rebind" the top\r
+         * level predicate somewhere up the call stack and see if we could push\r
+         * the predicate through.\r
+         */\r
+        \r
+        return source.getExpression().getSourceResultColumn();\r
+       }\r
+\r
+       /**\r
+        * Remap all ColumnReferences in this tree to be clones of the\r
+        * underlying expression.\r
+        *\r
+        * @return ValueNode                    The remapped expression tree.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public ValueNode remapColumnReferencesToExpressions()\r
+               throws StandardException\r
+       {\r
+               ResultColumn    rc;\r
+               ResultColumn    sourceRC = source;\r
+\r
+               /* Nothing to do if we are not pointing to a redundant RC */\r
+               if (! source.isRedundant())\r
+               {\r
+                       return this;\r
+               }\r
+\r
+               /* Find the last redundant RC in the chain.  We\r
+                * want to clone its expression.\r
+                */\r
+               for (rc = source; rc != null && rc.isRedundant(); )\r
+               {\r
+                       /* Find the matching ResultColumn */\r
+            ResultColumn nextRC = rc.getExpression().getSourceResultColumn();\r
+\r
+                       if (nextRC != null && nextRC.isRedundant())\r
+                       {\r
+                               sourceRC = nextRC;\r
+                       }\r
+                       rc = nextRC;\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (sourceRC == null)\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "sourceRC is expected to be non-null for " +\r
+                                       columnName);\r
+                       }\r
+\r
+                       if ( ! sourceRC.isRedundant())\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "sourceRC is expected to be redundant for " +\r
+                                       columnName);\r
+                       }\r
+               }\r
+\r
+               /* If last expression is a VCN, then we can't clone it.\r
+                * Instead, we just reset our source to point to the\r
+                * source of the VCN, those chopping out the layers.\r
+                * Otherwise, we return a clone of the underlying expression.\r
+                */\r
+               if (sourceRC.getExpression() instanceof VirtualColumnNode)\r
+               {\r
+                       VirtualColumnNode vcn =\r
+                               (VirtualColumnNode) (sourceRC.getExpression());\r
+                       ResultSetNode rsn = vcn.getSourceResultSet();\r
+                       if (rsn instanceof FromTable)\r
+                       {\r
+                               FromTable ft = (FromTable)rsn;\r
+                               tableNumber = ft.getTableNumber();\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.ASSERT(tableNumber != -1,\r
+                                               "tableNumber not expected to be -1");\r
+                               }\r
+\r
+                               /* It's not enough to just set the table number.  Depending\r
+                                * on the original query specified and on whether or not\r
+                                * subquery flattening has occurred, it's possible that\r
+                                * the expression to which we're remapping has a different\r
+                                * RCL ordering than the one to which we were mapped before\r
+                                * we got here.  In that case we also need to update the\r
+                                * columnNumber to point to the correct column in "ft".\r
+                                * See DERBY-2526 for details.\r
+                                */\r
+                               ResultColumn ftRC =\r
+                                       ft.getResultColumns().getResultColumn(columnName);\r
+\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.ASSERT(ftRC != null,\r
+                                               "Failed to find column '" + columnName + "' in the " +\r
+                                               "RCL for '" + ft.getTableName() + "'.");\r
+                               }\r
+\r
+                               /* Use the virtual column id if the ResultColumn's expression\r
+                                * is a virtual column (DERBY-3023).\r
+                                */\r
+                               columnNumber =\r
+                                       (ftRC.getExpression() instanceof VirtualColumnNode)\r
+                                               ? ftRC.getVirtualColumnId()\r
+                                               : ftRC.getColumnPosition();\r
+                       }\r
+                       else\r
+                       {\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.THROWASSERT("rsn expected to be a FromTable, but is a " + rsn.getClass().getName());\r
+                               }\r
+                       }\r
+                       source = sourceRC.getExpression().getSourceResultColumn();\r
+                       return this;\r
+               }\r
+               else\r
+               {\r
+                       return sourceRC.getExpression().getClone();\r
+               }\r
+       }\r
+\r
+       /** \r
+        * Update the table map to reflect the source\r
+        * of this CR.\r
+        *\r
+        * @param refs  The table map.\r
+        */\r
+       void getTablesReferenced(JBitSet refs)\r
+       {\r
+               if (refs.size() < tableNumber)\r
+                       refs.grow(tableNumber);\r
+\r
+               if (tableNumber != -1)  // it may not be set if replacesAggregate is true\r
+                       refs.set(tableNumber);\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this expression tree is cloneable.\r
+        *\r
+        * @return boolean      Whether or not this expression tree is cloneable.\r
+        */\r
+       public boolean isCloneable()\r
+       {\r
+               return true;\r
+       }\r
+\r
+       /** @see ValueNode#constantExpression */\r
+       public boolean constantExpression(PredicateList whereClause)\r
+       {\r
+               return whereClause.constantColumn(this);\r
+       }\r
+\r
+       /**\r
+        * ColumnReference's are to the current row in the system.\r
+        * This lets us generate\r
+        * a faster get that simply returns the column from the\r
+        * current row, rather than getting the value out and\r
+        * returning that, only to have the caller (in the situations\r
+        * needed) stuffing it back into a new column holder object.\r
+        * We will assume the general generate() path is for getting\r
+        * the value out, and use generateColumn() when we want to\r
+        * keep the column wrapped.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+        public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+        {\r
+               int sourceResultSetNumber = source.getResultSetNumber();\r
+\r
+               //PUSHCOMPILE\r
+               /* Reuse generated code, where possible */\r
+\r
+               /*\r
+               ** If the source is redundant, return the generation of its source.\r
+               ** Most redundant nodes will be flattened out by this point, but\r
+               ** in at least one case (elimination of redundant ProjectRestricts\r
+               ** during generation) we don't do this.\r
+               */\r
+               if (source.isRedundant())\r
+               {\r
+                       source.generateExpression(acb, mb);\r
+                       return;\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (sourceResultSetNumber < 0)\r
+                       {\r
+                               SanityManager.THROWASSERT("sourceResultSetNumber expected to be >= 0 for " + getTableName() + "." + getColumnName());\r
+                       }\r
+               }\r
+\r
+               /* The ColumnReference is from an immediately underlying ResultSet.\r
+                * The Row for that ResultSet is Activation.row[sourceResultSetNumber], \r
+                * where sourceResultSetNumber is the resultSetNumber for that ResultSet.\r
+                *\r
+                * The generated java is the expression:\r
+                *      (<interface>) this.row[sourceResultSetNumber].getColumn(#columnId);\r
+                *\r
+                * where <interface> is the appropriate Datatype protocol interface\r
+                * for the type of the column.\r
+                */\r
+           acb.pushColumnReference(mb, sourceResultSetNumber, \r
+                                                                               source.getVirtualColumnId());\r
+\r
+               mb.cast(getTypeCompiler().interfaceName());\r
+\r
+               /* Remember generated code for possible resuse */\r
+        }\r
+\r
+       /**\r
+        * Get the user-supplied schema name of this column.  This will be null\r
+        * if the user did not supply a name (for example, select t.a from t).\r
+        * Another example for null return value (for example, select b.a from t as b).\r
+        * But for following query select app.t.a from t, this will return APP\r
+        * Code generation of aggregate functions relies on this method\r
+        *\r
+        * @return      The user-supplied schema name of this column.  Null if no user-\r
+        *              supplied name.\r
+        */\r
+\r
+       public String getSchemaName()\r
+       {\r
+               return ( ( tableName != null) ? tableName.getSchemaName() : null );\r
+       }\r
+\r
+       /**\r
+        * Return the variant type for the underlying expression.\r
+        * The variant type can be:\r
+        *              VARIANT                         - variant within a scan\r
+        *                                                        (method calls and non-static field access)\r
+        *              SCAN_INVARIANT          - invariant within a scan\r
+        *                                                        (column references from outer tables)\r
+        *              QUERY_INVARIANT         - invariant within the life of a query\r
+        *                                                        (constant expressions)\r
+        *\r
+        * @return      The variant type for the underlying expression.\r
+        */\r
+       protected int getOrderableVariantType()\r
+       {\r
+               // ColumnReferences are invariant for the life of the scan\r
+               return Qualifier.SCAN_INVARIANT;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not the source of this ColumnReference is itself a ColumnReference.\r
+        *\r
+        * @return Whether or not the source of this ColumnReference is itself a ColumnReference.\r
+        */\r
+       boolean pointsToColumnReference()\r
+       { \r
+               return (source.getExpression() instanceof ColumnReference);\r
+       }\r
+\r
+       /**\r
+        * Get the DataTypeServices from this Node.\r
+        *\r
+        * @return      The DataTypeServices from this Node.  This\r
+        *              may be null if the node isn't bound yet.\r
+        */\r
+       public DataTypeDescriptor getTypeServices() throws StandardException\r
+       {\r
+        DataTypeDescriptor dtd = super.getTypeServices();\r
+        if( dtd == null && source != null)\r
+        {\r
+            dtd = source.getTypeServices();\r
+            if( dtd != null)\r
+                setType( dtd);\r
+        }\r
+        return dtd;\r
+    } // end of getTypeServices\r
+\r
+       /**\r
+        * Find the source result set for this ColumnReference and\r
+        * return it.  Also, when the source result set is found,\r
+        * return the position (within the source result set's RCL)\r
+        * of the column referenced by this ColumnReference.  The\r
+        * position is returned vai the colNum parameter.\r
+        *\r
+        * @param colNum Place to store the position of the column\r
+        *  to which this ColumnReference points (position is w.r.t\r
+        *  the source result set).\r
+        * @return The source result set for this ColumnReference;\r
+        *  null if there is no source result set.\r
+        */\r
+       protected ResultSetNode getSourceResultSet(int [] colNum)\r
+               throws StandardException\r
+       {\r
+               if (source == null)\r
+               {\r
+                       /* this can happen if column reference is pointing to a column\r
+                        * that is not from a base table.  For example, if we have a\r
+                        * VALUES clause like\r
+                        *\r
+                        *    (values (1, 2), (3, 4)) V1 (i, j)\r
+                        *\r
+                        * and then a column reference to VI.i, the column reference\r
+                        * won't have a source.\r
+                        */\r
+                       return null;\r
+               }\r
+\r
+               ValueNode rcExpr = null;\r
+               ResultColumn rc = getSource();\r
+\r
+               // Walk the ResultColumn->ColumnReference chain until we\r
+               // find a ResultColumn whose expression is a VirtualColumnNode.\r
+\r
+               rcExpr = rc.getExpression();\r
+               colNum[0] = getColumnNumber();\r
+\r
+               /* We have to make sure we enter this loop if rc is redundant,\r
+                * so that we can navigate down to the actual source result\r
+                * set (DERBY-1777). If rc *is* redundant, then rcExpr is not\r
+                * guaranteed to be a ColumnReference, so we have to check\r
+                * for that case inside the loop.\r
+                */\r
+               while ((rcExpr != null) &&\r
+                       (rc.isRedundant() || (rcExpr instanceof ColumnReference)))\r
+               {\r
+                       if (rcExpr instanceof ColumnReference)\r
+                       {\r
+                               colNum[0] = ((ColumnReference)rcExpr).getColumnNumber();\r
+                               rc = ((ColumnReference)rcExpr).getSource();\r
+                       }\r
+\r
+                       /* If "rc" is redundant then that means it points to another\r
+                        * ResultColumn that in turn points to the source expression.\r
+                        * This can happen in cases where "rc" points to a subquery\r
+                        * that has been flattened into the query above it (flattening\r
+                        * of subqueries occurs during preprocessing).  In that case\r
+                        * we want to skip over the redundant rc and find the\r
+                        * ResultColumn that actually holds the source expression.\r
+                        */\r
+                       while (rc.isRedundant())\r
+                       {\r
+                               rcExpr = rc.getExpression();\r
+                               if (rcExpr instanceof VirtualColumnNode)\r
+                                       rc = rcExpr.getSourceResultColumn();\r
+                               else if (rcExpr instanceof ColumnReference)\r
+                               {\r
+                                       colNum[0] = ((ColumnReference)rcExpr).getColumnNumber();\r
+                                       rc = ((ColumnReference)rcExpr).getSource();\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* If rc isn't pointing to a VirtualColumnNode nor\r
+                                        * to a ColumnReference, then it's not pointing to\r
+                                        * a result set.  It could, for example, be pointing\r
+                                        * to a constant node or to the result of an aggregate\r
+                                        * or function.  Break out of both loops and return\r
+                                        * null since there is no source result set.\r
+                                        */\r
+                                       rcExpr = null;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       rcExpr = rc.getExpression();\r
+               }\r
+\r
+               // If we found a VirtualColumnNode, return the VirtualColumnNode's\r
+               // sourceResultSet.  The column within that sourceResultSet that\r
+               // is referenced by this ColumnReference is also returned, via\r
+               // the colNum parameter, and was set above.\r
+               if ((rcExpr != null) && (rcExpr instanceof VirtualColumnNode))\r
+                       return ((VirtualColumnNode)rcExpr).getSourceResultSet();\r
+\r
+               // If we get here then the ColumnReference doesn't reference\r
+               // a result set, so return null.\r
+               colNum[0] = -1;\r
+               return null;\r
+       }\r
+       \r
+       protected boolean isEquivalent(ValueNode o) throws StandardException\r
+       {\r
+               if (!isSameNodeType(o)) {\r
+                       return false;\r
+               }\r
+               ColumnReference other = (ColumnReference)o;\r
+               return (tableNumber == other.tableNumber \r
+                               && columnName.equals(other.getColumnName()));\r
+       }\r
+\r
+       /**\r
+        * Mark this column reference as "scoped", which means that it\r
+        * was created (as a clone of another ColumnReference) to serve\r
+        * as the left or right operand of a scoped predicate.\r
+        */\r
+       protected void markAsScoped()\r
+       {\r
+               scoped = true;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this ColumnReference is scoped.\r
+        */\r
+       protected boolean isScoped()\r
+       {\r
+               return scoped;\r
+       }\r
+\r
+       /**\r
+        * Helper class to keep track of remap data when a ColumnReference\r
+        * is remapped multiple times.  This allows the CR to be UN-\r
+        * remapped multiple times, as well.\r
+        */\r
+       private class RemapInfo\r
+       {\r
+               int colNum;\r
+               int tableNum;\r
+               String colName;\r
+               ResultColumn source;\r
+\r
+               RemapInfo(int cNum, int tNum, String cName, ResultColumn rc)\r
+               {\r
+                       colNum = cNum;\r
+                       tableNum = tNum;\r
+                       colName = cName;\r
+                       source = rc;\r
+               }\r
+\r
+               int getColumnNumber() { return colNum; }\r
+               int getTableNumber() { return tableNum; }\r
+               String getColumnName() { return colName; }\r
+               ResultColumn getSource() { return source; }\r
+\r
+               void setColNumber(int cNum) { colNum = cNum; }\r
+               void setTableNumber(int tNum) { tableNum = tNum; }\r
+               void setColName(String cName) { colName = cName; }\r
+               void setSource(ResultColumn rc) { source = rc; }\r
+       }\r
+}\r