KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.BinaryListOperatorNode
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.error.StandardException;
25
26 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
27
28 import org.apache.derby.iapi.reference.SQLState;
29
30 import org.apache.derby.iapi.types.DataTypeDescriptor;
31 import org.apache.derby.iapi.types.TypeId;
32 import org.apache.derby.iapi.sql.compile.Visitor;
33 import org.apache.derby.iapi.sql.compile.Visitable;
34
35 import org.apache.derby.iapi.services.sanity.SanityManager;
36
37 import org.apache.derby.iapi.store.access.Qualifier;
38
39 import org.apache.derby.iapi.util.JBitSet;
40
41 import java.util.Vector JavaDoc;
42
43 /**
44  * A BinaryListOperatorNode represents a built-in "binary" operator with a single
45  * operand on the left of the operator and a list of operands on the right.
46  * This covers operators such as IN and BETWEEN.
47  *
48  * @author Jerry Brenner
49  */

50
51 public abstract class BinaryListOperatorNode extends ValueNode
52 {
53     String JavaDoc methodName;
54     /* operator used for error messages */
55     String JavaDoc operator;
56
57     String JavaDoc leftInterfaceType;
58     String JavaDoc rightInterfaceType;
59
60     ValueNode receiver; // used in generation
61
ValueNode leftOperand;
62     ValueNodeList rightOperandList;
63
64     /**
65      * Initializer for a BinaryListOperatorNode
66      *
67      * @param leftOperand The left operand of the node
68      * @param rightOperandList The right operand list of the node
69      * @param operator String representation of operator
70      */

71
72     public void init(Object JavaDoc leftOperand, Object JavaDoc rightOperandList,
73                        Object JavaDoc operator, Object JavaDoc methodName)
74     {
75         this.leftOperand = (ValueNode) leftOperand;
76         this.rightOperandList = (ValueNodeList) rightOperandList;
77         this.operator = (String JavaDoc) operator;
78         this.methodName = (String JavaDoc) methodName;
79     }
80
81     /**
82      * Convert this object to a String. See comments in QueryTreeNode.java
83      * for how this should be done for tree printing.
84      *
85      * @return This object as a String
86      */

87
88     public String JavaDoc toString()
89     {
90         if (SanityManager.DEBUG)
91         {
92             return "operator: " + operator + "\n" +
93                    "methodName: " + methodName + "\n" +
94                 super.toString();
95         }
96         else
97         {
98             return "";
99         }
100     }
101
102     /**
103      * Prints the sub-nodes of this object. See QueryTreeNode.java for
104      * how tree printing is supposed to work.
105      *
106      * @param depth The depth of this node in the tree
107      */

108
109     public void printSubNodes(int depth)
110     {
111         if (SanityManager.DEBUG)
112         {
113             super.printSubNodes(depth);
114
115             if (leftOperand != null)
116             {
117                 printLabel(depth, "leftOperand: ");
118                 leftOperand.treePrint(depth + 1);
119             }
120
121             if (rightOperandList != null)
122             {
123                 printLabel(depth, "rightOperandList: ");
124                 rightOperandList.treePrint(depth + 1);
125             }
126         }
127     }
128
129     /**
130      * Set the clause that this node appears in.
131      *
132      * @param clause The clause that this node appears in.
133      */

134     public void setClause(int clause)
135     {
136         super.setClause(clause);
137         leftOperand.setClause(clause);
138         rightOperandList.setClause(clause);
139     }
140
141     /**
142      * Bind this expression. This means binding the sub-expressions,
143      * as well as figuring out what the return type is for this expression.
144      *
145      * @param fromList The FROM list for the query this
146      * expression is in, for binding columns.
147      * @param subqueryList The subquery list being built as we find SubqueryNodes
148      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
149      *
150      * @return The new top of the expression tree.
151      *
152      * @exception StandardException Thrown on error
153      */

154
155     public ValueNode bindExpression(
156         FromList fromList, SubqueryList subqueryList,
157         Vector JavaDoc aggregateVector)
158             throws StandardException
159     {
160         leftOperand = leftOperand.bindExpression(fromList, subqueryList, aggregateVector);
161         rightOperandList.bindExpression(fromList, subqueryList, aggregateVector);
162
163         /* Is there a ? parameter on the left? */
164         if (leftOperand.requiresTypeFromContext())
165         {
166             ValueNode rightOperand = (ValueNode) rightOperandList.elementAt(0);
167
168             /*
169             ** It's an error if both operands are all ? parameters.
170             */

171             if (rightOperandList.containsAllParameterNodes())
172             {
173                 throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS,
174                                                                     operator);
175             }
176
177             /* Set the left operand to the type of right parameter. */
178             leftOperand.setType(rightOperandList.getTypeServices());
179         }
180
181         /* Is there a ? parameter on the right? */
182         if (rightOperandList.containsParameterNode())
183         {
184             /* Set the right operand to the type of the left parameter. */
185             rightOperandList.setParameterDescriptor(leftOperand.getTypeServices());
186         }
187
188         /* If the left operand is not a built-in type, then generate a conversion
189          * tree to a built-in type.
190          */

191         if (leftOperand.getTypeId().userType())
192         {
193             leftOperand = leftOperand.genSQLJavaSQLTree();
194         }
195
196         /* Generate bound conversion trees for those elements in the rightOperandList
197          * that are not built-in types.
198          */

199         rightOperandList.genSQLJavaSQLTrees();
200
201         /* Test type compatability and set type info for this node */
202         bindComparisonOperator();
203
204         return this;
205     }
206
207     /**
208      * Test the type compatability of the operands and set the type info
209      * for this node. This method is useful both during binding and
210      * when we generate nodes within the language module outside of the parser.
211      *
212      * @exception StandardException Thrown on error
213      */

