KickJava   Java API By Example, From Geeks To Geeks.

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


1 package com.daffodilwoods.daffodildb.server.sql99.dql.plan.table;
2
3 import com.daffodilwoods.daffodildb.client.*;
4 import com.daffodilwoods.daffodildb.server.datasystem.indexsystem.*;
5 import com.daffodilwoods.daffodildb.server.datasystem.interfaces.*;
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.set.*;
11 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.table.*;
12 import com.daffodilwoods.daffodildb.server.sql99.dql.plan.*;
13 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.*;
14 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
15 import com.daffodilwoods.database.resource.*;
16 import com.daffodilwoods.database.sqlinitiator.*;
17
18 /**
19  * It represents the plan for Full Outer Join. It provides the functionality of
20  * obtaining resultset. The resultset of full outer join is union distinct
21  * resultset of left outer join and right outer join.
22  * <p>Title: </p>
23  * <p>Description: </p>
24  * <p>Copyright: Copyright (c) 2003</p>
25  * <p>Company: </p>
26  * @author unascribed
27  * @version 1.0
28  */

29
30 public class QualifiedFullPlan extends JoinPlanAbstract implements _QualifiedPlan {
31
32    /**
33     * If the index can be used in solving the QualifiedFullPlan , then this flag is set
34     */

35    private boolean isOptimizationPossible = false;
36
37    /**
38     * It represents the plan for left outer join.
39     */

40    protected _QualifiedPlan qualifiedLeftTablePlan;
41
42    public QualifiedFullPlan(_TablePlan tablePlanLeft0, _TablePlan tablePlanRight0, booleanvalueexpression onCondition, _QualifiedPlan qualifiedLeftPlan, _ServerSession session) throws DException {
43       tablePlanLeft = tablePlanLeft0;
44       tablePlanRight = tablePlanRight0;
45       joinCondition = onCondition;
46       /*
47         Following line is commented because of DSE3901 is not defined Exception is
48          thrown when compiere view(RV_ProjectLineIssue) runs. -- Manoj Kr. Nov. 19,2004
49        */

50       isOptimizationPossible = false;
51       childPlans = new _TablePlan[] {tablePlanLeft, tablePlanRight};
52       qualifiedLeftTablePlan = qualifiedLeftPlan;
53       initializeTableDetails();
54    }
55
56    /**
57     * Returns the type of plan
58     * @return
59     * @throws DException
60     */

61    public int getType() throws DException {
62       return QUALIFIEDFULLPLAN;
63    }
64
65    /**
66     * Calculates the cost of solving this Plan. If underlying resultsets are not
67     * sorted on condition columns then cost includes the cost of left outer join
68     * as well as the cost of both underlying childrens. If underlying resultsets
69     * are sorted on condition columns, then cost includes the cost of both
70     * underlying childrens.
71     * @return
72     * @throws DException
73     */

74
75    public double getCost(_ServerSession session) throws DException {
76       if (isOptimizationPossible) {
77          return getCostWhenOptimzationPossible(session);
78       }
79       return getCostWhenOptimizationNotPossible(session);
80    }
81
82    public String JavaDoc toString() {
83       StringBuffer JavaDoc strbuffer = new StringBuffer JavaDoc();
84       strbuffer.append("QUALIFIEDLEFTPLAN");
85       strbuffer.append("[" + tablePlanLeft.toString() + "]");
86       strbuffer.append("[" + tablePlanRight.toString() + "]");
87       if (joinCondition != null) {
88          strbuffer.append("Condition[" + joinCondition + "]");
89       }
90       if (isOptimizationPossible) {
91          strbuffer.append("NONE[TRUE]");
92       } else {
93          strbuffer.append("NONE[FALSE]");
94       }
95       return strbuffer.toString();
96    }
97
98    /**
99     * This method is used to obtain the resultset for Full Outer Join.
100     * When underlying resultsets are sorted on conditional columns then
101     * IndexedFullJoinIterator is created from the resultsets of left and right
102     * Plan.
103     *
104     * If underlying resultsets are not sorted on conditional columns then union
105     * of Loj and special Roj makes the resultset. Special Roj is a Roj in which
106     * only those rows comes into resultset for which there is no matching row in
107     * other iterator based on join condition.
108     *
109     * @param session
110     * @return
111     * @throws DException
112     */

113
114    public _Iterator execute(_ServerSession session) throws DException {
115       if (isOptimizationPossible) {
116          _Iterator iter1 = tablePlanLeft.execute(session);
117          _Iterator iter2 = tablePlanRight.execute(session);
118          _Iterator iter3=new IndexedFullJoinIterator(iter1,iter2, joinCondition, iter1.getKeyColumnInformations(), iter2.getKeyColumnInformations(), null, session);
119          iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
120          return iter3;
121       } else {
122   Object JavaDoc obclone = getClonedCD(joinCondition);
123          _Iterator iter1 = tablePlanLeft.execute(session);
124          _Iterator iter2 = tablePlanRight.execute(session);
125
126          _Iterator iter4=qualifiedLeftTablePlan.execute(session);
127          iter4.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
128
129          _Iterator iter5=new SpecialRightJoinIterator(iter1, iter2, (booleanvalueexpression)obclone, iter1.getKeyColumnInformations(), iter2.getKeyColumnInformations(), null, session);
130          iter5.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
131
132          _Iterator iter3=new FullJoinUnionIterator(iter4,iter5);
133          return iter3;
134       }
135    }
136
137    public String JavaDoc getVerifier() throws DException {
138       StringBuffer JavaDoc strbuffer = new StringBuffer JavaDoc();
139       inc();
140       strbuffer.append(tabW("[ QUALIFIED_FULL_PLAN ]"));
141       strbuffer.append("\n" + tablePlanLeft.getVerifier());
142       strbuffer.append("\n" + tablePlanRight.getVerifier());
143       inc();
144       if (joinCondition != null) {
145          strbuffer.append(tab("Condition = [" + joinCondition + "]"));
146       }
147       if (qualifiedLeftTablePlan != null) {
148          strbuffer.append(tab("QualifiedLeftTablePlan = [" + qualifiedLeftTablePlan.getVerifier() + "]"));
149       }
150
151       if (isOptimizationPossible) {
152          strbuffer.append(tab("isOptimizationPossible = [TRUE]"));
153       } else {
154          strbuffer.append(tab("isOptimizationPossible = [FALSE]"));
155       }
156       dec();
157       strbuffer.append(tab("[/ QUALIFIED_FULL_PLAN ]"));
158       dec();
159       return strbuffer.toString();
160    }
161
162    /**
163     * Returns the plan for FullOuterJoin.
164     * @return
165     * @throws DException
166     */

167
168    public _QueryPlan getQueryPlan() throws DException {
169       return new QueryPlan("QualifiedFullPlan", null, null, null);
170    }
171
172    /**
173     * Returns this plan.
174     * @return
175     * @throws DException
176     */

177
178    public _TablePlan[] getChildTablePlans() throws DException {
179       return new _TablePlan[] {this};
180    }
181
182    /**
183     * Checks whether the underlying resultsets are sorted on conditional columns
184     * or not. This method is currently not in use.
185     * @param session
186     * @throws DException
187     */

188
189    private void isOptimizationPossible(_ServerSession session) throws DException {
190      if (isConditionBelongsToBothPlanAndSeekable(joinCondition) == TypeConstants.BOTHSIDESEEKABLE) {
191          /** @todo set the Order in underlying Plans */
192          if (getOrder() == null) {
193             /** @todo Also check about the usage of index in conditional Column
194                  or artifically merge the Order if any column can use the index*/

195             if (tablePlanLeft.getType() == TableExpressionConstants.SINGLETABLEPLAN && tablePlanRight.getType() == TableExpressionConstants.SINGLETABLEPLAN) {
196                ColumnDetails[] cd = getColumnDetailsOfLeftAndRight(tablePlanLeft.getTableDetails()[0]);
197                isOptimizedCondition(session, tablePlanLeft, cd, 0);
198                if (isOptimizationPossible) {
199                   return;
200                }
201                isOptimizedCondition(session, tablePlanRight, cd, 1);
202                return;
203
204             }
205          }
206       }
207
208    }
209
210    /**
211     * checks whether the Col of Condition belonging to tablePlan Passed.
212     * This method is currently not in use.
213     * @param session
214     * @param tablePlan
215     * @param cd
216     * @param index
217     * @throws DException
218     */

219
220    private void isOptimizedCondition(_ServerSession session, _TablePlan tablePlan, ColumnDetails[] cd, int index) throws DException {
221       TableDetails tableDetailLeft = tablePlan.getTableDetails()[0];
222       _IndexTable indexTableLeft = session.getIndexTable(tableDetailLeft.getQualifiedIdentifier());
223       _IndexInformation[] indexInformation = indexTableLeft.getIndexInformations();
224       if (canUseIndex(indexInformation, cd[index])) {
225          isOptimizationPossible = true;
226          setOrder(cd);
227       }
228    }
229
230    /**
231     * This method is used to check whether index is present on the passed column.
232     * This method is currently not in use.
233     * @param indexInformation
234     * @param cd
235     * @return
236     * @throws DException
237     */

238
239    private boolean canUseIndex(_IndexInformation indexInformation[], ColumnDetails cd) throws DException {
240       String JavaDoc indexCol = cd.getColumn();
241       for (int i = 0; i < indexInformation.length; i++) {
242          String JavaDoc[] indexColumns = indexInformation[i].getColumns();
243          if ( (indexCol.equalsIgnoreCase(indexColumns[0]))) {
244             return true;
245          }
246       }
247       return false;
248    }
249
250    /**
251     * Returns the columns of left table and columns of right table that are
252     * included in condition.This method is currently not in use.
253     * @param tableDetailsLeft
254     * @return
255     * @throws DException
256     */

257
258    private ColumnDetails[] getColumnDetailsOfLeftAndRight(TableDetails tableDetailsLeft) throws DException {
259       ColumnDetails[] cds = joinCondition.getColumnDetails();
260         if (cds.length > 2) {
261          throw new DException("DSE3901", new Object JavaDoc[] {"Condition is not seekable"});
262       }
263       TableDetails td1 = cds[0].getTableDetails();
264       if (td1 == tableDetailsLeft) {
265          return cds;
266       } else {
267          return new ColumnDetails[] {cds[1], cds[0]};
268       }
269    }
270
271    /**
272     * Calculates the cost of solving this Plan. If underlying resultsets
273     * are sorted on condition columns, then cost includes the cost of both
274     * underlying childrens.
275     * @param session
276     * @return
277     * @throws DException
278     */

279    private double getCostWhenOptimzationPossible(_ServerSession session) throws DException {
280       double cost2 = tablePlanRight.getCost(session);
281       double cost1 = tablePlanLeft.getCost(session);
282       double totalCost1 = cost1 + cost2;
283       return totalCost1;
284    }
285
286    /**
287     * Calculates the cost of solving this Plan. If underlying resultsets are not
288     * sorted on condition columns then cost includes the cost of left outer join
289     * as well as the cost of both underlying childrens.
290     * @param session
291     * @return
292     * @throws DException
293     */

294    private double getCostWhenOptimizationNotPossible(_ServerSession session) throws DException {
295       long rows = qualifiedLeftTablePlan.getRowCount(session);
296       double cost1 = tablePlanLeft.getCost(session) + tablePlanRight.getCost(session);
297       double cost2 = qualifiedLeftTablePlan.getCost(session);
298       double totalCost1 = cost1 + cost2 + joinCondition.getCost(rows, true);
299       return totalCost1;
300    }
301
302    /**
303     * Merges the JoinRelation in the this Plan
304     * @param joinRelation
305     * @throws DException
306     */

307    public void merge(_JoinRelation joinRelation) throws DException {
308       super.merge(joinRelation);
309       qualifiedLeftTablePlan.merge(joinRelation);
310    }
311
312    /**
313     * Sets the Order in the underlying plans, first it creates the Orders from
314     * the ColumnDetails and then set it to underLyingPlan. This method is
315     * currently not in use.
316     * @param columnDetails
317     * @throws DException
318     */

319    private void setOrder(ColumnDetails[] columnDetails) throws DException {
320       _Order leftOrder = new SelectOrder(new ColumnDetails[] {columnDetails[0]});
321       _Order rightOrder = new SelectOrder(new ColumnDetails[] {columnDetails[1]});
322       ( (_SingleTablePlan) tablePlanLeft).setOrder(leftOrder);
323       ( (_SingleTablePlan) tablePlanRight).setOrder(rightOrder);
324    }
325
326    /**
327     * This method is used to obtain left underlying plan .
328     * @usage NaturalJoin
329     * @return
330     */

331
332    public _TablePlan getFirstPlan() {
333       return tablePlanLeft;
334    }
335
336    /**
337     * This method is used to obtain right underlying plan .
338     * @usage NaturalJoin
339     * @return
340     */

341    public _TablePlan getSecondPlan() {
342       return tablePlanRight;
343    }
344
345    /**
346     * This method is used to obtain condition of full outer join.
347     * @usage NaturalJoin
348     * @return
349     */

350
351    public booleanvalueexpression getCondition() {
352       return joinCondition;
353    }
354
355    /**
356     * This method is used to obtain left outer plan .
357     * @usage NaturalJoin
358     * @return
359     */

360
361    public _QualifiedPlan getLeftPlan() {
362       return qualifiedLeftTablePlan;
363    }
364
365    /**
366     * This method is used to remove the cover of unExecutable plans like
367     * OrderSequencePlan and TemporaryMergePlan in the hierarchy of table plans.
368     * @return
369     * @throws DException
370     */

371
372    public _TablePlan joinMissingLink() throws DException {
373       tablePlanLeft = tablePlanLeft.joinMissingLink();
374       tablePlanRight = tablePlanRight.joinMissingLink();
375       childPlans = new _TablePlan[] {tablePlanLeft, tablePlanRight};
376       qualifiedLeftTablePlan.joinMissingLink(); // If orderSequencePlan is under this Loj which can come under View. Just to remove it.
377
return this;
378    }
379
380    /**
381     * The following methods are same as corresponding counterparts getCost
382     * methods. In these method getCostWithoutOrder is called instead of getCost
383     * methods.
384     */

385
386
387    public double getCostWithoutOrder(_ServerSession session) throws DException {
388       if (isOptimizationPossible) {
389          return getCostWithoutOrderWhenOptimzationPossible(session);
390       }
391       return getCostWithoutOrderWhenOptimizationNotPossible(session);
392    }
393
394
395    private double getCostWithoutOrderWhenOptimzationPossible(_ServerSession session) throws DException {
396       double cost2 = tablePlanRight.getCostWithoutOrder(session);
397       double cost1 = tablePlanLeft.getCostWithoutOrder(session);
398       double totalCost1 = cost1 + cost2;
399       return totalCost1;
400    }
401
402    private double getCostWithoutOrderWhenOptimizationNotPossible(_ServerSession session) throws DException {
403       long rows = qualifiedLeftTablePlan.getRowCount(session);
404       double cost2 = tablePlanRight.getCostWithoutOrder(session) + tablePlanLeft.getCostWithoutOrder(session);
405       double cost1 = qualifiedLeftTablePlan.getCostWithoutOrder(session);
406       double totalCost1 = cost1 + cost2 + +joinCondition.getCost(rows, true);
407       return totalCost1;
408    }
409
410    /**
411     * The following methods are same as corresponding counterparts execute
412     * methods. In these method executeWithoutOrder is called instead of execute
413     * methods.
414     */

415
416    public _Iterator executeWithoutOrder(_ServerSession session) throws DException {
417       if (isOptimizationPossible) {
418          _Iterator iter1 = tablePlanLeft.execute(session);
419          _Iterator iter2 = tablePlanRight.execute(session);
420          _Iterator iter=new IndexedFullJoinIterator(iter1, iter2, joinCondition, iter1.getKeyColumnInformations(), iter2.getKeyColumnInformations(), null, session);
421          iter.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
422          return iter;
423       } else {
424          _Iterator iter1 = tablePlanLeft.executeWithoutOrder(session);
425          _Iterator iter2 = tablePlanRight.executeWithoutOrder(session);
426
427          _Iterator iter4=qualifiedLeftTablePlan.executeWithoutOrder(session);
428          iter4.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
429
430          _Iterator iter5=new SpecialRightJoinIterator(iter1, iter2, joinCondition, iter1.getKeyColumnInformations(), iter2.getKeyColumnInformations(), null, session);
431          iter5.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
432
433          _Iterator iter3=new FullJoinUnionIterator(iter4,iter5);
434          return iter3;
435       }
436    }
437    private Object JavaDoc getClonedCD(booleanvalueexpression cd) throws DException {
438        try {
439          return cd.clone();
440        }
441        catch (CloneNotSupportedException JavaDoc ex) {
442          throw new DException("DSE0", new Object JavaDoc[] {"Clone Not Supported"});
443        }
444      }
445
446 }
447
Popular Tags