001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.IsNode
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
025: import org.apache.derby.iapi.services.sanity.SanityManager;
026: import org.apache.derby.iapi.error.StandardException;
027:
028: import org.apache.derby.iapi.sql.compile.NodeFactory;
029:
030: import org.apache.derby.iapi.types.BooleanDataValue;
031:
032: import org.apache.derby.iapi.services.compiler.MethodBuilder;
033:
034: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
035: import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
036: import org.apache.derby.iapi.reference.ClassName;
037: import org.apache.derby.iapi.services.classfile.VMOpcode;
038:
039: import java.lang.reflect.Modifier;
040:
041: import java.util.Vector;
042:
043: public class IsNode extends BinaryLogicalOperatorNode {
044: private boolean notMe; // set to true if we're to negate the sense of this node
045:
046: /**
047: * Initializer for an IsNode
048: *
049: * @param leftOperand The left operand of the IS
050: * @param rightOperand The right operand of the IS
051: * @param notMe Whether to reverse the sense of this node.
052: */
053:
054: public void init(Object leftOperand, Object rightOperand,
055: Object notMe) {
056: // the false for shortCir
057: super .init(leftOperand, rightOperand, "is");
058: this .notMe = ((Boolean) notMe).booleanValue();
059: }
060:
061: /**
062: * Bind this logical operator. All that has to be done for binding
063: * a logical operator is to bind the operands, check that both operands
064: * are BooleanDataValue, and set the result type to BooleanDataValue.
065: *
066: * @param fromList The query's FROM list
067: * @param subqueryList The subquery list being built as we find SubqueryNodes
068: * @param aggregateVector The aggregate vector being built as we find AggregateNodes
069: *
070: * @return The new top of the expression tree.
071: *
072: * @exception StandardException Thrown on error
073: */
074:
075: public ValueNode bindExpression(FromList fromList,
076: SubqueryList subqueryList, Vector aggregateVector)
077: throws StandardException {
078: super .bindExpression(fromList, subqueryList, aggregateVector);
079:
080: leftOperand.checkIsBoolean();
081: rightOperand.checkIsBoolean();
082:
083: setType(leftOperand.getTypeServices());
084:
085: return this ;
086: }
087:
088: /**
089: * Eliminate NotNodes in the current query block. We just mark whether
090: * this IS node is under an eliminated NOT node.
091: *
092: * @param underNotNode Whether or not we are under a NotNode.
093: *
094: *
095: * @return The modified expression
096: *
097: * @exception StandardException Thrown on error
098: */
099: ValueNode eliminateNots(boolean underNotNode)
100: throws StandardException {
101: if (underNotNode) {
102: notMe = !notMe;
103: }
104:
105: leftOperand = leftOperand.eliminateNots(false);
106: rightOperand = rightOperand.eliminateNots(false);
107:
108: return this ;
109: }
110:
111: /**
112: * Do the 1st step in putting child expressions into conjunctive normal
113: * form. This step ensures that the top level of the child expression is
114: * a chain of AndNodes terminated by a true BooleanConstantNode.
115: *
116: * @return The modified expression
117: *
118: * @exception StandardException Thrown on error
119: */
120: public ValueNode putAndsOnTop() throws StandardException {
121: leftOperand = leftOperand.putAndsOnTop();
122: rightOperand = rightOperand.putAndsOnTop();
123:
124: return this ;
125: }
126:
127: /**
128: * Verify that putAndsOnTop() did its job correctly. Verify that the top level
129: * of the expression is a chain of AndNodes terminated by a true BooleanConstantNode.
130: *
131: * @return Boolean which reflects validity of the tree.
132: */
133: public boolean verifyPutAndsOnTop() {
134: return (leftOperand.verifyPutAndsOnTop() && rightOperand
135: .verifyPutAndsOnTop());
136: }
137:
138: /**
139: * Finish putting an expression into conjunctive normal
140: * form. An expression tree in conjunctive normal form meets
141: * the following criteria:
142: * o If the expression tree is not null,
143: * the top level will be a chain of AndNodes terminating
144: * in a true BooleanConstantNode.
145: * o The left child of an AndNode will never be an AndNode.
146: * o Any right-linked chain that includes an AndNode will
147: * be entirely composed of AndNodes terminated by a true BooleanConstantNode.
148: * o The left child of an OrNode will never be an OrNode.
149: * o Any right-linked chain that includes an OrNode will
150: * be entirely composed of OrNodes terminated by a false BooleanConstantNode.
151: * o ValueNodes other than AndNodes and OrNodes are considered
152: * leaf nodes for purposes of expression normalization.
153: * In other words, we won't do any normalization under
154: * those nodes.
155: *
156: * In addition, we track whether or not we are under a top level AndNode.
157: * SubqueryNodes need to know this for subquery flattening.
158: *
159: * @param underTopAndNode Whether or not we are under a top level AndNode.
160: *
161: *
162: * @return The modified expression
163: *
164: * @exception StandardException Thrown on error
165: */
166: public ValueNode changeToCNF(boolean underTopAndNode)
167: throws StandardException {
168: leftOperand = leftOperand.changeToCNF(false);
169: rightOperand = rightOperand.changeToCNF(false);
170:
171: return this ;
172: }
173:
174: /**
175: * Verify that changeToCNF() did its job correctly. Verify that:
176: * o AndNode - rightOperand is not instanceof OrNode
177: * leftOperand is not instanceof AndNode
178: * o OrNode - rightOperand is not instanceof AndNode
179: * leftOperand is not instanceof OrNode
180: *
181: * @return Boolean which reflects validity of the tree.
182: */
183: public boolean verifyChangeToCNF() {
184: return (leftOperand.verifyChangeToCNF() && rightOperand
185: .verifyChangeToCNF());
186: }
187:
188: /**
189: * Do code generation for this logical binary operator.
190: *
191: * @param acb The ExpressionClassBuilder for the class we're generating
192: * @param mb the method the expression will go into
193: *
194: * @exception StandardException Thrown on error
195: */
196:
197: public void generateExpression(ExpressionClassBuilder acb,
198: MethodBuilder mb) throws StandardException {
199: String evaluatorMethodName;
200:
201: /*
202: ** Generate the return value. Generated code is:
203: **
204: ** <fieldLeft>.<evaluatorMethodName>(<fieldRight>)
205: */
206:
207: if (notMe) {
208: evaluatorMethodName = "isNot";
209: } else {
210: evaluatorMethodName = "is";
211: }
212:
213: leftOperand.generateExpression(acb, mb);
214: rightOperand.generateExpression(acb, mb);
215: mb.callMethod(VMOpcode.INVOKEINTERFACE,
216: ClassName.BooleanDataValue, evaluatorMethodName,
217: ClassName.BooleanDataValue, 1);
218: }
219: }
|