Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / compile / ValueNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java
new file mode 100644 (file)
index 0000000..7ea4014
--- /dev/null
@@ -0,0 +1,1416 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.ValueNode\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 java.util.Vector;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.i18n.MessageService;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+import org.apache.derby.iapi.sql.compile.NodeFactory;\r
+import org.apache.derby.iapi.sql.compile.Optimizable;\r
+import org.apache.derby.iapi.sql.compile.TypeCompiler;\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.util.JBitSet;\r
+\r
+/**\r
+ * A ValueNode is an abstract class for all nodes that can represent data\r
+ * values, that is, constants, columns, and expressions.\r
+ *\r
+ */\r
+\r
+public abstract class ValueNode extends QueryTreeNode\r
+{\r
+    /**\r
+     * The data type for this node.\r
+     */\r
+       protected DataTypeDescriptor    dataTypeServices;\r
+   \r
+       private TypeCompiler typeCompiler;\r
+\r
+       // Whether or not additional predicates have been created from this one.\r
+       boolean transformed;\r
+\r
+       /*\r
+       ** Constructor for untyped ValueNodes, for example, untyped NULLs\r
+       ** and parameter nodes.\r
+       **\r
+       ** Binding will replace all untyped ValueNodes with typed ValueNodes\r
+       ** when it figures out what their types should be.\r
+       */\r
+       public ValueNode()\r
+       {\r
+       }\r
+    \r
+    /**\r
+     * Set this node's type from type components.\r
+     */\r
+    final void setType(TypeId typeId,\r
+            boolean isNullable,\r
+            int maximumWidth)\r
+       throws StandardException\r
+       \r
+       {\r
+        setType(\r
+                new DataTypeDescriptor(\r
+                            (TypeId) typeId,\r
+                            isNullable,\r
+                            maximumWidth\r
+                        )\r
+                    );           \r
+       }\r
+\r
+    /**\r
+     * Set this node's type from type components.\r
+     */\r
+    final void setType(TypeId typeId,\r
+            int precision, int scale,\r
+            boolean isNullable,\r
+            int maximumWidth)\r
+       throws StandardException\r
+    {\r
+        setType(\r
+                new DataTypeDescriptor(\r
+                            (TypeId) typeId,\r
+                            precision,\r
+                            scale,\r
+                            isNullable,\r
+                            maximumWidth\r
+                        )\r
+                    );   \r
+    }\r
+\r
+       /**\r
+        * Initializer for numeric types.\r
+        * \r
+        *\r
+        * @param typeId        The TypeID of this new node\r
+        * @param precision     The precision of this new node\r
+        * @param scale         The scale of this new node\r
+        * @param isNullable    The nullability of this new node\r
+        * @param maximumWidth  The maximum width of this new node\r
+        *\r
+        * @exception StandardException\r
+        */\r
+\r
+       public void init(\r
+                       Object typeId,\r
+                       Object precision,\r
+                       Object scale,\r
+                       Object isNullable,\r
+                       Object maximumWidth)\r
+               throws StandardException\r
+       {\r
+               setType(\r
+                       new DataTypeDescriptor(\r
+                                               (TypeId) typeId,\r
+                                               ((Integer) precision).intValue(),\r
+                                               ((Integer) scale).intValue(),\r
+                                               ((Boolean) isNullable).booleanValue(),\r
+                                               ((Integer) maximumWidth).intValue()\r
+                                       )\r
+                               );\r
+       }\r
+\r
+       /**\r
+        * Initializer for non-numeric types.\r
+        * \r
+        *\r
+        * @param tcf           The factory to get the\r
+        *                                      DataTypeServicesFactory from\r
+        * @param typeId        The TypeID of this new node\r
+        * @param isNullable    The nullability of this new node\r
+        * @param maximumWidth  The maximum width of this new node\r
+        *\r
+        * @exception StandardException\r
+        */\r
+\r
+       ValueNode(\r
+                       Object tcf,\r
+                       Object typeId,\r
+                       Object isNullable,\r
+                       Object maximumWidth)\r
+               throws StandardException\r
+       {\r
+               setType(new DataTypeDescriptor(\r
+                                               (TypeId) typeId,\r
+                                               ((Boolean) isNullable).booleanValue(),\r
+                                               ((Integer) maximumWidth).intValue()\r
+                                               )\r
+                               );\r
+       }\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 "dataTypeServices: " +\r
+                               ( ( dataTypeServices != null) ?\r
+                                               dataTypeServices.toString() : "null" ) + "\n" +\r
+                               super.toString();\r
+               }\r
+               else\r
+               {\r
+                       return "";\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Get the DataTypeServices from this ValueNode.\r
+        *\r
+        * @return      The DataTypeServices from this ValueNode.  This\r
+        *              may be null if the node isn't bound yet.\r
+        */\r
+       public DataTypeDescriptor getTypeServices() throws StandardException\r
+       {\r
+               return dataTypeServices;\r
+       }\r
+\r
+       /**\r
+        * Get the TypeId from this ValueNode.\r
+        *\r
+        * @return      The TypeId from this ValueNode.  This\r
+        *              may be null if the node isn't bound yet.\r
+        */\r
+       public TypeId getTypeId() throws StandardException\r
+       {\r
+        DataTypeDescriptor dtd = getTypeServices();\r
+        if (dtd != null)\r
+            return dtd.getTypeId();\r
+               return null;\r
+       }\r
+\r
+\r
+       /**\r
+               Return the DataValueFactory\r
+       */\r
+       protected final DataValueFactory getDataValueFactory() {\r
+               return getLanguageConnectionContext().getDataValueFactory();\r
+       }\r
+\r
+       /**\r
+        * Get the TypeCompiler from this ValueNode, based on its TypeId\r
+     * using getTypeId().\r
+        *\r
+        * @return      This ValueNode's TypeCompiler\r
+        *\r
+        */\r
+       public final TypeCompiler getTypeCompiler() throws StandardException\r
+       {\r
+               return getTypeCompiler(getTypeId());\r
+       }\r
+\r
+       /**\r
+        * Set the DataTypeServices for this ValueNode.  This method is\r
+        * overridden in ParameterNode.\r
+        *\r
+        * @param dataTypeServices      The DataTypeServices to set in this\r
+        *                              ValueNode\r
+        */\r
+\r
+       public void setType(DataTypeDescriptor dataTypeServices) throws StandardException\r
+       {\r
+               this.dataTypeServices = dataTypeServices;\r
+\r
+               // Clear the typeCompiler, just in case type has changed\r
+               typeCompiler = null;\r
+       }\r
+       \r
+       /**\r
+        * There are many subclasses of ValueNode where we want the \r
+        * DataTypeDescriptor of the node to have the same collation type as the \r
+        * compilation schema's collation type. For that purpose, this method in \r
+        * the baseclass here can be utilized by the subclasses. In addition, the\r
+        * subclasses can pass the collationDerivation that they expect the\r
+        * DataTypeDescriptor to have.\r
+        * \r
+        * @param collationDerivation This can be \r
+        * StringDataValue#COLLATION_DERIVATION_IMPLICIT\r
+        * StringDataValue#COLLATION_DERIVATION_NONE\r
+        * StringDataValue#COLLATION_DERIVATION_EXPLICIT\r
+        * \r
+        * @throws StandardException\r
+        */\r
+       protected void setCollationUsingCompilationSchema(int collationDerivation)\r
+       throws StandardException {\r
+        getTypeServices().setCollationType(\r
+                    getSchemaDescriptor(null, false).getCollationType());\r
+        getTypeServices().setCollationDerivation(collationDerivation);\r
+       }\r
+\r
+\r
+       /**\r
+        * Get the source for this ValueNode.\r
+        *\r
+        * @return      The source of this ValueNode, null if this node\r
+     * is not sourced by a column.\r
+        */\r
+\r
+       public ResultColumn getSourceResultColumn()\r
+       {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Mark this predicate has having been transformed (other predicates\r
+        * were generated from it).  This will help us with ensure that the\r
+        * predicate does not get calculated into the selectivity multiple\r
+        * times.\r
+        */\r
+       void setTransformed()\r
+       {\r
+               transformed = true;\r
+       }\r
+\r
+       /** \r
+        * Return whether or not this predicate has been transformed.\r
+        *\r
+        * @return Whether or not this predicate has been transformed.\r
+        */\r
+       boolean getTransformed()\r
+       {\r
+               return transformed;\r
+       }\r
+\r
+       \r
+       public ValueNode bindExpression(\r
+                                                                       FromList fromList, SubqueryList subqueryList,\r
+                                                                       Vector  aggregateVector)\r
+               throws StandardException\r
+       {\r
+               return bindExpression(fromList, subqueryList, aggregateVector,false);\r
+       }\r
+       \r
+\r
+       /**\r
+        * Bind this expression.  This is a place-holder method - it should never\r
+        * be called.\r
+        *\r
+        * @param fromList                      The FROM list to use for binding\r
+        * @param subqueryList          The SubqueryList we are building as we hit\r
+        *                                                      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(\r
+                       FromList fromList, SubqueryList subqueryList,\r
+                       Vector aggregateVector, boolean forQueryRewrite) \r
+                               throws StandardException\r
+       {\r
+               /* There are a bizillion classes which extend ValueNode.  Here is info\r
+                * on some of the classes that bindExpression() should not be called on\r
+                * and why:\r
+                *      o  BaseColumnNodes should only appear under the ResultColumnList\r
+                *     in the FromBaseTable.  They are created/bound when binding the\r
+                *     FromBaseTable.\r
+                */\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(false, \r
+                                               "bindExpression() not expected to be called on a " + \r
+                                               this.getClass().toString());\r
+               }\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Generate a SQL->Java->SQL conversion tree above the current node\r
+        * and bind the new nodes individually.\r
+        * This is useful when doing comparisons, built-in functions, etc. on\r
+        * java types which have a direct mapping to system built-in types.\r
+        *\r
+        * @return ValueNode    The new tree.\r
+        *\r
+        * @exception StandardException Thrown on error\r
+        */\r
+       public ValueNode genSQLJavaSQLTree()\r
+               throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(getTypeId() != null,\r
+                               "genSQLJavaSQLTree() only expected to be called on a bound node");\r
+                       SanityManager.ASSERT(getTypeId().userType(),\r
+                               "genSQLJavaSQLTree() only expected to be called on user types");\r
+               }\r
+\r
+               JavaValueNode stjvn = (JavaValueNode) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,\r
+                                                                       this,\r
+                                                                       getContextManager());\r
+\r
+               ValueNode jtsvn = (ValueNode) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,\r
+                                                                       stjvn,\r
+                                                                       getContextManager());\r
+               jtsvn.setType(DataTypeDescriptor.getSQLDataTypeDescriptor(stjvn.getJavaTypeName()));\r
+               return jtsvn;\r
+       }\r
+\r
+       /**\r
+        * Preprocess an expression tree.  We do a number of transformations\r
+        * here (including subqueries, IN lists, LIKE and BETWEEN) plus\r
+        * subquery flattening.\r
+        * NOTE: This is done before the outer ResultSetNode is preprocessed.\r
+        *\r
+        * @param       numTables                       Number of tables in the DML Statement\r
+        * @param       outerFromList           FromList from outer query block\r
+        * @param       outerSubqueryList       SubqueryList from outer query block\r
+        * @param       outerPredicateList      PredicateList from outer query block\r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode preprocess(int numTables,\r
+                                                               FromList outerFromList,\r
+                                                               SubqueryList outerSubqueryList,\r
+                                                               PredicateList outerPredicateList) \r
+                                       throws StandardException\r
+       {\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Eliminate NotNodes in the current query block.  We traverse the tree, \r
+        * inverting ANDs and ORs and eliminating NOTs as we go.  We stop at \r
+        * ComparisonOperators and boolean expressions.  We invert \r
+        * ComparisonOperators and replace boolean expressions with \r
+        * boolean expression = false.\r
+        * NOTE: Since we do not recurse under ComparisonOperators, there\r
+        * still could be NotNodes left in the tree.\r
+        *\r
+        * @param       underNotNode            Whether or not we are under a NotNode.\r
+        *                                                      \r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       ValueNode eliminateNots(boolean underNotNode) \r
+                                       throws StandardException\r
+       {\r
+               if (! underNotNode)\r
+               {\r
+                       return this;\r
+               }\r
+\r
+               /* bind() has ensured that this node's type is SQLBoolean */\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(\r
+                               getTypeId().isBooleanTypeId(),\r
+                                       "Node's type (" +\r
+                                       getTypeId().getSQLTypeName() +\r
+                                       ") is expected to be boolean");\r
+\r
+               /* Return ValueNode = false */\r
+               return genEqualsFalseTree();\r
+       }\r
+\r
+       /**\r
+        * Transform this into this = false.  Useful for NOT elimination.\r
+        *\r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode genEqualsFalseTree()\r
+                       throws StandardException\r
+       {\r
+               BinaryRelationalOperatorNode equalsNode;\r
+               BooleanConstantNode              falseNode;\r
+               boolean                                 nullableResult;\r
+               NodeFactory                             nodeFactory = getNodeFactory();\r
+\r
+               falseNode = (BooleanConstantNode) nodeFactory.getNode(\r
+                                                                       C_NodeTypes.BOOLEAN_CONSTANT_NODE,\r
+                                                                       Boolean.FALSE,\r
+                                                                       getContextManager());\r
+               equalsNode = (BinaryRelationalOperatorNode)\r
+                                                       nodeFactory.getNode(\r
+                                                               C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,\r
+                                                               this,\r
+                                                               falseNode,\r
+                                                               getContextManager());\r
+               nullableResult = getTypeServices().isNullable();\r
+               equalsNode.setType(new DataTypeDescriptor(\r
+                                                                       TypeId.BOOLEAN_ID,\r
+                                                                       nullableResult)\r
+                                                 );\r
+               return equalsNode;\r
+       }\r
+\r
+       /**\r
+        * Transform this into this is null.  Useful for NOT elimination.\r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode genIsNullTree()\r
+                       throws StandardException\r
+       {\r
+               IsNullNode isNullNode;\r
+\r
+               isNullNode = (IsNullNode)\r
+                                                       getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.IS_NULL_NODE,\r
+                                                                                                       this,\r
+                                                                                                       getContextManager());\r
+               isNullNode.setType(new DataTypeDescriptor(\r
+                                                                       TypeId.BOOLEAN_ID,\r
+                                                                       false)\r
+                                                 );\r
+               return isNullNode;\r
+       }\r
+\r
+       /**\r
+        * Verify that eliminateNots() did its job correctly.  Verify that\r
+        * there are no NotNodes above the top level comparison operators\r
+        * and boolean expressions.\r
+        *\r
+        * @return              Boolean which reflects validity of the tree.\r
+        */\r
+       boolean verifyEliminateNots()\r
+       {\r
+               if (SanityManager.ASSERT)\r
+               {\r
+                       return (! (this instanceof NotNode));\r
+               }\r
+               else\r
+               {\r
+                       return true;\r
+               }\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
+               NodeFactory             nodeFactory = getNodeFactory();\r
+\r
+        QueryTreeNode trueNode = nodeFactory.getNode(\r
+                                                                               C_NodeTypes.BOOLEAN_CONSTANT_NODE,\r
+                                                                               Boolean.TRUE,\r
+                                                                               getContextManager());\r
+               AndNode andNode = (AndNode) nodeFactory.getNode(\r
+                                                                               C_NodeTypes.AND_NODE,\r
+                                                                               this,\r
+                                                                               trueNode,\r
+                                                                               getContextManager());\r
+               andNode.postBindFixup();\r
+               return andNode;\r
+       }\r
+\r
+       /**\r
+        * Verify that putAndsOnTop() did its job correctly.  Verify that the top level \r
+        * of the expression is a chain of AndNodes.\r
+        *\r
+        * @return              Boolean which reflects validity of the tree.\r
+        */\r
+       public boolean verifyPutAndsOnTop()\r
+       {\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * Finish putting an expression into conjunctive normal\r
+        * form.  An expression tree in conjunctive normal form meets\r
+        * the following criteria:\r
+        *              o  If the expression tree is not null,\r
+        *                 the top level will be a chain of AndNodes terminating\r
+        *                 in a true BooleanConstantNode.\r
+        *              o  The left child of an AndNode will never be an AndNode.\r
+        *              o  Any right-linked chain that includes an AndNode will\r
+        *                 be entirely composed of AndNodes terminated by a true BooleanConstantNode.\r
+        *              o  The left child of an OrNode will never be an OrNode.\r
+        *              o  Any right-linked chain that includes an OrNode will\r
+        *                 be entirely composed of OrNodes terminated by a false BooleanConstantNode.\r
+        *              o  ValueNodes other than AndNodes and OrNodes are considered\r
+        *                 leaf nodes for purposes of expression normalization.\r
+        *                 In other words, we won't do any normalization under\r
+        *                 those nodes.\r
+        *\r
+        * In addition, we track whether or not we are under a top level AndNode.  \r
+        * SubqueryNodes need to know this for subquery flattening.\r
+        *\r
+        * @param       underTopAndNode         Whether or not we are under a top level AndNode.\r
+        *                                                      \r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode changeToCNF(boolean underTopAndNode) \r
+                                       throws StandardException\r
+       {\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Verify that changeToCNF() did its job correctly.  Verify that:\r
+        *              o  AndNode  - rightOperand is not instanceof OrNode\r
+        *                                    leftOperand is not instanceof AndNode\r
+        *              o  OrNode       - rightOperand is not instanceof AndNode\r
+        *                                        leftOperand is not instanceof OrNode\r
+        *\r
+        * @return              Boolean which reflects validity of the tree.\r
+        */\r
+       public boolean verifyChangeToCNF()\r
+       {\r
+               return true;\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
+        * 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.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)\r
+               throws StandardException\r
+       {\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * This returns the user-supplied schema name of the column.\r
+        * At this class level, it simply returns null. But, the subclasses\r
+        * of ValueNode will overwrite this method to return the\r
+        * user-supplied schema name.\r
+        * \r
+        * When the value node is in a result column of a select list,\r
+        * the user can request metadata information. The result column\r
+        * won't have a column descriptor, so we return some default\r
+        * information through the expression. This lets expressions that\r
+        * are simply columns return all of the info, and others use\r
+        * this supertype's default values.\r
+        *\r
+        * @return the default schema name for an expression -- null\r
+        */\r
+       public String getSchemaName() throws StandardException\r
+       {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * This returns the user-supplied table name of the column.\r
+        * At this class level, it simply returns null. But, the subclasses\r
+        * of ValueNode will overwrite this method to return the\r
+        * user-supplied table name.\r
+        *\r
+        * When the value node is in a result column of a select list,\r
+        * the user can request metadata information. The result column\r
+        * won't have a column descriptor, so we return some default\r
+        * information through the expression. This lets expressions that\r
+        * are simply columns return all of the info, and others use\r
+        * this supertype's default values.\r
+        *\r
+        * @return the default table name for an expression -- null\r
+        */\r
+       public String getTableName()\r
+       {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * @return the default updatability for an expression - false\r
+        */\r
+       public boolean updatableByCursor()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * This is null so that the caller will substitute in the resultset generated\r
+        * name as needed.\r
+        *\r
+        * @return the default column name for an expression -- null.\r
+        */\r
+       public String getColumnName()\r
+       {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Get a bit map of table references in this expression\r
+        *\r
+        * @return      A bit map of table numbers referred to in this expression\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       JBitSet getTablesReferenced()\r
+               throws StandardException\r
+       {\r
+               ReferencedTablesVisitor rtv = new ReferencedTablesVisitor(new JBitSet(0));\r
+               accept(rtv);\r
+               return rtv.getTableMap();\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 false;\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() throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(false,\r
+                               "getClone() not expected to be called for " +\r
+                               getClass().getName());\r
+               }\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Copy all of the "appropriate fields" for a shallow copy.\r
+        *\r
+        * @param oldVN         The ValueNode to copy from.\r
+        *\r
+        */\r
+       public void copyFields(ValueNode oldVN) throws StandardException\r
+       {\r
+               dataTypeServices = oldVN.getTypeServices();\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() throws StandardException\r
+       {\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this expression tree represents a constant expression.\r
+        *\r
+        * @return      Whether or not this expression tree represents a constant expression.\r
+        */\r
+       public boolean isConstantExpression()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this expression tree represents a constant value.\r
+        * In this case, "constant" means that it will always evaluate to the\r
+        * same thing, even if it includes columns.  A column is constant if it\r
+        * is compared to a constant expression.\r
+        *\r
+        * @return      True means this expression tree represents a constant value.\r
+        */\r
+       public boolean constantExpression(PredicateList whereClause)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+         * Bind time logic. Raises an error if this ValueNode, once compiled, returns\r
+         * unstable results AND if we're in a context where unstable results are\r
+         * forbidden.\r
+         *\r
+         * Called by children who may NOT appear in the WHERE subclauses of ADD TABLE clauses.\r
+         *\r
+         *     @param  fragmentType    Type of fragment as a String, for inclusion in error messages.\r
+         *     @param  fragmentBitMask Type of fragment as a bitmask of possible fragment types\r
+         *\r
+         * @exception StandardException                Thrown on error\r
+         */\r
+       public  void    checkReliability( String fragmentType, int fragmentBitMask )\r
+               throws StandardException\r
+       {\r
+               // if we're in a context that forbids unreliable fragments, raise an error\r
+               if ( ( getCompilerContext().getReliability() & fragmentBitMask ) != 0 )\r
+               {\r
+            throwReliabilityException( fragmentType );\r
+               }\r
+       }\r
+\r
+       /**\r
+         * Bind time logic. Raises an error if this ValueNode, once compiled, returns\r
+         * unstable results AND if we're in a context where unstable results are\r
+         * forbidden.\r
+         *\r
+         * Called by children who may NOT appear in the WHERE subclauses of ADD TABLE clauses.\r
+         *\r
+         *     @param  fragmentBitMask Type of fragment as a bitmask of possible fragment types\r
+         *     @param  fragmentType    Type of fragment as a String, to be fetch for the error message.\r
+         *\r
+         * @exception StandardException                Thrown on error\r
+         */\r
+       public  void    checkReliability( int fragmentBitMask, String fragmentType )\r
+               throws StandardException\r
+       {\r
+               // if we're in a context that forbids unreliable fragments, raise an error\r
+               if ( ( getCompilerContext().getReliability() & fragmentBitMask ) != 0 )\r
+               {\r
+            String fragmentTypeTxt = MessageService.getTextMessage( fragmentType );\r
+            throwReliabilityException( fragmentTypeTxt );\r
+               }\r
+       }\r
+\r
+    /**\r
+     * Common code for the 2 checkReliability functions.  Always throws StandardException.\r
+     *\r
+     * @param fragmentType Type of fragment as a string, for inclusion in error messages.\r
+     * @exception StandardException        Throws an error, always.\r
+     */\r
+    private void throwReliabilityException( String fragmentType ) throws StandardException\r
+    {\r
+        String sqlState;\r
+               /* Error string somewhat dependent on operation due to different\r
+                * nodes being allowed for different operations.\r
+                */\r
+               if (getCompilerContext().getReliability() == CompilerContext.DEFAULT_RESTRICTION)\r
+               {\r
+            sqlState = SQLState.LANG_INVALID_DEFAULT_DEFINITION;\r
+               }\r
+               else\r
+               {\r
+            sqlState = SQLState.LANG_UNRELIABLE_QUERY_FRAGMENT;\r
+               }\r
+               throw StandardException.newException(sqlState, fragmentType);\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
+        * @exception StandardException         Thrown on error\r
+        */\r
+       protected int getOrderableVariantType() throws StandardException\r
+       {\r
+               // The default is VARIANT\r
+               return Qualifier.VARIANT;\r
+       }\r
+\r
+\r
+       /**\r
+         * Bind time logic. Raises an error if this ValueNode does not resolve to\r
+         *     a boolean value. This method is called by WHERE clauses.\r
+         *\r
+         *     @return bound coercion of this node to a builtin type as necessary\r
+         *\r
+         * @exception StandardException                Thrown on error\r
+         */\r
+       public  ValueNode       checkIsBoolean()\r
+               throws StandardException\r
+       {\r
+               ValueNode       whereClause = this;\r
+\r
+               /*\r
+               ** Is the datatype of the WHERE clause BOOLEAN?\r
+               **\r
+               ** NOTE: This test is not necessary in SQL92 entry level, because\r
+               ** it is syntactically impossible to have a non-Boolean WHERE clause\r
+               ** in that level of the standard.  But we intend to extend the\r
+               ** language to allow Boolean user functions in the WHERE clause,\r
+               ** so we need to test for the error condition.\r
+               */\r
+               TypeId whereTypeId = whereClause.getTypeId();\r
+\r
+               /* If the where clause is not a built-in type, then generate a bound \r
+                * conversion tree to a built-in type.\r
+                */\r
+               if (whereTypeId.userType())\r
+               {\r
+                       whereClause = whereClause.genSQLJavaSQLTree();\r
+                       whereTypeId = whereClause.getTypeId();\r
+               }\r
+\r
+               if (! whereTypeId.equals(TypeId.BOOLEAN_ID))\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, \r
+                               whereTypeId.getSQLTypeName()\r
+                               );\r
+               }\r
+\r
+               return  whereClause;\r
+       }\r
+\r
+       /**\r
+        * Return an Object representing the bind time value of this\r
+        * expression tree.  If the expression tree does not evaluate to\r
+        * a constant at bind time then we return null.\r
+        * This is useful for bind time resolution of VTIs.\r
+        * RESOLVE: What do we do for primitives?\r
+        *\r
+        * @return      An Object representing the bind time value of this expression tree.\r
+        *                      (null if not a bind time constant.)\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       Object getConstantValueAsObject()\r
+               throws StandardException\r
+       {\r
+               return null;\r
+       }\r
+\r
+       /////////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      The ValueNode defers its generate() work to a method that works on\r
+       //      ExpressionClassBuilders rather than ActivationClassBuilders. This\r
+       //      is so that expression generation can be shared by the Core compiler\r
+       //      AND the Replication Filter compiler.\r
+       //\r
+       /////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+       /**\r
+        * Do the code generation for this node.  Call the more general\r
+        * routine that generates expressions.\r
+        *\r
+        * @param acb   The ActivationClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       protected final void generate(ActivationClassBuilder acb,\r
+                                                                               MethodBuilder mb)\r
+                                                               throws StandardException\r
+       {\r
+               generateExpression( acb, mb );\r
+       }\r
+\r
+       /**\r
+        * The only reason this routine exists is so that I don't have to change\r
+        * the protection on generateExpression() and rototill all of QueryTree.\r
+        *\r
+        * @param ecb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public  void generateFilter(ExpressionClassBuilder ecb,\r
+                                                                               MethodBuilder mb)\r
+               throws StandardException\r
+       {\r
+               generateExpression( ecb, mb );\r
+       }\r
+       \r
+\r
+       /**\r
+        * The default selectivity for value nodes is 50%.  This is overridden\r
+        * in specific cases, such as the RelationalOperators.\r
+        */\r
+       public double selectivity(Optimizable optTable)\r
+       throws StandardException\r
+       {\r
+               // Return 1 if additional predicates have been generated from this one.\r
+               if (transformed)\r
+               {\r
+                       return 1.0;\r
+               }\r
+               else\r
+               {\r
+                       return 0.5d;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Update the array of columns in = conditions with expressions without\r
+        * column references from the same table.  This is useful when doing\r
+        * subquery flattening on the basis of an equality condition.\r
+        * eqOuterCols or tableColMap may be null if the calling routine\r
+        * doesn't need the information provided\r
+        *\r
+        * @param tableNumber   The tableNumber of the table from which\r
+        *                                              the columns of interest come from.\r
+        * @param eqOuterCols   Array of booleans for noting which columns\r
+        *                                              are in = predicates without columns from the\r
+        *                                              subquery block. May be null.\r
+        * @param tableNumbers  Array of table numbers in this query block.\r
+        * @param tableColMap   Array of bits for noting which columns\r
+        *                                              are in = predicates for each table in the\r
+        *                                              query block. May be null.\r
+        * @param resultColTable True if tableNumber is the table containing result\r
+        *                                              columns\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        * \r
+        */\r
+       void checkTopPredicatesForEqualsConditions(\r
+                               int tableNumber, boolean[] eqOuterCols, int[] tableNumbers, \r
+                               JBitSet[] tableColMap, boolean resultColTable)\r
+               throws StandardException\r
+       {\r
+               for (ValueNode whereWalker = this; whereWalker instanceof AndNode; \r
+                        whereWalker = ((AndNode) whereWalker).getRightOperand())\r
+               {\r
+                       // See if this is a candidate =\r
+                       AndNode and = (AndNode) whereWalker;\r
+\r
+                       if (!and.getLeftOperand().isRelationalOperator() ||\r
+                               !(((RelationalOperator)(and.getLeftOperand())).getOperator() == RelationalOperator.EQUALS_RELOP))\r
+                       {\r
+                               continue;\r
+                       }\r
+\r
+                       BinaryRelationalOperatorNode beon =\r
+                                       (BinaryRelationalOperatorNode) and.getLeftOperand();\r
+                       ValueNode left = beon.getLeftOperand();\r
+                       ValueNode right = beon.getRightOperand();\r
+                       int resultTable = 0;\r
+                       if (resultColTable)\r
+                       {\r
+                               for ( ; resultTable < tableNumbers.length; resultTable++)\r
+                               {\r
+                                       if (tableNumbers[resultTable] == tableNumber)\r
+                                               break;\r
+                               }\r
+                       }\r
+                       else\r
+                               resultTable = -1;\r
+\r
+                       /* Is this = of the right form? */\r
+                       if ((left instanceof ColumnReference) &&\r
+                               ((ColumnReference) left).getTableNumber() == tableNumber)\r
+                       {\r
+                               updateMaps(tableColMap, eqOuterCols, tableNumbers, tableNumber,\r
+                                       resultTable, right, left);\r
+                       }\r
+                       else if ((right instanceof ColumnReference) &&\r
+                                        ((ColumnReference) right).getTableNumber() == tableNumber)\r
+                       {\r
+                               updateMaps(tableColMap, eqOuterCols, tableNumbers, tableNumber,\r
+                                       resultTable, left, right);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Does this represent a true constant.\r
+        *\r
+        * @return Whether or not this node represents a true constant.\r
+        */\r
+       boolean isBooleanTrue()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Does this represent a false constant.\r
+        *\r
+        * @return Whether or not this node represents a false constant.\r
+        */\r
+       boolean isBooleanFalse()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Generate code for this calculation.  This is a place-holder method -\r
+        * it should not be called.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                               throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(false, "Code generation for this type of ValueNode is unimplemented");\r
+       }\r
+\r
+       /**\r
+        * Set the correct bits in tableColMap and set the boolean value in eqOuterCols \r
+        * given two arguments to an = predicate\r
+        * tableColMap[t] - bit is set if the column is in an = predicate with a column \r
+        *                                      in table t, or a bit is set if the column is in an \r
+        *                                      = predicate with a constant,parameter or correlation variable \r
+        *                                  (for all table t, if this tableColMap is not for the\r
+        *                                      table with the result columns)\r
+        * eqOuterCols[c] - is true if the column is in an = predicate with a constant,\r
+        *                                      parameter or correlation variable\r
+        * \r
+        *\r
+        * @param tableColMap   Array of bitmaps for noting which columns are in = \r
+        *                                              predicates with columns from each table\r
+        * @param eqOuterCols   Array of booleans for noting which columns\r
+        *                                              are in = predicates without columns from the\r
+        *                                              subquery block.\r
+        * @param tableNumber   table number for which we are setting up the Maps\r
+        * @param resultTable   -1 if this table is not the result table; otherwise\r
+        *                                              the index into tableNumbers for the result table\r
+        * @param arg1                  one side of the = predicate\r
+        * @param arg2                  other side of the = predicate\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       private void updateMaps(JBitSet[] tableColMap, boolean[] eqOuterCols,\r
+               int[] tableNumbers,  int tableNumber, int resultTable,\r
+               ValueNode arg1, ValueNode arg2)\r
+                       throws StandardException\r
+       {\r
+               /* arg2 is a column from our table.  This\r
+                * is a good = for both All tables and Outer arrays\r
+                * if the right side is a constant or a parameter\r
+                * or a column from an outer table.\r
+                * It is a good = for only the All array if\r
+                * the right side is a column from this query block.\r
+                */\r
+               if ((arg1 instanceof ConstantNode) || (arg1.requiresTypeFromContext()))\r
+               {\r
+                       setValueCols(tableColMap, eqOuterCols,\r
+                               ((ColumnReference) arg2).getColumnNumber(), resultTable);\r
+               }\r
+               else if((arg1 instanceof ColumnReference &&\r
+                                       ((ColumnReference) arg1).getTableNumber() != tableNumber))\r
+               {\r
+                       /* See if other columns is a correlation column */\r
+                       int otherTN = ((ColumnReference) arg1).getTableNumber();\r
+                       int index = 0;\r
+                       int colNumber = ((ColumnReference) arg2).getColumnNumber();\r
+\r
+                       for ( ; index < tableNumbers.length; index++)\r
+                       {\r
+                               if (otherTN == tableNumbers[index])\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       /* Correlation column, so we can treat it as a constant */\r
+                       if (index == tableNumbers.length)\r
+                       {\r
+                               setValueCols(tableColMap, eqOuterCols, colNumber, resultTable);\r
+                       }\r
+                       else if (tableColMap != null)\r
+                       {\r
+                               tableColMap[index].set(colNumber);\r
+                       }\r
+\r
+               }\r
+               else\r
+               {\r
+                       /* See if other side contains a column reference from the same table */\r
+                       JBitSet referencedTables = arg1.getTablesReferenced();\r
+                       /* See if other columns are all correlation columns */\r
+                       int index = 0;\r
+                       int colNumber = ((ColumnReference) arg2).getColumnNumber();\r
+                       for ( ; index < tableNumbers.length; index++)\r
+                       {\r
+                               if (referencedTables.get(tableNumbers[index]))\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       /* Correlation column, so we can treat it as a constant */\r
+                       if (index == tableNumbers.length)\r
+                       {\r
+                               setValueCols(tableColMap, eqOuterCols, colNumber, resultTable);\r
+                       }\r
+                       else if (tableColMap != null && !referencedTables.get(tableNumber))\r
+                       {\r
+                               tableColMap[index].set(colNumber);\r
+                       }\r
+               }\r
+       }\r
+       /**\r
+        * Set eqOuterCols and the column in all the tables for constants,\r
+        * parmeters and correlation columns\r
+        * The column in the tableColMap is set only for the current table\r
+        * if the table is the result column table.  For other tables in the\r
+        * query we set the column for all the tables since the constant will\r
+        * reduced the number of columns required in a unique multicolumn index for\r
+        * distinctness.\r
+        * For example, given an unique index on t1(a,b), setting b=1 means that\r
+        * t1(a) is unique since there can be no duplicates for a where b=1 without\r
+        * destroying the uniqueness of t1(a,b).  However, for the result columns\r
+        * setting b=1, does not mean that a select list of t1.a is distinct if\r
+        * t1.a is the only column used in joining with another table\r
+        * e.g. select t1.a from t1, t2 where t1.a = t2.a and t1.b = 1;\r
+        * \r
+        *      t1                      t2                      result\r
+        *      a       b               a                       a\r
+        *  1   1               1                       1\r
+        *  1   2               2                       1\r
+        *      2       1\r
+        * \r
+        *\r
+        * @param tableColMap   Array of bitmaps for noting which columns are in = \r
+        *                                              predicates with columns from each table\r
+        * @param eqOuterCols   Array of booleans for noting which columns\r
+        *                                              are in = predicates without columns from the\r
+        *                                              subquery block.\r
+        * @param colReference  The column to set\r
+        * @param resultTable   If -1 set all the bit for all the tables for that\r
+        *                                              column; otherwise set the bit for the specified table\r
+        *\r
+        *\r
+        */\r
+       private void setValueCols(JBitSet[] tableColMap, boolean[] eqOuterCols, \r
+               int colReference, int resultTable)\r
+       {\r
+               if (eqOuterCols != null)\r
+                       eqOuterCols[colReference] = true;\r
+\r
+               if (tableColMap != null)\r
+               {\r
+                       if (resultTable == -1)\r
+                       {\r
+                               for (int i = 0; i < tableColMap.length; i++)\r
+                                       tableColMap[i].set(colReference);\r
+                       }\r
+                       else\r
+                               tableColMap[resultTable].set(colReference);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if this ValueNode is a relational operator. Relational\r
+        * Operators are <, <=, =, >, >=, <> as well as IS NULL and IS NOT\r
+        * NULL. This is the preferred way of figuring out if a ValueNode is\r
+        * relational or not. \r
+        * @see RelationalOperator\r
+        * @see BinaryRelationalOperatorNode\r
+        * @see IsNullNode\r
+       */\r
+       public boolean isRelationalOperator()\r
+       {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Returns true if this value node is a <em>equals</em> operator. \r
+        *\r
+        * @see ValueNode#isRelationalOperator\r
+        */\r
+       public boolean isBinaryEqualsOperatorNode()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Returns true if this value node is an operator created\r
+        * for optimized performance of an IN list.\r
+        *\r
+        * Or more specifically, returns true if this value node is\r
+        * an equals operator of the form "col = ?" that we generated\r
+        * during preprocessing to allow index multi-probing.\r
+        */\r
+       public boolean isInListProbeNode()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /** Return true if the predicate represents an optimizable equality node.\r
+        * an expression is considered to be an optimizable equality node if all the\r
+        * following conditions are met:\r
+        * <ol>\r
+        * <li> the operator is an <em>=</em> or <em>IS NULL</em> operator </li>\r
+        * <li> one of the operands is a column specified by optTable/columnNumber</li>\r
+        * <li> Both operands are not the same column; i.e tab.col = tab.col </li>\r
+        * <li> There are no implicit varchar comparisons of the operands; i.e\r
+        * either both operands are string like (varchar, char, longvarchar) or\r
+        * neither operand is string like </li>\r
+        * </ol>\r
+        * \r
+        * @param optTable      the table being optimized. Column reference must be from\r
+        * this table.\r
+        * @param columnNumber the column number. One of the operands of this\r
+        * predicate must be the column number specified by optTable/columnNumber\r
+        * @param isNullOkay if set to true we also consider IS NULL predicates;\r
+        * otherwise consider only = predicates.\r
+        */\r
+       public boolean optimizableEqualityNode(Optimizable optTable, \r
+                                                                                  int columnNumber, \r
+                                                                                  boolean isNullOkay)\r
+               throws StandardException\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Returns TRUE if the type of this node will be determined from the\r
+        * context in which it is getting used. If true is returned then\r
+     * after bindExpression() is called on the node, its type\r
+     * must be set (from the relevant context) using setType().\r
+        *\r
+        * @return Whether this node's type will be determined from the context\r
+        */\r
+       public boolean requiresTypeFromContext()\r
+       {\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Returns TRUE if this is a parameter node. We do lots of special things\r
+        * with Parameter Nodes.\r
+        *\r
+        */\r
+       public boolean isParameterNode()\r
+       {\r
+               return false;\r
+       }\r
+       \r
+       /**\r
+        * Tests if this node is equivalent to the specified ValueNode. Two \r
+        * ValueNodes are considered equivalent if they will evaluate to the same\r
+        * value during query execution. \r
+        * <p> \r
+        * This method provides basic expression matching facility for the derived \r
+        * class of ValueNode and it is used by the language layer to compare the \r
+        * node structural form of the two expressions for equivalence at bind \r
+        * phase.  \r
+        *  <p>\r
+        * Note that it is not comparing the actual row values at runtime to produce \r
+        * a result; hence, when comparing SQL NULLs, they are considered to be \r
+        * equivalent and not unknown.  \r
+        *  <p>\r
+        * One usage case of this method in this context is to compare the select \r
+        * column expression against the group by expression to check if they are \r
+        * equivalent.  e.g.:\r
+        *  <p>\r
+        * SELECT c1+c2 FROM t1 GROUP BY c1+c2   \r
+        *  <p>\r
+        * In general, node equivalence is determined by the derived class of \r
+        * ValueNode.  But they generally abide to the rules below:\r
+        *  <ul>\r
+        * <li>The two ValueNodes must be of the same node type to be considered \r
+        *   equivalent.  e.g.:  CastNode vs. CastNode - equivalent (if their args \r
+        *   also match), ColumnReference vs CastNode - not equivalent.\r
+        *   \r
+        * <li>If node P contains other ValueNode(s) and so on, those node(s) must \r
+        *   also be of the same node type to be considered equivalent.\r
+        *   \r
+        * <li>If node P takes a parameter list, then the number of arguments and its \r
+        *   arguments for the two nodes must also match to be considered \r
+        *   equivalent.  e.g.:  CAST(c1 as INTEGER) vs CAST(c1 as SMALLINT), they \r
+        *   are not equivalent.\r
+        *   \r
+        * <li>When comparing SQL NULLs in this context, they are considered to be \r
+        *   equivalent.\r
+        * \r
+        * <li>If this does not apply or it is determined that the two nodes are not \r
+        *   equivalent then the derived class of this method should return false; \r
+        *   otherwise, return true.\r
+        * </ul>   \r
+        *   \r
+        * @param other the node to compare this ValueNode against.\r
+        * @return <code>true</code> if the two nodes are equivalent, \r
+        * <code>false</code> otherwise.\r
+        * \r
+        * @throws StandardException \r
+        */\r
+       protected abstract boolean isEquivalent(ValueNode other)\r
+               throws StandardException;\r
+\r
+       /**\r
+        * Tests if this node is of the same type as the specified node as\r
+        * reported by {@link QueryTreeNode#getNodeType()}.\r
+        * \r
+        * @param other the node to compare this value node against. \r
+        * \r
+        * @return <code>true</code> if the two nodes are of the same type.  \r
+        */\r
+       protected final boolean isSameNodeType(ValueNode other)\r
+       {\r
+               if (other != null) {\r
+                       return other.getNodeType() == getNodeType();\r
+               }\r
+               return false;\r
+       }\r
+       \r
+}\r