Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / BinaryLogicalOperatorNode.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/BinaryLogicalOperatorNode.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/BinaryLogicalOperatorNode.java
new file mode 100644 (file)
index 0000000..1c29e75
--- /dev/null
@@ -0,0 +1,239 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.BinaryLogicalOperatorNode\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.BooleanDataValue;\r
+import org.apache.derby.iapi.types.TypeId;\r
+\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\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
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+\r
+import java.lang.reflect.Modifier;\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.util.Vector;\r
+\r
+abstract class BinaryLogicalOperatorNode extends BinaryOperatorNode\r
+{\r
+       boolean shortCircuitValue;\r
+\r
+       /**\r
+        * Initializer for a BinaryLogicalOperatorNode\r
+        *\r
+        * @param leftOperand   The left operand of the comparison\r
+        * @param rightOperand  The right operand of the comparison\r
+        * @param methodName    The name of the method to call in the generated\r
+        *                                              class.  In this case, it's actually an operator\r
+        *                                              name.\r
+        */\r
+\r
+       public void init(\r
+                               Object  leftOperand,\r
+                               Object  rightOperand,\r
+                               Object          methodName)\r
+       {\r
+               /* For logical operators, the operator and method names are the same */\r
+               super.init(leftOperand, rightOperand, methodName, methodName,\r
+                               ClassName.BooleanDataValue, ClassName.BooleanDataValue);\r
+       }\r
+\r
+       /**\r
+        * Bind this logical operator.  All that has to be done for binding\r
+        * a logical operator is to bind the operands, check that both operands\r
+        * are BooleanDataValue, and set the result type to BooleanDataValue.\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
+               //following is to check if we have something like "? AND 1=1" or "2>1 OR ?" \r
+               if (leftOperand.isParameterNode() || rightOperand.isParameterNode())\r
+                       throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" );\r
+\r
+               super.bindExpression(fromList, subqueryList, aggregateVector);\r
+\r
+               return this;\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 (leftOperand.verifyEliminateNots() &&\r
+                                       rightOperand.verifyEliminateNots());\r
+               }\r
+               else\r
+               {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Do code generation for this logical binary operator.\r
+        * This is used for AND and OR. the IsNode extends this class but\r
+        * overrides generateExpression.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class we're generating\r
+        * @param mb    The method the code to place the code\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+               throws StandardException\r
+       {               \r
+               /*\r
+               ** This generates the following code:\r
+               **\r
+               ** (<leftOperand>.equals(shortCircuitValue) ?\r
+               **       <leftOperand> :\r
+               **   <leftOperand>.<and/or>(<rightOperand>)\r
+               **\r
+               ** The ?: operator accomplishes the short-circuiting.  We save the\r
+               ** value of the left operand on the stack so we don't have to evaluate\r
+               ** it twice.\r
+               **\r
+               ** The BooleanDataValue.{and,or} methods return an immutable BooleanDataValue\r
+               ** and an immutable BooleanDataValue is returned by this generated code in\r
+               ** the short circuit case.\r
+               */\r
+\r
+               /*\r
+               ** See whether the left operand equals the short-circuit value.\r
+               ** Generated code is:\r
+               **              .equals(shortCircuitValue)\r
+               */\r
+\r
+               leftOperand.generateExpression(acb, mb);\r
+               // stack - left\r
+\r
+               // put an extra left of the stack for potential\r
+               // use in the else clause.\r
+               mb.dup();\r
+               // stack - left, left\r
+               mb.push(shortCircuitValue);\r
+               // stack - left, left, shortcircuit\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "equals", "boolean", 1);\r
+               // stack left, result\r
+\r
+               /*\r
+               ** Generate the if expression.  This is what accomplishes\r
+               ** short-circuiting.\r
+               **\r
+               ** Generated code is:\r
+               **\r
+               **              <test for short circuiting> ?\r
+               **                      <call to BooleanDataValue.getImmutable> : <call to operator method>\r
+               **\r
+               ** For AND short circuiting shortcircuit value will be false, so that\r
+               ** if left is false, no need to evaluate the right and the result will be false.\r
+               **\r
+               ** For OR short circuiting shortcircuit value will be true, so that\r
+               ** if left is true, no need to to evaluate the right and the result will be true.\r
+               **\r
+               ** In both cases the result is the same as the left operand.\r
+               **\r
+               ** TODO: Could short circuit when the left value is NULL as well. Then\r
+               ** the result would be NULL in either case and still equal to the left value.\r
+               ** This would require a different check on the conditional.\r
+               */\r
+\r
+               mb.conditionalIf();\r
+               \r
+               // stack: left\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getImmutable",\r
+                               ClassName.BooleanDataValue, 0);\r
+               \r
+               // stack: result (matching left)\r
+\r
+               mb.startElseCode();\r
+\r
+               /*\r
+               ** Generate the return value if the left operand does not equal the\r
+               ** short-circuit value.  This is the call to "and" or "or".\r
+               **\r
+               ** Generated code is:\r
+               **\r
+               **      <fieldx>.<methodName>(<rightOperand>)\r
+               */\r
+\r
+               // stack: left\r
+\r
+               rightOperand.generateExpression(acb, mb);\r
+\r
+               // stack: left, right\r
+               mb.upCast(ClassName.BooleanDataValue);\r
+\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, ClassName.BooleanDataValue, 1);\r
+               // stack: result(left op right)\r
+\r
+               mb.completeConditional();\r
+               //       stack: result\r
+\r
+       }\r
+\r
+       DataTypeDescriptor resolveLogicalBinaryOperator(\r
+                                                               DataTypeDescriptor leftType,\r
+                                                               DataTypeDescriptor rightType)\r
+                                                       throws StandardException\r
+       {\r
+               if ( ( ! (leftType.getTypeId().isBooleanTypeId()) ) ||\r
+                        ( ! (rightType.getTypeId().isBooleanTypeId()) ) )\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_BINARY_LOGICAL_NON_BOOLEAN);\r
+               }\r
+\r
+               return leftType.getNullabilityType(\r
+                                       leftType.isNullable() || rightType.isNullable());\r
+       }\r
+}\r