214     public void bindComparisonOperator()
215             throws StandardException
216     {
217         boolean nullableResult;
218
219         /* Can the types be compared to each other? */
220         rightOperandList.comparable(leftOperand);
221
222         /*
223         ** Set the result type of this comparison operator based on the
224         ** operands. The result type is always SQLBoolean - the only question
225         ** is whether it is nullable or not. If either the leftOperand or
226         ** any of the elements in the rightOperandList is
227         ** nullable, the result of the comparison must be nullable, too, so
228         ** we can represent the unknown truth value.
229         */

230         nullableResult = leftOperand.getTypeServices().isNullable() ||
231                             rightOperandList.isNullable();
232         setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, nullableResult));
233     }
234
235     /**
236      * Preprocess an expression tree. We do a number of transformations
237      * here (including subqueries, IN lists, LIKE and BETWEEN) plus
238      * subquery flattening.
239      * NOTE: This is done before the outer ResultSetNode is preprocessed.
240      *
241      * @param numTables Number of tables in the DML Statement
242      * @param outerFromList FromList from outer query block
243      * @param outerSubqueryList SubqueryList from outer query block
244      * @param outerPredicateList PredicateList from outer query block
245      *
246      * @return The modified expression
247      *
248      * @exception StandardException Thrown on error
249      */

250     public ValueNode preprocess(int numTables,
251                                 FromList outerFromList,
252                                 SubqueryList outerSubqueryList,
253                                 PredicateList outerPredicateList)
254                     throws StandardException
255     {
256         leftOperand = leftOperand.preprocess(numTables,
257                                              outerFromList, outerSubqueryList,
258                                              outerPredicateList);
259         rightOperandList.preprocess(numTables,
260                                     outerFromList, outerSubqueryList,
261                                     outerPredicateList);
262         return this;
263     }
264
265     /**
266      * Set the leftOperand to the specified ValueNode
267      *
268      * @param newLeftOperand The new leftOperand
269      */

270     public void setLeftOperand(ValueNode newLeftOperand)
271     {
272         leftOperand = newLeftOperand;
273     }
274
275     /**
276      * Get the leftOperand
277      *
278      * @return The current leftOperand.
279      */

280     public ValueNode getLeftOperand()
281     {
282         return leftOperand;
283     }
284
285     /**
286      * Set the rightOperandList to the specified ValueNodeList
287      *
288      * @param newRightOperandList The new rightOperandList
289      *
290      */

291     public void setRightOperandList(ValueNodeList newRightOperandList)
292     {
293         rightOperandList = newRightOperandList;
294     }
295
296     /**
297      * Get the rightOperandList
298      *
299      * @return The current rightOperandList.
300      */

