KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.DistinctNode
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.compile.Optimizable;
25 import org.apache.derby.iapi.sql.compile.OptimizableList;
26 import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
27 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
28 import org.apache.derby.iapi.sql.compile.Optimizer;
29 import org.apache.derby.iapi.sql.compile.CostEstimate;
30 import org.apache.derby.iapi.sql.compile.Visitable;
31 import org.apache.derby.iapi.sql.compile.Visitor;
32 import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
33 import org.apache.derby.iapi.sql.compile.RowOrdering;
34 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
35
36 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
37 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
38
39 import org.apache.derby.iapi.sql.Activation;
40 import org.apache.derby.iapi.sql.ResultSet;
41 import org.apache.derby.iapi.reference.ClassName;
42
43 import org.apache.derby.iapi.services.classfile.VMOpcode;
44
45 import org.apache.derby.iapi.error.StandardException;
46
47 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
48
49 import org.apache.derby.iapi.services.compiler.MethodBuilder;
50
51 import org.apache.derby.iapi.services.sanity.SanityManager;
52
53 import org.apache.derby.iapi.util.JBitSet;
54
55
56 import java.util.Properties JavaDoc;
57 import java.util.Vector JavaDoc;
58
59 /**
60  * A DistinctNode represents a result set for a disinct operation
61  * on a select. It has the same description as its input result set.
62  *
63  * For the most part, it simply delegates operations to its childResultSet,
64  * which is currently expected to be a ProjectRestrictResultSet generated
65  * for a SelectNode.
66  *
67  * NOTE: A DistinctNode extends FromTable since it can exist in a FromList.
68  *
69  * @author ames
70  */

71 public class DistinctNode extends SingleChildResultSetNode
72 {
73     boolean inSortedOrder;
74
75     /**
76      * Initializer for a DistinctNode.
77      *
78      * @param childResult The child ResultSetNode
79      * @param inSortedOrder Whether or not the child ResultSetNode returns its
80      * output in sorted order.
81      * @param tableProperties Properties list associated with the table
82      *
83      * @exception StandardException Thrown on error
84      */

85     public void init(
86                         Object JavaDoc childResult,
87                         Object JavaDoc inSortedOrder,
88                         Object JavaDoc tableProperties) throws StandardException
89     {
90         super.init(childResult, tableProperties);
91
92         if (SanityManager.DEBUG)
93         {
94             if (!(childResult instanceof Optimizable))
95             {
96                 SanityManager.THROWASSERT("childResult, " + childResult.getClass().getName() +
97                     ", expected to be instanceof Optimizable");
98             }
99             if (!(childResult instanceof FromTable))
100             {
101                 SanityManager.THROWASSERT("childResult, " + childResult.getClass().getName() +
102                     ", expected to be instanceof FromTable");
103             }
104         }
105
106         ResultColumnList prRCList;
107
108         /*
109             We want our own resultColumns, which are virtual columns
110             pointing to the child result's columns.
111
112             We have to have the original object in the distinct node,
113             and give the underlying project the copy.
114          */

115
116         /* We get a shallow copy of the ResultColumnList and its
117          * ResultColumns. (Copy maintains ResultColumn.expression for now.)
118          */

119         prRCList = this.childResult.getResultColumns().copyListAndObjects();
120         resultColumns = this.childResult.getResultColumns();
121         this.childResult.setResultColumns(prRCList);
122
123         /* Replace ResultColumn.expression with new VirtualColumnNodes
124          * in the DistinctNode's RCL. (VirtualColumnNodes include
125          * pointers to source ResultSetNode, this, and source ResultColumn.)
126          */

127         resultColumns.genVirtualColumnNodes(this, prRCList);
128
129         /* Verify that we can perform a DISTINCT on the
130          * underlying tree.
131          */

132         resultColumns.verifyAllOrderable();
133
134         this.inSortedOrder = ((Boolean JavaDoc) inSortedOrder).booleanValue();
135     }
136
137     /*
138      * Optimizable interface
139      */

140
141     /**
142      * @see Optimizable#optimizeIt
143      *
144      * @exception StandardException Thrown on error
145      */

146     public CostEstimate optimizeIt(Optimizer optimizer,
147                                     OptimizablePredicateList predList,
148                                     CostEstimate outerCost,
149                                     RowOrdering rowOrdering)
150             throws StandardException
151     {
152         CostEstimate childCost =
153             ((Optimizable) childResult).optimizeIt(optimizer,
154                                     predList,
155                                     outerCost,
156                                     rowOrdering);
157
158         return super.optimizeIt(optimizer, predList, outerCost, rowOrdering);
159     }
160
161     /**
162      * @see Optimizable#estimateCost
163      *
164      * @exception StandardException Thrown on error
165      */

166     public CostEstimate estimateCost(OptimizablePredicateList predList,
167                                     ConglomerateDescriptor cd,
168                                     CostEstimate outerCost,
169                                     Optimizer optimizer,
170                                     RowOrdering rowOrdering)
171             throws StandardException
172     {
173         // RESOLVE: WE NEED TO ADD IN THE COST OF SORTING HERE, AND FIGURE
174
// OUT HOW MANY ROWS WILL BE ELIMINATED.
175
CostEstimate childCost =
176             ((Optimizable) childResult).estimateCost(predList,
177                                     cd,
178                                     outerCost,
179                                     optimizer,
180                                     rowOrdering);
181
182         costEstimate = getCostEstimate(optimizer);
183         costEstimate.setCost(childCost.getEstimatedCost(),
184                              childCost.rowCount(),
185                              childCost.singleScanRowCount());
186
187
188         /*
189         ** No need to use estimateCost on join strategy - that has already
190         ** been done on the child.
191         */

192         return costEstimate;
193     }
194
195     /**
196      * @see org.apache.derby.iapi.sql.compile.Optimizable#pushOptPredicate
197      *
198      * @exception StandardException Thrown on error
199      */

200
201     public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate)
202             throws StandardException
203     {
204         return false;
205         // return ((Optimizable) childResult).pushOptPredicate(optimizablePredicate);
206
}
207
208     /**
209      * Convert this object to a String. See comments in QueryTreeNode.java
210      * for how this should be done for tree printing.
211      *
212      * @return This object as a String
213      */

