--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.ConstantNode\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.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.TypeId;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * ConstantNode holds literal constants as well as nulls.\r
+ * <p>\r
+ * A NULL from the parser may not yet know its type; that\r
+ * must be set during binding, as it is for parameters.\r
+ * <p>\r
+ * the DataValueDescriptor methods want to throw exceptions\r
+ * when they are of the wrong type, but to do that they\r
+ * must check typeId when the value is null, rather than\r
+ * the instanceof check they do for returning a valid value.\r
+ * <p>\r
+ * For code generation, we generate a static field. Then we set the \r
+ * field be the proper constant expression (something like <code>\r
+ * getDatavalueFactory().getCharDataValue("hello", ...)) </code>)\r
+ * in the constructor of the generated method. Ideally\r
+ * we would have just \r
+ */\r
+abstract class ConstantNode extends ValueNode\r
+{\r
+ DataValueDescriptor value;\r
+\r
+ /*\r
+ ** In case generateExpression() is called twice (something\r
+ ** that probably wont happen but might), we will cache\r
+ ** our generated expression and just return a reference\r
+ ** to the field that holds our value (instead of having\r
+ ** two fields holding the same constant).\r
+ */\r
+\r
+ /**\r
+ * Initializer for non-numeric types\r
+ *\r
+ * @param typeId The Type ID of the datatype\r
+ * @param nullable True means the constant is nullable\r
+ * @param maximumWidth The maximum number of bytes in the data value\r
+ *\r
+ * @exception StandardException\r
+ */\r
+ public void init(\r
+ Object typeId,\r
+ Object nullable,\r
+ Object maximumWidth)\r
+ throws StandardException\r
+ {\r
+ setType((TypeId) typeId,\r
+ ((Boolean) nullable).booleanValue(),\r
+ ((Integer) maximumWidth).intValue());\r
+\r
+ }\r
+\r
+ /**\r
+ * Constructor for untyped nodes, which contain little information\r
+ *\r
+ */\r
+ ConstantNode()\r
+ {\r
+ super();\r
+ }\r
+\r
+ /**\r
+ * Set the value in this ConstantNode.\r
+ */\r
+ void setValue(DataValueDescriptor value)\r
+ {\r
+ this.value = value;\r
+ }\r
+\r
+ /**\r
+ * Get the value in this ConstantNode\r
+ */\r
+ public DataValueDescriptor getValue()\r
+ {\r
+ return value;\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 "value: " + value + "\n" +\r
+ super.toString();\r
+ }\r
+ else\r
+ {\r
+ return "";\r
+ }\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
+ /**\r
+ * Return a clone of this node.\r
+ *\r
+ * @return ValueNode A clone of this node.\r
+ *\r
+ */\r
+ public ValueNode getClone()\r
+ {\r
+ /* All constants can simply be reused */\r
+ return this;\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
+ * In this case, there are no sub-expressions, and the return type\r
+ * is already known, so this is just a stub.\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. Although this class\r
+ * doesn't throw this exception, it's subclasses do and hence this method\r
+ * signature here needs to have throws StandardException \r
+ */\r
+ public ValueNode bindExpression(\r
+ FromList fromList, SubqueryList subqueryList,\r
+ Vector aggregateVector)\r
+ throws StandardException\r
+ {\r
+ /*\r
+ ** This has to be here for binding to work, but it doesn't\r
+ ** have to do anything, because the datatypes of constant nodes\r
+ ** are pre-generated by the parser.\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 true;\r
+ }\r
+\r
+ /** @see ValueNode#constantExpression */\r
+ public boolean constantExpression(PredicateList whereClause)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * For a ConstantNode, we generate the equivalent literal value.\r
+ * A null is generated as a Null value cast to the type of\r
+ * the constant node.\r
+ * The subtypes of ConstantNode generate literal expressions\r
+ * for non-null values.\r
+ *\r
+ * @param acb The ExpressionClassBuilder for the class being built\r
+ * @param mb The method the code to place the code\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void generateExpression\r
+ (\r
+ ExpressionClassBuilder acb, \r
+ MethodBuilder mb\r
+ ) throws StandardException\r
+ {\r
+ /* Are we generating a SQL null value? */\r
+ if (isNull())\r
+ {\r
+ acb.generateNull(mb, getTypeCompiler(), \r
+ getTypeServices().getCollationType());\r
+ }\r
+ else\r
+ {\r
+ generateConstant(acb, mb); // ask sub type to give a constant,\r
+ // usually a literal like 'hello'\r
+\r
+ acb.generateDataValue(mb, getTypeCompiler(), \r
+ getTypeServices().getCollationType(), (LocalField) null);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * This generates the proper constant. It is implemented\r
+ * by every specific constant node (e.g. IntConstantNode).\r
+ *\r
+ * @param acb The ExpressionClassBuilder for the class being built\r
+ * @param mb The method the code to place the code\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ abstract void generateConstant(ExpressionClassBuilder acb, MethodBuilder mb)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Return whether or not this node represents a typed null constant.\r
+ *\r
+ */\r
+ boolean isNull()\r
+ {\r
+ return (value == null || value.isNull());\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
+ * VARIANT - immutable\r
+ *\r
+ * @return The variant type for the underlying expression.\r
+ */\r
+ protected int getOrderableVariantType()\r
+ {\r
+ // Constants are constant for the life of the query\r
+ return Qualifier.CONSTANT;\r
+ }\r
+ \r
+ protected boolean isEquivalent(ValueNode o) throws StandardException\r
+ {\r
+ if (isSameNodeType(o)) {\r
+ ConstantNode other = (ConstantNode)o;\r
+ \r
+ // value can be null which represents a SQL NULL value.\r
+ return ( (other.getValue() == null && getValue() == null) || \r
+ (other.getValue() != null && \r
+ other.getValue().compare(getValue()) == 0) );\r
+ }\r
+ return false;\r
+ }\r
+}\r