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 / UnaryArithmeticOperatorNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/UnaryArithmeticOperatorNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/UnaryArithmeticOperatorNode.java
new file mode 100644 (file)
index 0000000..8343c76
--- /dev/null
@@ -0,0 +1,276 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.UnaryArithmeticOperatorNode\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.dictionary.DataDictionary;\r
+\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.reference.SQLState;\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.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import java.sql.Types;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * This node represents a unary arithmetic operator\r
+ *\r
+ */\r
+\r
+public class UnaryArithmeticOperatorNode extends UnaryOperatorNode\r
+{\r
+       private final static int UNARY_PLUS     = 0;\r
+       private final static int UNARY_MINUS    = 1;\r
+       private final static int SQRT = 2;\r
+       private final static int ABSOLUTE = 3;\r
+       private final static String[] UNARY_OPERATORS = {"+","-","SQRT", "ABS/ABSVAL"};\r
+       private final static String[] UNARY_METHODS = {"plus","minus","sqrt", "absolute"};\r
+\r
+       private int operatorType;\r
+  \r
+       /**\r
+        * Initializer for a UnaryArithmeticOperatorNode\r
+        *\r
+        * @param operand               The operand of the node\r
+        */\r
+       public void init(Object operand)\r
+       {\r
+               switch(getNodeType())\r
+               {\r
+                       case C_NodeTypes.UNARY_PLUS_OPERATOR_NODE:\r
+                               operatorType = UNARY_PLUS;\r
+                               break;\r
+                       case C_NodeTypes.UNARY_MINUS_OPERATOR_NODE:\r
+                               operatorType = UNARY_MINUS;\r
+                               break;\r
+                       case C_NodeTypes.SQRT_OPERATOR_NODE:\r
+                               operatorType = SQRT;\r
+                               break;\r
+                       case C_NodeTypes.ABSOLUTE_OPERATOR_NODE:\r
+                               operatorType = ABSOLUTE;\r
+                               break;\r
+                       default:\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.THROWASSERT("init for UnaryArithmeticOperator called with wrong nodeType = " + getNodeType());\r
+                               }\r
+                           break;\r
+               }\r
+               init(operand, UNARY_OPERATORS[this.operatorType], \r
+                               UNARY_METHODS[this.operatorType]);\r
+       }\r
+    \r
+    /**\r
+     * Unary + and - require their type to be set if\r
+     * they wrap another node (e.g. a parameter) that\r
+     * requires type from its context.\r
+     * @see ValueNode#requiresTypeFromContext\r
+     */\r
+    public boolean requiresTypeFromContext()\r
+    {\r
+        if (operatorType == UNARY_PLUS || operatorType == UNARY_MINUS)\r
+            return operand.requiresTypeFromContext(); \r
+        return false;\r
+    }\r
+    \r
+    /**\r
+     * A +? or a -? is considered a parameter.\r
+     */\r
+    public boolean isParameterNode()\r
+    {\r
+        if (operatorType == UNARY_PLUS || operatorType == UNARY_MINUS)\r
+            return operand.isParameterNode(); \r
+        return false;\r
+    }\r
+\r
+       /**\r
+     * For SQRT and ABS the parameter becomes a DOUBLE.\r
+     * For unary + and - no change is made to the\r
+     * underlying node. Once this node's type is set\r
+     * using setType, then the underlying node will have\r
+     * its type set.\r
+        *\r
+        * @exception StandardException         Thrown if ?  parameter doesn't\r
+        *                                                                      have a type bound to it yet.\r
+        *                                                                      ? parameter where it isn't allowed.\r
+        */\r
+\r
+       void bindParameter() throws StandardException\r
+       {\r
+               if (operatorType == SQRT || operatorType == ABSOLUTE)\r
+               {\r
+                       operand.setType(\r
+                               new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), true));\r
+            return;\r
+               }\r
+        \r
+               //Derby-582 add support for dynamic parameter for unary plus and minus\r
+               if (operatorType == UNARY_MINUS || operatorType == UNARY_PLUS) \r
+                       return;\r
+        \r
+        // Not expected to get here since only the above types are supported\r
+        // but the super-class method will throw an exception\r
+        super.bindParameter();\r
+        \r
+       }\r
+    \r
+       /**\r
+        * Bind this operator\r
+        *\r
+        * @param fromList                      The query's FROM list\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(\r
+               FromList        fromList, SubqueryList subqueryList,\r
+               Vector  aggregateVector)\r
+                       throws StandardException\r
+       {\r
+               //Return with no binding, if the type of unary minus/plus parameter is not set yet.\r
+               if (operand.requiresTypeFromContext() && ((operatorType == UNARY_PLUS || operatorType == UNARY_MINUS))\r
+                               && operand.getTypeServices() == null)\r
+                               return this;\r
+\r
+               bindOperand(fromList, subqueryList,\r
+                               aggregateVector);\r
+\r
+               if (operatorType == SQRT || operatorType == ABSOLUTE)\r
+               {\r
+                       bindSQRTABS();\r
+               }\r
+               else if (operatorType == UNARY_PLUS || operatorType == UNARY_MINUS)\r
+               {\r
+            checkOperandIsNumeric(operand.getTypeId());\r
+               }\r
+               /*\r
+               ** The result type of a +, -, SQRT, ABS is the same as its operand.\r
+               */\r
+               super.setType(operand.getTypeServices());\r
+               return this;\r
+       }\r
+    \r
+    /**\r
+     * Only called for Unary +/-.\r
+     *\r
+     */\r
+       private void checkOperandIsNumeric(TypeId operandType) throws StandardException\r
+       {\r
+           if (!operandType.isNumericTypeId())\r
+           {\r
+               throw StandardException.newException(\r
+                    SQLState.LANG_UNARY_ARITHMETIC_BAD_TYPE, \r
+                       (operatorType == UNARY_PLUS) ? "+" : "-", \r
+                               operandType.getSQLTypeName());\r
+           }\r
+           \r
+       }\r
+\r
+       /**\r
+        * Do code generation for this unary plus operator\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class we're generating\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {\r
+               /* Unary + doesn't do anything.  Just return the operand */\r
+               if (operatorType == UNARY_PLUS)\r
+                       operand.generateExpression(acb, mb);\r
+               else\r
+                       super.generateExpression(acb, mb);\r
+       }\r
+       /**\r
+        * Bind SQRT or ABS\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       private void bindSQRTABS()\r
+                       throws StandardException\r
+       {\r
+               TypeId  operandType;\r
+               int     jdbcType;\r
+\r
+               /*\r
+               ** Check the type of the operand \r
+               */\r
+               operandType = operand.getTypeId();\r
+\r
+               /*\r
+                * If the operand is not a build-in type, generate a bound conversion\r
+                * tree to build-in types.\r
+                */\r
+               if (operandType.userType() )\r
+               {\r
+                       operand = operand.genSQLJavaSQLTree();\r
+               }\r
+               /* DB2 doesn't cast string types to numeric types for numeric functions  */\r
+\r
+               jdbcType = operandType.getJDBCTypeId();\r
+\r
+               /* Both SQRT and ABS are only allowed on numeric types */\r
+               if (!operandType.isNumericTypeId())\r
+                       throw StandardException.newException(\r
+                                               SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, \r
+                                               getOperatorString(), operandType.getSQLTypeName());\r
+\r
+               /* For SQRT, if operand is not a DOUBLE, convert it to DOUBLE */\r
+               if (operatorType == SQRT && jdbcType != Types.DOUBLE)\r
+               {\r
+                       operand = (ValueNode) getNodeFactory().getNode(\r
+                                       C_NodeTypes.CAST_NODE,\r
+                                       operand,\r
+                                       new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), true),\r
+                                       getContextManager());\r
+                       ((CastNode) operand).bindCastNodeOnly();\r
+               }\r
+       }\r
+\r
+       /** We are overwriting this method here because for -?/+?, we now know\r
+       the type of these dynamic parameters and hence we can do the parameter\r
+       binding. The setType method will call the binding code after setting\r
+       the type of the parameter*/\r
+       public void setType(DataTypeDescriptor descriptor) throws StandardException\r
+       {\r
+        if (operand.requiresTypeFromContext() && operand.getTypeServices() == null)\r
+        {\r
+            checkOperandIsNumeric(descriptor.getTypeId());\r
+                   operand.setType(descriptor);\r
+        }\r
+               super.setType(descriptor);\r
+       }\r
+}\r