301     public ValueNodeList getRightOperandList()
302     {
303         return rightOperandList;
304     }
305
306     /**
307      * Categorize this predicate. Initially, this means
308      * building a bit map of the referenced tables for each predicate.
309      * If the source of this ColumnReference (at the next underlying level)
310      * is not a ColumnReference or a VirtualColumnNode then this predicate
311      * will not be pushed down.
312      *
313      * For example, in:
314      * select * from (select 1 from s) a (x) where x = 1
315      * we will not push down x = 1.
316      * NOTE: It would be easy to handle the case of a constant, but if the
317      * inner SELECT returns an arbitrary expression, then we would have to copy
318      * that tree into the pushed predicate, and that tree could contain
319      * subqueries and method calls.
320      * RESOLVE - revisit this issue once we have views.
321      *
322      * @param referencedTabs JBitSet with bit map of referenced FromTables
323      * @param simplePredsOnly Whether or not to consider method
324      * calls, field references and conditional nodes
325      * when building bit map
326      *
327      * @return boolean Whether or not source.expression is a ColumnReference
328      * or a VirtualColumnNode.
329      * @exception StandardException Thrown on error
330      */

331     public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
332         throws StandardException
333     {
334         boolean pushable;
335         pushable = leftOperand.categorize(referencedTabs, simplePredsOnly);
336         pushable = (rightOperandList.categorize(referencedTabs, simplePredsOnly) && pushable);
337         return pushable;
338     }
339
340     /**
341      * Remap all ColumnReferences in this tree to be clones of the
342      * underlying expression.
343      *
344      * @return ValueNode The remapped expression tree.
345      *
346      * @exception StandardException Thrown on error
347      */

348     public ValueNode remapColumnReferencesToExpressions()
349         throws StandardException
350     {
351         // we need to assign back because a new object may be returned, beetle 4983
352
leftOperand = leftOperand.remapColumnReferencesToExpressions();
353         rightOperandList.remapColumnReferencesToExpressions();
354         return this;
355     }
356
357     /**
358      * Return whether or not this expression tree represents a constant expression.
359      *
360      * @return Whether or not this expression tree represents a constant expression.
361      */

362     public boolean isConstantExpression()
363     {
364         return (leftOperand.isConstantExpression() &&
365                 rightOperandList.isConstantExpression());
366     }
367
368     /** @see ValueNode#constantExpression */
369     public boolean constantExpression(PredicateList whereClause)
370     {
371         return (leftOperand.constantExpression(whereClause) &&
372                 rightOperandList.constantExpression(whereClause));
373     }
374
375     /**
376      * Return the variant type for the underlying expression.
377      * The variant type can be:
378      * VARIANT - variant within a scan
379      * (method calls and non-static field access)
380      * SCAN_INVARIANT - invariant within a scan
381      * (column references from outer tables)
382      * QUERY_INVARIANT - invariant within the life of a query
383      * CONSTANT - immutable
384      *
385      * @return The variant type for the underlying expression.
386      * @exception StandardException thrown on error
387      */

388     protected int getOrderableVariantType() throws StandardException
389     {
390         int leftType = leftOperand.getOrderableVariantType();
391         int rightType = rightOperandList.getOrderableVariantType();
392
393         return Math.min(leftType, rightType);
394     }
395
396     /**
397      * Accept a visitor, and call v.visit()
398      * on child nodes as necessary.
399      *
400      * @param v the visitor
401      *
402      * @exception StandardException on error
403      */

404     public Visitable accept(Visitor v)
405         throws StandardException
406     {
407         Visitable returnNode = v.visit(this);
408
409         if (v.skipChildren(this))
410         {
411             return returnNode;
412         }
413
414         if (leftOperand != null && !v.stopTraversal())
415         {
416             leftOperand = (ValueNode)leftOperand.accept(v);
417         }
418             
419         if (rightOperandList != null && !v.stopTraversal())
420         {
421             rightOperandList = (ValueNodeList)rightOperandList.accept(v);
422         }
423             
424         return returnNode;
425     }
426         
427         /**
428          * @inheritDoc
429          */

430     protected boolean isEquivalent(ValueNode o) throws StandardException
431     {
432         if (!isSameNodeType(o))
433         {
434             return false;
435         }
436         BinaryListOperatorNode other = (BinaryListOperatorNode)o;
437         if (!operator.equals(other.operator)
438                 || !leftOperand.isEquivalent(other.getLeftOperand()))
439         {
440             return false;
441         }
442         
443         int sz = getRightOperandList().size();
444         if (sz != other.rightOperandList.size())
445         {
446             return false;
447         }
448         for (int i = 0; i < sz; i++)
449         {
450             ValueNode e = (ValueNode)rightOperandList.elementAt(i);
451             if (!e.isEquivalent((ValueNode)other.rightOperandList.elementAt(i)))
452             {
453                 return false;
454             }
455         }
456         return true;
457     }
458 }
459
Popular Tags