KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > BinaryLogicalOperatorNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.BinaryLogicalOperatorNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
25
26 import org.apache.derby.iapi.types.BooleanDataValue;
27 import org.apache.derby.iapi.types.TypeId;
28
29 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
30
31 import org.apache.derby.iapi.error.StandardException;
32 import org.apache.derby.iapi.services.compiler.MethodBuilder;
33 import org.apache.derby.iapi.services.compiler.LocalField;
34
35 import org.apache.derby.iapi.services.sanity.SanityManager;
36 import org.apache.derby.iapi.reference.ClassName;
37 import org.apache.derby.iapi.reference.SQLState;
38 import org.apache.derby.iapi.types.DataTypeDescriptor;
39
40 import java.lang.reflect.Modifier JavaDoc;
41 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
42 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
43 import org.apache.derby.iapi.services.classfile.VMOpcode;
44
45 import java.util.Vector JavaDoc;
46
47 abstract class BinaryLogicalOperatorNode extends BinaryOperatorNode
48 {
49     boolean shortCircuitValue;
50
51     /**
52      * Initializer for a BinaryLogicalOperatorNode
53      *
54      * @param leftOperand The left operand of the comparison
55      * @param rightOperand The right operand of the comparison
56      * @param methodName The name of the method to call in the generated
57      * class. In this case, it's actually an operator
58      * name.
59      */

60
61     public void init(
62                 Object JavaDoc leftOperand,
63                 Object JavaDoc rightOperand,
64                 Object JavaDoc methodName)
65     {
66         /* For logical operators, the operator and method names are the same */
67         super.init(leftOperand, rightOperand, methodName, methodName,
68                 ClassName.BooleanDataValue, ClassName.BooleanDataValue);
69     }
70
71     /**
72      * Bind this logical operator. All that has to be done for binding
73      * a logical operator is to bind the operands, check that both operands
74      * are BooleanDataValue, and set the result type to BooleanDataValue.
75      *
76      * @param fromList The query's FROM list
77      * @param subqueryList The subquery list being built as we find SubqueryNodes
78      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
79      *
80      * @return The new top of the expression tree.
81      *
82      * @exception StandardException Thrown on error
83      */

84
85     public ValueNode bindExpression(
86         FromList fromList, SubqueryList subqueryList,
87         Vector JavaDoc aggregateVector)
88             throws StandardException
89     {
90         //following is to check if we have something like "? AND 1=1" or "2>1 OR ?"
91
if (leftOperand.isParameterNode() || rightOperand.isParameterNode())
92             throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" );
93         //following 2 ifs are to check if we have something like "+? AND 1=1" or "2>1 OR -?" ie -?/+? by themselves
94
if ((leftOperand instanceof UnaryOperatorNode) &&
95                 ((UnaryOperatorNode)leftOperand).isUnaryMinusOrPlusWithParameter())
96             throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" );
97         if ((rightOperand instanceof UnaryOperatorNode) &&
98                 ((UnaryOperatorNode)rightOperand).isUnaryMinusOrPlusWithParameter())
99             throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" );
100
101         super.bindExpression(fromList, subqueryList, aggregateVector);
102
103         return this;
104     }
105
106     /**
107      * Verify that eliminateNots() did its job correctly. Verify that
108      * there are no NotNodes above the top level comparison operators
109      * and boolean expressions.
110      *
111      * @return Boolean which reflects validity of the tree.
112      */

113     boolean verifyEliminateNots()
114     {
115         if (SanityManager.ASSERT)
116         {
117             return (leftOperand.verifyEliminateNots() &&
118                     rightOperand.verifyEliminateNots());
119         }
120         else
121         {
122             return true;
123         }
124     }
125
126     /**
127      * Do code generation for this logical binary operator.
128      * This is used for AND and OR. the IsNode extends this class but
129      * overrides generateExpression.
130      *
131      * @param acb The ExpressionClassBuilder for the class we're generating
132      * @param mb The method the code to place the code
133      *
134      *
135      * @exception StandardException Thrown on error
136      */

137
138     public void generateExpression(ExpressionClassBuilder acb,
139                                             MethodBuilder mb)
140         throws StandardException
141     {
142         /*
143         ** This generates the following code:
144         **
145         ** (<leftOperand>.equals(shortCircuitValue) ?
146         ** <leftOperand> :
147         ** <leftOperand>.<and/or>(<rightOperand>)
148         **
149         ** The ?: operator accomplishes the short-circuiting. We save the
150         ** value of the left operand on the stack so we don't have to evaluate
151         ** it twice.
152         **
153         ** The BooleanDataValue.{and,or} methods return an immutable BooleanDataValue
154         ** and an immutable BooleanDataValue is returned by this generated code in
155         ** the short circuit case.
156         */

157
158         /*
159         ** See whether the left operand equals the short-circuit value.
160         ** Generated code is:
161         ** .equals(shortCircuitValue)
162         */

163
164         leftOperand.generateExpression(acb, mb);
165         // stack - left
166

167         // put an extra left of the stack for potential
168
// use in the else clause.
169
mb.dup();
170         // stack - left, left
171
mb.push(shortCircuitValue);
172         // stack - left, left, shortcircuit
173
mb.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, "equals", "boolean", 1);
174         // stack left, result
175

176         /*
177         ** Generate the if expression. This is what accomplishes
178         ** short-circuiting.
179         **
180         ** Generated code is:
181         **
182         ** <test for short circuiting> ?
183         ** <call to BooleanDataValue.getImmutable> : <call to operator method>
184         **
185         ** For AND short circuiting shortcircuit value will be false, so that
186         ** if left is false, no need to evaluate the right and the result will be false.
187         **
188         ** For OR short circuiting shortcircuit value will be true, so that
189         ** if left is true, no need to to evaluate the right and the result will be true.
190         **
191         ** In both cases the result is the same as the left operand.
192         **
193         ** TODO: Could short circuit when the left value is NULL as well. Then
194         ** the result would be NULL in either case and still equal to the left value.
195         ** This would require a different check on the conditional.
196         */

197
198         mb.conditionalIf();
199         
200         // stack: left
201
mb.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, "getImmutable",
202                 ClassName.BooleanDataValue, 0);
203         
204         // stack: result (matching left)
205

206         mb.startElseCode();
207
208         /*
209         ** Generate the return value if the left operand does not equal the
210         ** short-circuit value. This is the call to "and" or "or".
211         **
212         ** Generated code is:
213         **
214         ** <fieldx>.<methodName>(<rightOperand>)
215         */

216
217         // stack: left
218

219         rightOperand.generateExpression(acb, mb);
220
221         // stack: left, right
222
mb.upCast(ClassName.BooleanDataValue);
223
224         mb.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, methodName, ClassName.BooleanDataValue, 1);
225         // stack: result(left op right)
226

227         mb.completeConditional();
228         // stack: result
229

230     }
231
232     DataTypeDescriptor resolveLogicalBinaryOperator(
233                                 DataTypeDescriptor leftType,
234                                 DataTypeDescriptor rightType)
235                             throws StandardException
236     {
237         if ( ( ! (leftType.getTypeId().isBooleanTypeId()) ) ||
238              ( ! (rightType.getTypeId().isBooleanTypeId()) ) )
239         {
240             throw StandardException.newException(SQLState.LANG_BINARY_LOGICAL_NON_BOOLEAN);
241         }
242
243         return new DataTypeDescriptor(leftType,
244                     leftType.isNullable() || rightType.isNullable());
245     }
246 }
247
Popular Tags