KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > daffodilwoods > daffodildb > server > sql99 > dql > plan > table > GroupByPlan


1 package com.daffodilwoods.daffodildb.server.sql99.dql.plan.table;
2
3 import java.util.*;
4
5 import com.daffodilwoods.daffodildb.client.*;
6 import com.daffodilwoods.daffodildb.server.datasystem.indexsystem.*;
7 import com.daffodilwoods.daffodildb.server.serversystem.*;
8 import com.daffodilwoods.daffodildb.server.sql99.common.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.common.*;
10 import com.daffodilwoods.daffodildb.server.sql99.dql.execution.*;
11 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
12 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.order.*;
13 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.table.*;
14 import com.daffodilwoods.daffodildb.server.sql99.dql.listenerevents.*;
15 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.*;
16 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.*;
17 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
18 import com.daffodilwoods.database.resource.*;
19 import com.daffodilwoods.database.sqlinitiator.*;
20 import java.util.*;
21 import com.daffodilwoods.daffodildb.utils.byteconverter.CbCUsffWbmvfIboemfs;
22 import com.daffodilwoods.database.utility.P;
23
24
25 /**
26  * GroupByPlan is a plan to obtain the resultset in which each row represents a
27  * group of the same values of group by columns. The resultset provided by this
28  * plan also provides the value of aggregate columns for each group. If only
29  * aggregates are present without group by clause, then all the rows belong to
30  * one same group.
31  * <p>Title: </p>
32  * <p>Description: </p>
33  * <p>Copyright: Copyright (c) 2003</p>
34  * <p>Company: </p>
35  * @author unascribed
36  * @version 1.0
37  */

