--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.IsNode\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
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.compile.NodeFactory;\r
+\r
+import org.apache.derby.iapi.types.BooleanDataValue;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.util.Vector;\r
+\r
+public class IsNode extends BinaryLogicalOperatorNode\r
+{\r
+ private boolean notMe; // set to true if we're to negate the sense of this node\r
+\r
+ /**\r
+ * Initializer for an IsNode\r
+ *\r
+ * @param leftOperand The left operand of the IS\r
+ * @param rightOperand The right operand of the IS\r
+ * @param notMe Whether to reverse the sense of this node.\r
+ */\r
+\r
+ public void init(\r
+ Object leftOperand,\r
+ Object rightOperand,\r
+ Object notMe )\r
+ {\r
+ // the false for shortCir\r
+ super.init(leftOperand, rightOperand, "is" );\r
+ this.notMe = ((Boolean) notMe).booleanValue();\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
+ super.bindExpression(fromList, subqueryList, aggregateVector);\r
+\r
+ leftOperand.checkIsBoolean();\r
+ rightOperand.checkIsBoolean();\r
+\r
+ setType(leftOperand.getTypeServices());\r
+\r
+ return this;\r
+ }\r
+\r
+ \r
+ /**\r
+ * Eliminate NotNodes in the current query block. We just mark whether\r
+ * this IS node is under an eliminated NOT node.\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 ) { notMe = !notMe; }\r
+\r
+ leftOperand = leftOperand.eliminateNots( false);\r
+ rightOperand = rightOperand.eliminateNots( false );\r
+\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Do the 1st step in putting child expressions into conjunctive normal\r
+ * form. This step ensures that the top level of the child expression is\r
+ * a chain of AndNodes terminated by a true BooleanConstantNode.\r
+ *\r
+ * @return The modified expression\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public ValueNode putAndsOnTop() \r
+ throws StandardException\r
+ {\r
+ leftOperand = leftOperand.putAndsOnTop();\r
+ rightOperand = rightOperand.putAndsOnTop();\r
+\r
+ return this;\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 terminated by a true BooleanConstantNode.\r
+ *\r
+ * @return Boolean which reflects validity of the tree.\r
+ */\r
+ public boolean verifyPutAndsOnTop()\r
+ {\r
+ return ( leftOperand.verifyPutAndsOnTop() && rightOperand.verifyPutAndsOnTop() );\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
+ leftOperand = leftOperand.changeToCNF(false );\r
+ rightOperand = rightOperand.changeToCNF(false );\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 ( leftOperand.verifyChangeToCNF() && rightOperand.verifyChangeToCNF() );\r
+ }\r
+\r
+\r
+ /**\r
+ * Do code generation for this logical binary 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
+ String evaluatorMethodName;\r
+\r
+ /*\r
+ ** Generate the return value. Generated code is:\r
+ **\r
+ ** <fieldLeft>.<evaluatorMethodName>(<fieldRight>)\r
+ */\r
+\r
+ if ( notMe ) { evaluatorMethodName = "isNot"; }\r
+ else { evaluatorMethodName = "is"; }\r
+\r
+ leftOperand.generateExpression(acb, mb);\r
+ rightOperand.generateExpression(acb, mb);\r
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.BooleanDataValue, evaluatorMethodName,\r
+ ClassName.BooleanDataValue, 1);\r
+ }\r
+}\r