214
215     public String JavaDoc toString()
216     {
217         if (SanityManager.DEBUG)
218         {
219             return childResult.toString() + "\n" + super.toString();
220         }
221         else
222         {
223             return "";
224         }
225     }
226
227     /**
228      * Optimize this DistinctNode.
229      *
230      * @param dataDictionary The DataDictionary to use for optimization
231      * @param predicates The PredicateList to optimize. This should
232      * be a join predicate.
233      * @param outerRows The number of outer joining rows
234      *
235      * @return ResultSetNode The top of the optimized subtree
236      *
237      * @exception StandardException Thrown on error
238      */

239
240     public ResultSetNode optimize(DataDictionary dataDictionary,
241                                   PredicateList predicates,
242                                   double outerRows)
243                     throws StandardException
244     {
245         /* We need to implement this method since a PRN can appear above a
246          * SelectNode in a query tree.
247          */

248         childResult = (ProjectRestrictNode) childResult.optimize(
249                                                             dataDictionary,
250                                                             predicates,
251                                                             outerRows);
252         Optimizer optimizer = getOptimizer(
253                         (FromList) getNodeFactory().getNode(
254                             C_NodeTypes.FROM_LIST,
255                             getNodeFactory().doJoinOrderOptimization(),
256                             this,
257                             getContextManager()),
258                         predicates,
259                         dataDictionary,
260                         (RequiredRowOrdering) null);
261
262         // RESOLVE: NEED TO FACTOR IN COST OF SORTING AND FIGURE OUT HOW
263
// MANY ROWS HAVE BEEN ELIMINATED.
264
costEstimate = optimizer.newCostEstimate();
265
266         costEstimate.setCost(childResult.getCostEstimate().getEstimatedCost(),
267                              childResult.getCostEstimate().rowCount(),
268                              childResult.getCostEstimate().singleScanRowCount());
269
270         return this;
271     }
272
273     /**
274      * Return whether or not the underlying ResultSet tree
275      * is ordered on the specified columns.
276      * RESOLVE - This method currently only considers the outermost table
277      * of the query block.
278      *
279      * @param crs The specified ColumnReference[]
280      * @param permuteOrdering Whether or not the order of the CRs in the array can be permuted
281      * @param fbtVector Vector that is to be filled with the FromBaseTable
282      *
283      * @return Whether the underlying ResultSet tree
284      * is ordered on the specified column.
285      */

286     boolean isOrderedOn(ColumnReference[] crs, boolean permuteOrdering, Vector JavaDoc fbtVector)
287     {
288         /* RESOLVE - DistinctNodes are ordered on their RCLs.
289          * Walk RCL to see if cr is 1st non-constant column in the
290          * ordered result.
291          */

292         return false;
293     }
294
295     /**
296      * generate the distinct result set operating over the source
297      * resultset.
298      *
299      * @exception StandardException Thrown on error
300      */

301     public void generate(ActivationClassBuilder acb,
302                                 MethodBuilder mb)
303                             throws StandardException
304     {
305         /* Get the next ResultSet#, so we can number this ResultSetNode, its
306          * ResultColumnList and ResultSet.
307          */

308         assignResultSetNumber();
309
310         // Get the final cost estimate based on the child's cost.
311
costEstimate = childResult.getFinalCostEstimate();
312
313         /*
314             create the orderItem and stuff it in.
315          */

316         int orderItem = acb.addItem(acb.getColumnOrdering(resultColumns));
317
318         /* Generate the SortResultSet:
319          * arg1: childExpress - Expression for childResultSet
320          * arg2: distinct - true, of course
321          * arg3: isInSortedOrder - is the source result set in sorted order
322          * arg4: orderItem - entry in saved objects for the ordering
323          * arg5: rowAllocator - method to construct rows for fetching
324          * from the sort
325          * arg6: row size
326          * arg7: resultSetNumber
327          */

328
329         acb.pushGetResultSetFactoryExpression(mb);
330
331         childResult.generate(acb, mb);
332         mb.push(true);
333         mb.push(inSortedOrder);
334         mb.push(orderItem);
335         resultColumns.generateHolder(acb, mb);
336         mb.push(resultColumns.getTotalColumnSize());
337         mb.push(resultSetNumber);
338         mb.push(costEstimate.rowCount());
339         mb.push(costEstimate.getEstimatedCost());
340
341         mb.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, "getSortResultSet",
342                 ClassName.NoPutResultSet, 9);
343     }
344 }
345
Popular Tags