KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.BetweenOperatorNode
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.conn.LanguageConnectionContext;
27
28 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
29
30 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
31
32 import org.apache.derby.iapi.services.compiler.MethodBuilder;
33
34 import org.apache.derby.iapi.services.sanity.SanityManager;
35
36 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
37 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
38 import org.apache.derby.iapi.sql.compile.NodeFactory;
39 import org.apache.derby.iapi.services.context.ContextManager;
40
41 /**
42  * A BetweenOperatorNode represents a BETWEEN clause. The between values are
43  * represented as a 2 element list in order to take advantage of code reuse.
44  *
45  * @author Jerry Brenner
46  */

47
48 public class BetweenOperatorNode extends BinaryListOperatorNode
49 {
50     /**
51      * Initializer for a BetweenOperatorNode
52      *
53      * @param leftOperand The left operand of the node
54      * @param betweenValues The between values in list form
55      */

56
57     public void init(Object JavaDoc leftOperand, Object JavaDoc betweenValues)
58     {
59         if (SanityManager.DEBUG)
60         {
61             ValueNodeList betweenVals = (ValueNodeList) betweenValues;
62
63             SanityManager.ASSERT(betweenVals.size() == 2,
64                 "betweenValues.size() (" +
65                 betweenVals.size() +
66                 ") is expected to be 2");
67         }
68
69         super.init(leftOperand, betweenValues, "BETWEEN", null);
70     }
71
72     /**
73      * Eliminate NotNodes in the current query block. We traverse the tree,
74      * inverting ANDs and ORs and eliminating NOTs as we go. We stop at
75      * ComparisonOperators and boolean expressions. We invert
76      * ComparisonOperators and replace boolean expressions with
77      * boolean expression = false.
78      * NOTE: Since we do not recurse under ComparisonOperators, there
79      * still could be NotNodes left in the tree.
80      *
81      * @param underNotNode Whether or not we are under a NotNode.
82      *
83      *
84      * @return The modified expression
85      *
86      * @exception StandardException Thrown on error
87      */

88     ValueNode eliminateNots(boolean underNotNode)
89                     throws StandardException
90     {
91         BinaryComparisonOperatorNode leftBCO;
92         BinaryComparisonOperatorNode rightBCO;
93         OrNode newOr;
94
95         if (SanityManager.DEBUG)
96         SanityManager.ASSERT(rightOperandList.size() == 2,
97             "rightOperandList.size() (" +
98             rightOperandList.size() +
99             ") is expected to be 2");
100
101         if (! underNotNode)
102         {
103             return this;
104         }
105
106         /* we want to convert the BETWEEN * into < OR >
107            as described below.
108         */

109
110         /* Convert:
111          * leftO between rightOList.elementAt(0) and rightOList.elementAt(1)
112          * to:
113          * leftO < rightOList.elementAt(0) or leftO > rightOList.elementAt(1)
114          * NOTE - We do the conversion here since ORs will eventually be
115          * optimizable and there's no benefit for the optimizer to see NOT BETWEEN
116          */

117
118         NodeFactory nodeFactory = getNodeFactory();
119         ContextManager cm = getContextManager();
120
121         /* leftO < rightOList.elementAt(0) */
122         leftBCO = (BinaryComparisonOperatorNode)
123                     nodeFactory.getNode(
124                                     C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE,
125                                     leftOperand,
126                                     rightOperandList.elementAt(0),
127                                     cm);
128         /* Set type info for the operator node */
129         leftBCO.bindComparisonOperator();
130
131         /* leftO > rightOList.elementAt(1) */
132         rightBCO = (BinaryComparisonOperatorNode)
133                     nodeFactory.getNode(
134                                 C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE,
135                                 leftOperand,
136                                 rightOperandList.elementAt(1),
137                                 cm);
138         /* Set type info for the operator node */
139         rightBCO.bindComparisonOperator();
140
141         /* Create and return the OR */
142         newOr = (OrNode) nodeFactory.getNode(
143                                                 C_NodeTypes.OR_NODE,
144                                                 leftBCO,
145                                                 rightBCO,
146                                                 cm);
147         newOr.postBindFixup();
148
149         /* Tell optimizer to use the between selectivity instead of >= * <= selectivities */
150         leftBCO.setBetweenSelectivity();
151         rightBCO.setBetweenSelectivity();
152
153         return newOr;
154     }
155
156     /**
157      * Preprocess an expression tree. We do a number of transformations
158      * here (including subqueries, IN lists, LIKE and BETWEEN) plus
159      * subquery flattening.
160      * NOTE: This is done before the outer ResultSetNode is preprocessed.
161      *
162      * @param numTables Number of tables in the DML Statement
163      * @param outerFromList FromList from outer query block
164      * @param outerSubqueryList SubqueryList from outer query block
165      * @param outerPredicateList PredicateList from outer query block
166      *
167      * @return The modified expression
168      *
169      * @exception StandardException Thrown on error
170      */

171     public ValueNode preprocess(int numTables,
172                                 FromList outerFromList,
173                                 SubqueryList outerSubqueryList,
174                                 PredicateList outerPredicateList)
175                     throws StandardException
176     {
177         ValueNode leftClone1;
178         ValueNode rightOperand;
179
180         /* We must 1st preprocess the component parts */
181         super.preprocess(numTables,
182                          outerFromList, outerSubqueryList,
183                          outerPredicateList);
184
185         /* This is where we do the transformation for BETWEEN to make it optimizable.
186          * c1 BETWEEN value1 AND value2 -> c1 >= value1 AND c1 <= value2
187          * This transformation is only done if the leftOperand is a ColumnReference.
188          */

189         if (!(leftOperand instanceof ColumnReference))
190         {
191             return this;
192         }
193
194         /* For some unknown reason we need to clone the leftOperand if it is
195          * a ColumnReference because reusing them in Qualifiers for a scan
196          * does not work.
197          */

198         leftClone1 = leftOperand.getClone();
199
200         /* The transformed tree has to be normalized:
201          * AND
202          * / \
203          * >= AND
204          * / \
205          * <= TRUE
206          */

207
208         NodeFactory nodeFactory = getNodeFactory();
209         ContextManager cm = getContextManager();
210
211         QueryTreeNode trueNode = nodeFactory.getNode(
212                                             C_NodeTypes.BOOLEAN_CONSTANT_NODE,
213                                             Boolean.TRUE,
214                                             cm);
215
216         /* Create the AND <= */
217         BinaryComparisonOperatorNode lessEqual =
218             (BinaryComparisonOperatorNode) nodeFactory.getNode(
219                         C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE,
220                         leftClone1,
221                         rightOperandList.elementAt(1),
222                         cm);
223
224         /* Set type info for the operator node */
225         lessEqual.bindComparisonOperator();
226
227         /* Create the AND */
228         AndNode newAnd = (AndNode) nodeFactory.getNode(
229                                                 C_NodeTypes.AND_NODE,
230                                                 lessEqual,
231                                                 trueNode,
232                                                 cm);
233         newAnd.postBindFixup();
234
235         /* Create the AND >= */
236         BinaryComparisonOperatorNode greaterEqual =
237             (BinaryComparisonOperatorNode) nodeFactory.getNode(
238                     C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE,
239                     leftOperand,
240                     rightOperandList.elementAt(0),
241                     cm);
242
243         /* Set type info for the operator node */
244         greaterEqual.bindComparisonOperator();
245
246         /* Create the AND */
247         newAnd = (AndNode) nodeFactory.getNode(
248                                                 C_NodeTypes.AND_NODE,
249                                                 greaterEqual,
250                                                 newAnd,
251                                                 cm);
252         newAnd.postBindFixup();
253
254         /* Tell optimizer to use the between selectivity instead of >= * <= selectivities */
255         lessEqual.setBetweenSelectivity();
256         greaterEqual.setBetweenSelectivity();
257
258         return newAnd;
259     }
260  
261     /**
262      * Do code generation for this BETWEEN operator.
263      *
264      * @param acb The ExpressionClassBuilder for the class we're generating
265      * @param mb The method the code to place the code
266      *
267      *
268      * @exception StandardException Thrown on error
269      */

270
271     public void generateExpression(ExpressionClassBuilder acb,
272                                             MethodBuilder mb)
273         throws StandardException
274     {
275         AndNode newAnd;
276         BinaryComparisonOperatorNode leftBCO;
277         BinaryComparisonOperatorNode rightBCO;
278
279         if (SanityManager.DEBUG)
280         SanityManager.ASSERT(rightOperandList.size() == 2,
281             "rightOperandList.size() (" +
282             rightOperandList.size() +
283             ") is expected to be 2");
284
285         /* Convert:
286          * leftO between rightOList.elementAt(0) and rightOList.elementAt(1)
287          * to:
288          * leftO >= rightOList.elementAt(0) and leftO <= rightOList.elementAt(1)
289          */

290
291         NodeFactory nodeFactory = getNodeFactory();
292         ContextManager cm = getContextManager();
293
294         /* leftO >= rightOList.elementAt(0) */
295         leftBCO = (BinaryComparisonOperatorNode)
296                     nodeFactory.getNode(
297                             C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE,
298                             leftOperand,
299                             rightOperandList.elementAt(0),
300                             cm);
301         /* Set type info for the operator node */
302         leftBCO.bindComparisonOperator();
303
304         /* leftO <= rightOList.elementAt(1) */
305         rightBCO = (BinaryComparisonOperatorNode)
306                     nodeFactory.getNode(
307                         C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE,
308                         leftOperand,
309                         rightOperandList.elementAt(1),
310                         cm);
311         /* Set type info for the operator node */
312         rightBCO.bindComparisonOperator();
313
314         /* Create and return the AND */
315         newAnd = (AndNode) nodeFactory.getNode(
316                                                 C_NodeTypes.AND_NODE,
317                                                 leftBCO,
318                                                 rightBCO,
319                                                 cm);
320         newAnd.postBindFixup();
321         newAnd.generateExpression(acb, mb);
322     }
323 }
324
Popular Tags