38
39 public class GroupByPlan extends PlanExceptionAbstract implements TableExpressionConstants, CostFactorConstants, SimpleConstants {
40
41    /**
42     * Represents the underlying plan on whose resultset, group by will be applied.
43     */

44
45    private _TablePlan tPlan; // UnderLying TablePlan
46

47    /**
48     * Represents the group by columns.
49     */

50
51    private GroupByCondition groupByCondition; // Grouping Condition ie Select OrdersId from Orders group by OrderId will have group by clause as of OrderId
52

53    /**
54     * Represents the order which will be applied on the resultset of groupby.
55     */

56
57    private _Order order; // Order to be solved after grouping
58

59    /**
60     * Represents the aggregate columns.
61     */

62
63    private ColumnDetails aggregateColumns[]; // aggregateColumns like max(A)
64

65    /**
66     * Represents the condition which will be solved on the resultset of groupby.
67     */

68
69    private booleanvalueexpression aggregateCondition; // Aggregate condition to be solved over this GroupByPlan
70

71    /**
72     * boolean variable to indicate whether cost is calculated for this plan or
73     * not.
74     */

75
76    private boolean costCalculated;
77
78    /**
79     * boolean variable to indicate whether aggregate columns can be solved with
80     * the help of index.
81     */

82
83    private boolean indexUsedInAggregate;
84
85    private _Reference[] havinClauseUnderlyingReferences;
86
87    public GroupByPlan(_TablePlan tPlan0, GroupByCondition groupByCondition0, _Order order0, ColumnDetails[] aggregateColumnDetails0, booleanvalueexpression aggregateCondition0, boolean indexUsedInAggregate0,_Reference[] underlyingRef) throws DException {
88       aggregateCondition = aggregateCondition0;
89       tPlan = tPlan0;
90       groupByCondition = groupByCondition0;
91       order = order0;
92       aggregateColumns = aggregateColumnDetails0;
93       indexUsedInAggregate = indexUsedInAggregate0;
94
95       havinClauseUnderlyingReferences=underlyingRef;
96    }
97
98    /**
99     * Returns the type of plan.
100     * @return
101     * @throws DException
102     */

103
104    public int getType() throws DException {
105       return TableExpressionConstants.GROUPBYPLAN;
106    }
107
108    /**
109     * Returns the cost for applying group by. Resultant Cost includes the cost
110     * of underlying plan as well as cost of solving group on the resultset
111     * obtained from underlying plan.
112     * @param session
113     * @return
114     * @throws DException
115     */

116
117    public double getCost(_ServerSession session) throws DException {
118       costCalculated = true;
119       return tPlan.getCost(session) * (100.0 + CostFactorConstants.GROUP) / 100;
120    }
121
122    /**
123     * Returns the estimated number of rows for the resultset obtained from this
124     * plan.
125     * @param serverSession
126     * @return
127     * @throws DException
128     */

129
130    public long getRowCount(_ServerSession serverSession) throws DException {
131       return tPlan.getRowCount(serverSession) * GROUPROWREDUCED;
132    }
133
134    /**
135     * It allows user to obtain group by resultset on the passed resultset. Also
136     * if there is any order present, which will be applied on groupby, then in
137     * this case an sortedResultset will be made on groupby resultset.
138     * @param session
139     * @param iterator
140     * @return
141     * @throws DException
142     */

143
144    private _Iterator execute(_ServerSession session, _Iterator iterator) throws DException {
145       iterator = createGroupByIterator(session, iterator);
146       return createTemporaryIndexIterator(session, iterator);
147    }
148
149    /**
150     * Creates the Sorted resultset on the passed resultset.
151     * @param iterator
152     * @return TemporaryIndexWrapperIterator.
153     * @throws DException
154     */

155    private _Iterator createTemporaryIndexIterator(_ServerSession session, _Iterator iterator) throws DException {
156       if (order != null) {
157          TemporaryIndexIterator tempIndex = null;
158          if (session.getType() == IteratorConstants.UPDATABLE) {
159             _KeyColumnInformation[] keyColumns = getChangeKeyColumns(getKeyColumnInformation(order), iterator.getKeyColumnInformations());
160             return GeneralPurposeStaticClass.getTemporaryIndexIterator(iterator, tPlan, session, order, keyColumns);
161          }
162          _Reference[] references = order.getReferences(getTableDetails());
163          VariableValues variableValues = new VariableValues(references, session);
164          CbCUsffWbmvfIboemfs tempHandler = new TempIndexHandler(iterator);
165          variableValues.setIterator(iterator);
166          iterator = session.getIndexedIterator(iterator,new ExpressionOrderValues( GeneralPurposeStaticClass.getJoinOrdered(order,iterator.getDefaultOrder() ) ,variableValues),tempHandler) ;
167          return new TemporaryIndexWrapperIterator(iterator,iterator);
168      }
169      return iterator;
170    }
171
172    /**
173     * Returns the resultset for solving groupby and aggregates present in this
174     * plan. If only aggregates are present, then it is checked whether index can
175     * be used to solve that aggregate or not. If index can be used then a
176     * resultset, which can use index in solving aggregate, is formed. otherwise
177     * resultset for computing aggregate function sequentially is formed.
178     * If group by clause is present, then a resultset which is capable of
179     * solving groupby as well as aggregate functions is formed.
180     * @param session
181     * @param iterator
182     * @return
183     * @throws DException
184     */

185
186    private _Iterator createGroupByIterator(_ServerSession session, _Iterator iterator) throws DException {
187       if (groupByCondition != null) {
188          groupByCondition.setIterator(iterator);
189          iterator = new GroupByIterator(iterator, groupByCondition, aggregateColumns,havinClauseUnderlyingReferences,session);
190       } else {
191          iterator = indexUsedInAggregate ? (_Iterator)new MaxMinIterator(iterator, aggregateColumns) :
192              new AggregateGroupByIterator(iterator, aggregateColumns,session);
193       }
194       iterator = solveCondition(session, iterator);
195
196       _Reference[] orderRef=order==null?null:order.getReferences(tPlan.getTableDetails());
197       /* DONE by vibha on 22-10-2004 to sove bug no */
198       if(orderRef !=null)
199        for (int i = 0; i < orderRef.length; i++) {
200        if(orderRef[i].getReferenceType() == SimpleConstants.VARIABLECOLUMN){
201          break;
202        }
203        havinClauseUnderlyingReferences=GeneralPurposeStaticClass.getJointReferences(havinClauseUnderlyingReferences,orderRef);
204      }
205       if (havinClauseUnderlyingReferences != null )
206         iterator.setSpecificUnderlyingReferences(havinClauseUnderlyingReferences);
207
208
209       return iterator;
210    }
211
212    /**
213     * Returns the resultset for condition(if any) which is solvable on resultset
214     * of groupby.
215     * @param session
216     * @param iterator
217     * @return
218     * @throws DException
219     */

220
221    private _Iterator solveCondition(_ServerSession session, _Iterator iterator) throws DException {
222       if (aggregateCondition != null) {
223          return getNonIndexedFilteredIteratorWithSubQuery(iterator, session, aggregateCondition);
224       }
225       return iterator;
226    }
227
228    /**
229     * It allows user to obtain group by resultset on underlying resultset.
230     * Also if there is any order present, which will be applied on groupby, then
231     * in this case an sortedResultset will be made on groupby resultset.
232     * @param session
233     * @return
234     * @throws DException
235     */

236
237    public _Iterator execute(_ServerSession session) throws DException {
238       if (!costCalculated) {
239          getCost(session);
240       }
241       _Iterator iterator = tPlan.execute(session);
242       return execute(session, iterator);
243    }
244
245    /**
246     * Returns order by columns as key columns. It is required when updatable
247     * resultset is used. It is currently not in use.
248     * @param order
249     * @return
250     * @throws DException
251     */

252
253    private _KeyColumnInformation[] getKeyColumnInformation(_Order order) throws DException {
254       boolean[] orders = order.getOrderOfColumns();
255       ColumnDetails[] columnDetails = order.getKeyColumnDetails();
256       int len = columnDetails.length;
257       _KeyColumnInformation[] columnInformations = new _KeyColumnInformation[len];
258       for (int i = 0; i < len; i++) {
259          columnInformations[i] = new TableKeyColumnInformation(columnDetails[i], orders[i]);
260          columnInformations[i].setTableDetails(columnDetails[i].getTableDetails());
261       }
262       return columnInformations;
263    }
264
265    /**
266     * Returns only those key columns which are part of order by columns. It is
267     * required when updatable resultset is used. It is currently not in use.
268     * @param orderColumnDetails
269     * @param keyColumns
270     * @return
271     * @throws DException
272     */

273
274    private _KeyColumnInformation[] getChangeKeyColumns(_KeyColumnInformation[] orderColumnDetails, _KeyColumnInformation[] keyColumns) throws DException {
275       TreeSet set = new TreeSet(new Comparator() {
276          public int compare(Object JavaDoc obj1, Object JavaDoc obj2) {
277             _KeyColumnInformation first = (_KeyColumnInformation) obj1;
278             _KeyColumnInformation second = (_KeyColumnInformation) obj2;
279             try {
280                return first.getColumnDetails() == second.getColumnDetails() ? 0 : -1;
281             } catch (DException ex) {
282                throw new DRuntimeException("Dump Call", null);
283             }
284          }
285       });
286       for (int i = 0, length = orderColumnDetails.length; i < length; i++) {
287          set.add(orderColumnDetails[i]);
288       }
289       for (int i = 0, length = keyColumns.length; i < length; i++) {
290          set.add(keyColumns[i]);
291       }
292       return (_KeyColumnInformation[]) set.toArray(new _KeyColumnInformation[set.size()]);
293    }
294
295    /**
296     * Returns the order which will be solvable on resultset of groupby.
297     * @return
298     * @throws DException
299     */

300
301    public _Order getOrder() throws DException {
302      return order;
303   }
304
305   /**
306    * It allows user to obtain group by resultset on underlying resultset.
307    * Also if there is any order present, which will be applied on groupby, then
308    * in this case an sortedResultset will be made on groupby resultset.
309    * As the passed condition will be solved by underlying plan, so we only need
310    * to obtain underlying resultset with condition.
311    * @param session
312    * @param condition
313    * @return
314    * @throws DException
315    */

316
317   public _Iterator execute(_ServerSession session, booleanvalueexpression condition) throws DException {
318      _Iterator iterator = tPlan.execute(session, condition);
319      return execute(session, iterator);
320   }
321
322   /**
323    * Returns the estimated number of rows for the resultset obtained from this
324    * plan.
325    * @param serverSession
326    * @return
327    * @throws DException
328    */

329
330   public long getEstimatedRows(booleanvalueexpression conditionArg, long estimatedRowCount, _ServerSession serverSession) throws DException {
331      return conditionArg.getEstimatedRows(getRowCount(serverSession));
332   }
333
334   /**
335    * Calculates the cost of solving group by on the underlying plan on which
336    * passed condition will be applied.
337    * @param session
338    * @param condition
339    * @param estimatedRows
340    * @return
341    * @throws DException
342    */

343
344   public double getCost(_ServerSession session, booleanvalueexpression condition, long estimatedRows) throws DException {
345      return tPlan.getCost(session, condition, estimatedRows) * CostFactorConstants.GROUP;
346   }
347
348   public String JavaDoc toString() {
349      String JavaDoc str = "GROUPBYPLAN[";
350      str += " TPLAN [" + tPlan + "]";
351      str += " AGGREGATECONDITION [" + aggregateCondition + "]";
352      str += "]";
353      return str;
354   }
355
356   public String JavaDoc getVerifier() throws DException {
357      StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
358      inc();
359      buffer.append(tabW("[ GROUPBY_PLAN ]"));
360      buffer.append("\n" + tPlan.getVerifier());
361      inc();
362      buffer.append(tab("[GroupByCondition = \"" + groupByCondition + "\"]"));
363      buffer.append(tab("[AggregateCondition = \"" + aggregateCondition + "\"]"));
364      buffer.append(tab("[Order = \"" + order + "\"]"));
365      dec();
366      buffer.append(tab("[/ GROUPBY_PLAN ]"));
367      dec();
368      return buffer.toString();
369   }
370
371   /**
372    * Returns the plan for group by.
373    * @usage Browser.
374    * @return
375    * @throws DException
376    */

377
378   public _QueryPlan getQueryPlan() throws DException {
379      _QueryPlan[] cplans = new _QueryPlan[] {tPlan.getQueryPlan()};
380      String JavaDoc cond = groupByCondition == null ? null : "" + groupByCondition;
381      String JavaDoc ord = order == null ? null : "" + order;
382      String JavaDoc cond1 = aggregateCondition == null ? null : "" + aggregateCondition;
383      cond = cond == null ? cond1 : (cond1 == null ? cond : cond + " <> " + cond1);
384      return new QueryPlan("GroupByPlan", cplans, cond, ord);
385   }
386
387   /**
388    * Returns all the children plans.
389    * @return
390    * @throws DException
391    */

392
393   public _TablePlan[] getChildTablePlans() throws DException {
394      childPlans = tPlan.getChildTablePlans();
395      initializeTableDetails();
396      return new _TablePlan[] {this};
397   }
398   /**
399     * The following methods delegate their call to their corresponding method,
400     * in which order is taken into consideration. It is done because order is
401     * needed to get the result properly.
402     */

403
404    public double getCostWithoutOrder(_ServerSession session, booleanvalueexpression condition, long estimatedRowCount) throws DException {
405       return getCost(session, condition, estimatedRowCount);
406    }
407
408    public double getCostWithoutOrder(_ServerSession session) throws DException {
409       return getCost(session);
410    }
411
412    public _Iterator executeWithOutOrder(_ServerSession session, booleanvalueexpression condition) throws DException {
413       return execute(session, condition);
414    }
415
416    public _Iterator executeWithoutOrder(_ServerSession session) throws DException {
417       return execute(session);
418    }
419
420 }
421
Popular Tags