KickJava   Java API By Example, From Geeks To Geeks.

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


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.serversystem.*;
7 import com.daffodilwoods.daffodildb.server.sql99.common.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.common.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
10 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.table.*;
11 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.*;
12 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.condition.*;
13 import com.daffodilwoods.daffodildb.server.sql99.dql.queryexpression.*;
14 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.*;
15 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.predicates.*;
16 import com.daffodilwoods.database.resource.*;
17 import com.daffodilwoods.database.sqlinitiator.*;
18 import com.daffodilwoods.database.utility.P;
19
20 /**
21  *
22  * <p>Title: ViewPlan</p>
23  * <p>Description:
24  * This class represents the plan for View. It comes into picture when our view
25  * is not optimizable. By optimizable we mean that if we map the view definition
26  * to outer query. The criteria for a view to be not optimizable are
27  * 1. if set operators are specified.
28  * 2. if group/order/distinct is present.
29  * 3. if functional columns are present.
30  * It provides the functionality of obtaining resultset for view.
31  * </p>
32  * <p>Copyright: Copyright (c) 2003</p>
33  * <p>Company: Daffodil S/W LTD.</p>
34  * @author SelectTeam
35  * @version 1.0
36  */

37
38 public class ViewPlan extends PlanAbstract implements TableExpressionConstants, _SingleTablePlan, ExecutionPlanConstants {
39
40    /**
41     * Represents the plan of select query involved in view.
42     */

43
44    private _TablePlan plan;
45
46    /**
47     * Represents view as table.
48     */

49
50    private TableDetails tableDetail;
51
52    /**
53     * Represents the mapping of columns that are used in query in which view is
54     * involved and columns that are involved in view.
55     */

56
57    private Object JavaDoc[][] virtualAndActualColumns; // Required in ViewIterator Mapping of Column against Column involved in query.
58

59    /**
60     * Represents the order which will be applied at the resultset of select
61     * query involved in view.
62     */

63
64    private _Order singleTableOrder;
65
66    /**
67     * Represents the mapping of join condition passed to this view vs total
68     * condition used to solve this view. Total condition includes the passed
69     * join condition and condition which is present in this plan.
70     */

71
72    private HashMap wayOfExecution;
73
74    public ViewPlan(queryexpression queryExpression0, TableDetails tableDetailsPassed, Object JavaDoc[][] virtualAndActualColumns0, _TablePlan plan0) {
75       tableDetail = tableDetailsPassed;
76       tableDetail.setTableType(TypeConstants.VIEW);
77       virtualAndActualColumns = virtualAndActualColumns0;
78       plan = plan0;
79       childPlans = new _TablePlan[] {plan0};
80       wayOfExecution = new HashMap();
81
82     }
83
84    /**
85     * Returns the type of plan. It is treated as Single Table.
86     * @return
87     * @throws DException
88     */

89
90    public int getType() throws DException {
91       return TableExpressionConstants.SINGLETABLEPLAN;
92    }
93
94    /**
95     * This method is used to obtain the resultset of view. It creates resultset
96     * for view on the resultset of select query involved in view. If any
97     * condition is present on this plan, then filtered resultset is formed on
98     * underlying resultset. And if any order is present then sorted resultset is
99     * also formed and returned.
100     * @param serverSession
101     * @return
102     * @throws DException
103     */

104
105    public _Iterator execute(_ServerSession serverSession) throws DException {
106       _Iterator iter = ( (_TablePlanAdditional) plan).executePlan(serverSession);
107       iter = new ViewIterator(iter, virtualAndActualColumns, tableDetail);
108       return checkForOrderAndCondition(iter, serverSession, remainingCondition);
109    }
110
111    /**
112     * This method is used to obtain the resultset of view based on the passed
113     * condition. It creates resultset for view on the resultset of select query
114     * involved in view. It retrieves the condition against the passed condition
115     * from the mapping which is set in getCost method. If condition is found, it
116     * means passed condition is not shifted to underlying plan so a filtered
117     * resultset is formed with this condition on underlying resultset. And if
118     * condition is not found, it means passed condition is shifted to underlying
119     * plan, then columns present in condition are mapped to actual columns
120     * present in view by using mapping of virtual and actual columns. Condition
121     * is shifted to underlying plan when columns present in join condition are
122     * not functional columns in view definition. Also if
123     * any order is present then sorted resultset is also formed and returned.
124     * @param session
125     * @param condition
126     * @return
127     * @throws DException
128     */

129
130    public _Iterator execute(_ServerSession session, booleanvalueexpression condition) throws DException {
131       booleanvalueexpression b = (booleanvalueexpression) wayOfExecution.get(condition);
132       _Iterator iter = null;
133       if (b == null) { // It means condition has been shifted below view.
134
map(condition);
135          iter = ( (_TablePlanAdditional) plan).executePlan(session, condition);
136       } else {
137          iter = ( (_TablePlanAdditional) plan).executePlan(session);
138       }
139       iter = new ViewIterator(iter, virtualAndActualColumns, tableDetail);
140       return checkForOrderAndCondition(iter, session, b);
141    }
142
143    /**
144     * This method is used to obtain the cost of view based on the passed
145     * condition and number of rows. It firstly checks whether passed condition
146     * can be shifted to underlying plan. It is the case when columns present in
147     * join condition are not functional columns in view definition. So for
148     * finding this, columns of condition are mapped to columns present in view
149     * definition. So based on the fact whether condition is shifted to
150     * underlying plan, cost is calculated. And at the end, columns of condition
151     * are restored to the original columns used in query in which view is
152     * involved. This is done because this join condition can be passed to some
153     * other plan for calculating cost.
154     * @param session
155     * @param condition
156     * @param estimatedRows
157     * @return
158     * @throws DException
159     */

160
161    public double getCost(_ServerSession session, booleanvalueexpression condition, long estimatedRows) throws
162        DException {
163       Object JavaDoc[][] mapping = map(condition);
164       double cost = 0.0;
165
166       /* above line is commented by Done by vibha on 26July 2004
167        */

168             if (condition.canUseForSeek()== TypeConstants.BOTHSIDESEEKABLE) {
169       cost = plan.getCost(session, condition, estimatedRows);
170          cost = addCostForCondition(cost, session, remainingCondition, 1);
171       } else {
172          booleanvalueexpression newBve = BVEPlanMerger.addAndConditions(condition, remainingCondition);
173          wayOfExecution.put(condition, newBve);
174          cost = plan.getCost(session);
175          cost = addCostForCondition(cost, session, newBve, estimatedRows);
176       }
177       reMap(mapping);
178       return cost;
179    }
180
181    /**
182     * This method is used to calculate the cost of obtaining resultset from this
183     * plan. Resultant cost includes the cost of underlying plan, cost of solving
184     * condition.
185     * @param session
186     * @return
187     * @throws DException
188     */

189
190    public double getCost(_ServerSession session) throws DException {
191       double cost = plan.getCost(session);
192       return addCostForCondition(cost, session, remainingCondition, 1);
193    }
194
195    /**
196     * This method return array of single table plan.
197     * @return
198     * @throws DException
199     */

200
201    public _SingleTablePlan[] getSingleTablePlans() throws DException {
202       return new _SingleTablePlan[] {this};
203    }
204
205    /**
206     * This method is responsible for removing the cover of non executables plan
207     * like OrderSequence Plan and TemporaryMerge Plan. This method is returning
208     * this because in underlying query plan separate call for joinMissingLink is
209     * initiated by underlying queryspecification.
210     * @return
211     * @throws DException
212     */

213
214    public _TablePlan joinMissingLink() throws DException {
215       return this;
216    }
217
218    /**
219     * @param session
220     * @param condition
221     * @return
222     * @throws DException
223     */

224
225    public _Order getOrder() throws DException {
226       return GeneralPurposeStaticClass.getJoinOrdered(singleTableOrder, plan.getOrder());
227    }
228
229    /**
230     * This method adds the cost of solving condition to passed cost.
231     * @param cost
232     * @param serverSession
233     * @param condition
234     * @param rows
235     * @return
236     * @throws DException
237     */

238
239    protected double addCostForCondition(double cost, _ServerSession serverSession, booleanvalueexpression condition, long rows) throws DException {
240       return condition == null
241           ? cost
242           : cost + condition.getCost(plan.getRowCount(serverSession) * rows, false);
243    }
244
245    /**
246     * This method is used to map the columns of condition to the columns which
247     * are present in view definition.
248     * @param condition
249     * @return
250     * @throws DException
251     */

252
253    private Object JavaDoc[][] map(booleanvalueexpression condition) throws DException {
254       ColumnDetails[] cd = condition.getColumnDetails();
255       ArrayList list = new ArrayList(5);
256       try {
257          for (int i = 0; i < cd.length; i++) {
258             for (int j = 0; j < virtualAndActualColumns.length; j++) {
259                ColumnDetails virtualColumn = (ColumnDetails) virtualAndActualColumns[j][0];
260                if (cd[i].getTable() == virtualColumn.getTable() && cd[i].getColumn().equalsIgnoreCase(virtualColumn.getColumn())) {
261                   list.add(new Object JavaDoc[] {cd[i], cd[i].clone()});
262                   GeneralPurposeStaticClass.updateColumnDetailsProperties(cd[i], (ColumnDetails) virtualAndActualColumns[j][1]);
263                   break;
264                }
265             }
266          }
267       } catch (CloneNotSupportedException JavaDoc ex) {
268          throw new DException("DSE0", new Object JavaDoc[] {"Clone Not Supported"});
269       }
270       return (Object JavaDoc[][]) list.toArray(new Object JavaDoc[0][]);
271    }
272
273    /**
274     * This method is used to restore the columns to original columns of query
275     * in which view is involved.
276     * @param mapping
277     * @throws DException
278     */

279
280    private void reMap(Object JavaDoc[][] mapping) throws DException {
281       for (int i = 0; i < mapping.length; i++) {
282          GeneralPurposeStaticClass.updateColumnDetailsProperties( (ColumnDetails) mapping[i][0], (ColumnDetails) mapping[i][1]);
283       }
284    }
285
286    public String JavaDoc toString() {
287       if (plan == null) {
288          return "VIEWPLAN[NULL]";
289       }
290       return "VIEWPLAN[" + plan + "]";
291    }
292
293    /**
294     * This plan set the condition in case of order sequence plan.
295     * @param condition
296     * @throws DException
297     */

298
299    public void setCondition(booleanvalueexpression condition) throws DException {
300       remainingCondition = condition;
301    }
302
303    /**
304     * Return the view as table.
305     * @return
306     * @throws DException
307     */

308
309    public TableDetails[] getTableDetails() throws DException {
310       return new TableDetails[] {tableDetail};
311    }
312
313    /**
314     * Returns view as table. This method previously returns the underlying
315     * tables of view. But now it behaves like getTableDetails. It is redundant.
316     * @return
317     * @throws DException
318     */

319
320    public TableDetails[] getViewTableDetails() throws DException {
321       return new TableDetails[] {tableDetail};
322    }
323
324    public String JavaDoc getVerifier() throws DException {
325       if (plan == null) {
326          return "VIEWPLAN[NULL]";
327       }
328       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
329       inc();
330       buffer.append(tabW("[ VIEWPLAN ]"));
331       buffer.append("\n" + plan.getVerifier());
332       buffer.append(tab("[/ VIEWPLAN ]"));
333       inc();
334       buffer.append(tab("[RemainingCondition =\"" + remainingCondition + "\"]"));
335       buffer.append(tab("[Order =\"" + singleTableOrder + "\"]"));
336       dec();
337       return buffer.toString();
338    }
339
340    /**
341     * This method is used to check whether passed table belongs to this plan.
342     * @param tableDetails0
343     * @return
344     * @throws DException
345     */

346
347    public boolean ifExists(TableDetails tableDetails0) throws DException {
348       return tableDetails0 == tableDetail;
349    }
350
351    /**
352     * This is used to form resultset for condition and order present on this
353     * plan.
354     * @param iterator
355     * @param serverSession
356     * @return
357     * @throws DException
358     */

359
360    private _Iterator checkForOrderAndCondition(_Iterator iterator, _ServerSession serverSession, booleanvalueexpression condition) throws DException {
361       iterator = checkForCondition(iterator, serverSession, condition);
362       if (singleTableOrder != null) {
363          iterator = GeneralPurposeStaticClass.getTemporaryIndexIterator(iterator, this, serverSession, singleTableOrder);
364       }
365       return iterator;
366    }
367
368    /**
369     * This method is used to obtain the resultset for passed condition.
370     * @param iterator
371     * @param session
372     * @return
373     * @throws DException
374     */

375    private _Iterator checkForCondition(_Iterator iterator, _ServerSession session, booleanvalueexpression condition) throws DException {
376       if (condition != null) {
377          return getNonIndexedFilteredIteratorWithSubQuery(iterator, session, condition);
378       }
379       return iterator;
380    }
381
382    /**
383     * This method is used to provide underlying plans.
384     * @return
385     * @throws DException
386     */

387
388    public _TablePlan[] getChildTablePlans() throws DException {
389       childPlans = plan.getChildTablePlans();
390       initializeTableDetails();
391       return new _TablePlan[] {this};
392    }
393
394    /**
395     * Returns the plan for View.
396     * @return
397     * @throws DException
398     */

399
400    public _QueryPlan getQueryPlan() throws DException {
401       _QueryPlan[] cplans = new _QueryPlan[]{plan.getQueryPlan()};
402       String JavaDoc cond = null;
403       String JavaDoc ord = singleTableOrder == null ? null : ("" + singleTableOrder);
404       return new QueryPlan("ViewPlan " + tableDetail.getQualifiedTableName(),
405                            cplans, cond, ord);
406    }
407
408    /**
409     * Sets the order for this view.
410     * @param order
411     * @throws DException
412     */

413
414    public void setOrder(_Order order) throws DException {
415       this.singleTableOrder = order;
416    }
417
418    /**
419     * The following methods are same as corresponding counterparts getCost
420     * methods. In these method getCostWithoutOrder is called instead of getCost
421     * methods.
422     */

423
424    public double getCostWithoutOrder(_ServerSession session) throws DException {
425       double cost = plan.getCostWithoutOrder(session);
426       return addCostForCondition(cost, session, remainingCondition, 1);
427    }
428
429    public double getCostWithoutOrder(_ServerSession session, booleanvalueexpression condition, long estimatedRowCount) throws DException {
430       Object JavaDoc[][] mapping = map(condition);
431       double cost = 0.0;
432
433 /* above line is commented by Done by vibha on 26July 2004*/
434
435       if (condition.canUseForSeek() == TypeConstants.BOTHSIDESEEKABLE) {
436         cost = plan.getCostWithoutOrder(session, condition, estimatedRowCount);
437          cost = addCostForCondition(cost, session, remainingCondition, 1);
438       } else {
439          booleanvalueexpression newBve = BVEPlanMerger.addAndConditions(condition, remainingCondition);
440          wayOfExecution.put(condition, newBve);
441          cost = plan.getCostWithoutOrder(session);
442          cost = addCostForCondition(cost, session, newBve, estimatedRowCount);
443       }
444       reMap(mapping);
445       return cost;
446    }
447
448    /**
449     * The following methods are same as corresponding counterparts execute
450     * methods. In these method executeWithoutOrder is called instead of execute
451     * methods.
452     */

453
454    public _Iterator executeWithoutOrder(_ServerSession serverSession) throws DException {
455       _Iterator iter = ( (_TablePlanAdditional) plan).executeWithoutOrderPlan(serverSession);
456       iter = new ViewIterator(iter, virtualAndActualColumns, tableDetail);
457       if (remainingCondition == null) {
458          return iter;
459       }
460       return getNonIndexedFilteredIterator(iter, serverSession, remainingCondition);
461    }
462
463    public _Iterator executeWithOutOrder(_ServerSession session, booleanvalueexpression condition) throws DException {
464       booleanvalueexpression cond = (booleanvalueexpression) wayOfExecution.get(condition);
465       _Iterator iter = null;
466       if (cond == null) {
467          map(condition);
468          iter = ( (_TablePlanAdditional) plan).executeWithOutOrderPlan(session, condition);
469        } else {
470          iter = ( (_TablePlanAdditional) plan).executeWithoutOrderPlan(session);
471       }
472       iter = new ViewIterator(iter, virtualAndActualColumns, tableDetail);
473       if (cond == null) {
474         return iter;
475       }
476       return getNonIndexedFilteredIterator(iter, session, cond);
477    }
478
479 }
480
Popular Tags