KickJava   Java API By Example, From Geeks To Geeks.

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


1 package com.daffodilwoods.daffodildb.server.sql99.dql.plan.table;
2
3 import java.util.*;
4
5 import com.daffodilwoods.daffodildb.server.serversystem.*;
6 import com.daffodilwoods.daffodildb.server.sql99.common.*;
7 import com.daffodilwoods.daffodildb.server.sql99.dql.common.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.condition.*;
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.expression.booleanvalueexpression.*;
14 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
15 import com.daffodilwoods.database.resource.*;
16 import com.daffodilwoods.database.sqlinitiator.*;
17 import com.daffodilwoods.database.utility.*;
18 import com.daffodilwoods.daffodildb.server.sql99.common.TypeConstants;
19
20 /**
21  *
22  * <p>Title: JoinPlanAbstract</p>
23  * <p>Description:
24  * It provides the common functionality for all join plans. The common
25  * functionality includes the functionality of cost calculation and obtaining
26  * the resultset.
27  * </p>
28  * <p>Copyright: Copyright (c) 2003</p>
29  * <p>Company: Daffodil S/W Ltd.</p>
30  * @author SelectTeam
31  * @version 1.0
32  */

33
34 public abstract class JoinPlanAbstract extends PlanAbstract implements TableExpressionConstants {
35
36    /**
37     * Represents the left plan.
38     */

39
40    protected _TablePlan tablePlanLeft;
41
42    /**
43     * Represents the right plan.
44     */

45
46    protected _TablePlan tablePlanRight;
47
48    /**
49     * Represents the way of execution.
50     */

51
52    protected short executionPath = -1;
53
54    /**
55     * Represents the way of execution for condition which is solvable above the
56     * join level.
57     */

58
59    protected Object JavaDoc[][] mappingOfConditionAndWayOfExecution = new Object JavaDoc[0][];
60
61    /**
62     * Represents the way of execution for condition which is solvable above the
63     * join level and order is not needed.
64     */

65
66    protected Object JavaDoc[][] mappingOfConditionAndWayOfExecutionWithoutOrder = new Object JavaDoc[0][];
67
68    /**
69     * Represents the join condition
70     */

71
72    protected booleanvalueexpression joinCondition;
73
74    /**
75     * Represents the columns for hasRecord.
76     */

77
78    protected ColumnDetails[] hasRecordColumns;
79
80    private _Reference[] underlyingRef;
81
82
83
84    public void setUnderLyingRefernce(_Reference[] underLyingRef0) throws DException{
85      underlyingRef=underLyingRef0;
86    }
87
88    /**
89     * It is required when both tables of join condition belongs to this plan.
90     * JoinRelation is passed to Merge the joinCondition in this plan.
91     * If joinRelation condition involves functional Columns, then joinRelation
92     * condition is solved as non seekable condition at this level.
93     * Examples
94     * select * from V1 , V2 where V1.id = V2.id
95     * Actually, Vi.id column is Functional in View Query and after setQueryColumns
96     * call, table is null set for V1.id
97     * Then such conditions are solved as non seekable condition at this level.
98     * Checks the solvability on joinRelation on which Plan
99     * @param joinRelation
100     * @throws DException
101     */

102
103    public void merge(_JoinRelation joinRelation) throws DException {
104       if (isTableInvolvedIsNull(joinRelation)) {
105          joinCondition = BVEPlanMerger.addAndConditions(joinCondition, joinRelation.getCondition());
106          return;
107       }
108       mergeJoinRelation(joinRelation);
109    }
110
111    /**
112     * It check join relation is solvable on which plan. There may arise 3 cases-
113     * 1. condition belong to both plans.
114     * 2. condition belong to right plan.
115     * 3. condition belong to left plan.
116     * @param joinRelation
117     * @throws DException
118     */

119
120    private void mergeJoinRelation(_JoinRelation joinRelation) throws DException {
121       TableDetails[] tableDetails = joinRelation.getTableDetails();
122       int tableCount = checkForTablesInTablePlan(tableDetails, tablePlanRight);
123       switch (tableCount) {
124          case 1: // Belongs to Both The Plan
125
joinCondition = BVEPlanMerger.addAndConditions(joinCondition, joinRelation.getCondition());
126             break;
127          case 2: // Fully Belongs to Plan 2
128
tablePlanRight.merge(joinRelation);
129             break;
130          default: // Fully Belongs to Plan 1 as both the cases of Plan 1 is considered
131
tablePlanLeft.merge(joinRelation);
132       }
133    }
134
135    /**
136     * Returns rowCount of this Plan
137     * Let rowCount = Rows from Plan1 * Rows From Plan2
138     * If JoinCondition present here is null then rowCount is retuned
139     * else rowCount is the reduced rows by the joinCondition.
140     * @return
141     * @throws DException
142     */

143
144    public long getRowCount(_ServerSession session) throws DException {
145       long rc = joinCondition != null ? Math.min(tablePlanLeft.getRowCount(session), tablePlanRight.getRowCount(session)) : tablePlanLeft.getRowCount(session) * tablePlanRight.getRowCount(session);
146       return rc;
147    }
148
149    /**
150     * Computes Cost of this Plan
151     * Algo:
152     * a)
153     * If joinCondition is Null, case arises only in Qualified Plans when
154     * conditions are shifted to single table level. The cost will be the
155     * cartesianing cost of the two plans.(ie multiplication of the cost
156     * of two tables).
157     * b) Then we check whether the joinCondition is seekable and the
158     * condition belongs to both plans then we try the options of left
159     * seeking right and vice versa
160     * c) otherwise condition is non seekable and will be solved as
161     * remainingCondition.
162     *
163     * Whatever is the case, the way of execution is stored in variable.
164     *
165     * @return cost calculated
166     * @throws DException
167     */

168
169    public double getCost(_ServerSession session) throws DException {
170       if (joinCondition == null) {
171          executionPath = CONITION_NULL;
172          return getCostWhenConditionNull(session);
173       }
174       int conditionSeekableType = isConditionBelongsToBothPlanAndSeekable(joinCondition);
175        switch(conditionSeekableType){
176           case TypeConstants.NOSEEK:
177              executionPath = NOSEEK;
178              return getCostWhenNoSeek(session);
179           case TypeConstants.BOTHSIDESEEKABLE:
180          return computeCostWhenConditionIsSeekableAndBelongsToBothPlan(session);
181           case TypeConstants.LEFTSIDESEEKABLE:
182              executionPath = WHENRIGHTSEEKLEFT;
183              return getCostWhenRightSeekLeft(session);
184           case TypeConstants.RIGHTSIDESEEKABLE:
185              executionPath = WHENLEFTSEEKRIGHT;
186              return getCostWhenLeftSeekRight(session);
187           default :
188              throw new DException("DSE0",new Object JavaDoc[]{"Invalid conditionSeekableType"+conditionSeekableType});
189       }
190    }
191
192    /**
193     * Computes Cost when Left Seek Right
194     * Computes Cost when Right Seek Left
195     * Compare two costs and return whichever is less
196     * @return
197     * @throws DException
198     */

199
200    private double computeCostWhenConditionIsSeekableAndBelongsToBothPlan(_ServerSession session) throws DException {
201       double totalCost1 = getCostWhenLeftSeekRight(session);
202       double totalCost2 = getCostWhenRightSeekLeft(session);
203       if (totalCost1 > totalCost2) {
204          executionPath = WHENRIGHTSEEKLEFT;
205          return totalCost2;
206       }
207       executionPath = WHENLEFTSEEKRIGHT;
208       return totalCost1;
209    }
210
211    /**
212     * GetCostWithOutOrder is needed when Right Iterator is seeking into Left Iterator.
213     * It is same as getCost the only differnce is that Order is not considered
214     * in the Cost Calculation as order is solved on the top.
215     * @return
216     * @throws DException
217     */

218
219    public double getCostWithoutOrder(_ServerSession session) throws DException {
220       if (joinCondition == null) {
221          executionPath = CONITION_NULL;
222          return getCostWithoutOrderWhenConditionNull(session);
223       }
224       int conditionSeekableType = isConditionBelongsToBothPlanAndSeekable(joinCondition);
225        switch(conditionSeekableType){
226           case TypeConstants.NOSEEK:
227              executionPath = NOSEEK;
228              return getCostWhenNoSeek(session);
229           case TypeConstants.BOTHSIDESEEKABLE:
230          return computeCostWithoutOrderWhenConditionIsSeekableAndBelongsToBothPlan(session);
231           case TypeConstants.LEFTSIDESEEKABLE:
232              executionPath = WHENRIGHTSEEKLEFT;
233              return getCostWhenRightSeekLeftWithoutOrder(session);
234           case TypeConstants.RIGHTSIDESEEKABLE:
235              executionPath = WHENLEFTSEEKRIGHT;
236              return getCostWhenLeftSeekRightWithoutOrder(session);
237           default :
238              throw new DException("DSE0",new Object JavaDoc[]{"Invalid conditionSeekableType"+conditionSeekableType});
239       }
240
241    }
242
243    /**
244     * Computes Cost when Left Seek Right Without Order
245     * Computes Cost when Right Seek Left Without Order
246     * Compare two costs and return whichever is less
247     * @return
248     * @throws DException
249     */

250
251    private double computeCostWithoutOrderWhenConditionIsSeekableAndBelongsToBothPlan(_ServerSession session) throws DException {
252       double totalCost1 = getCostWhenLeftSeekRightWithoutOrder(session);
253       double totalCost2 = getCostWhenRightSeekLeftWithoutOrder(session);
254       if (totalCost1 > totalCost2) {
255          executionPath = WHENRIGHTSEEKLEFT;
256          return totalCost2;
257       }
258       executionPath = WHENLEFTSEEKRIGHT;
259       return totalCost1;
260    }
261
262    /**
263     * It is used to change the mapping of condition and its way of execution.
264     * The passed condition and its way of execution is added into the mapping.
265     * @param conditionAndWayOfExecution
266     * @param conditionArg
267     * @return
268     * @throws DException
269     */

270
271    private Object JavaDoc[][] changeMappingOfConditionAndWayOfExecution(Object JavaDoc[][] conditionAndWayOfExecution, booleanvalueexpression conditionArg) throws DException {
272       Object JavaDoc[][] tempConditionAndWayOfExecution = new Object JavaDoc[conditionAndWayOfExecution.length + 1][];
273       System.arraycopy(conditionAndWayOfExecution, 0, tempConditionAndWayOfExecution, 0, conditionAndWayOfExecution.length);
274       Object JavaDoc temp[] = new Object JavaDoc[2];
275       temp[0] = conditionArg;
276       tempConditionAndWayOfExecution[conditionAndWayOfExecution.length] = temp;
277       return tempConditionAndWayOfExecution;
278    }
279
280    /**
281     * Returns the cost when join condition is null and passed condition belongs
282     * to both plans. Cost includes the cost of underlying plans as well as the
283     * cost of applying condition on the cartesian of rows of both plans.
284     * @param conditionArg
285     * @return
286     * @throws DException
287     */

288
289    private double getCostWhenConditionNullAndConditionPassedSolvableOnBothPlan(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
290       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] =
291           new Integer JavaDoc(SOLVABLE_ON_BOTH_AND_CONDITION_NULL);
292       return tablePlanLeft.getCost(session) * tablePlanRight.getCost(session) +
293           conditionArg.getEstimatedRows(tablePlanLeft.getRowCount(session) * tablePlanRight.getRowCount(session));
294    }
295
296    /**
297     * Returns the cost when join condition is null and passed condition belongs
298     * to left plan. Cost includes the cost of underlying plans.
299     * @param conditionArg
300     * @param estimatedRowCount
301     * @return
302     * @throws DException
303     */

304    private double getCostWhenConditionNullAndWhenConditionPassedIsSolvableOnLeftPlan(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
305       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_CONDITION_NULL);
306       return tablePlanLeft.getCost(session, conditionArg, estimatedRowCount) * tablePlanRight.getCost(session);
307    }
308
309    /**
310     * Returns the cost when join condition is null and passed condition belongs
311     * to right plan. Cost includes the cost of underlying plans without the
312     * consideration of order, as we'll use right seek left. And in right seek
313     * left order will be solved at the top.
314     * @param conditionArg
315     * @param estimatedRowCount
316     * @return
317     * @throws DException
318     */

319    private double getCostWhenConditionNullAndWhenConditionPassedIsSolvableOnRightPlan(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
320       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_CONDITION_NULL);
321       double cost2 = tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount) * tablePlanLeft.getCostWithoutOrder(session);
322       if (getOrder() != null) {
323          cost2 += CostCalculator.getCostForTemporaryOrder(getRowCount(session));
324       }
325       return cost2;
326    }
327
328    /**
329     * Computes Cost of Plan for local JoinCondition. Also cost of evaluation of
330     * condition is added to resultant cost.
331     * @param conditionArg
332     * @param estimatedRowCount
333     * @return
334     * @throws DException
335     */

336    private double getCostWhenConditionPassedIsSolvableOnBothPlan(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
337       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_BOTH);
338       double cost = getCost(session);
339       long rowCount = getRowCount(session);
340       cost += conditionArg.getCost(rowCount, false);
341       return cost;
342    }
343
344    /**
345     * Computes cost when passed condition belong to left plan and local join
346     * condition is used for left seek right option.
347     * @param conditionArg
348     * @param estimatedRowCount
349     * @return
350     * @throws DException
351     */

352
353    private double getCostWhenConditionPassedIsSolvableOnLeftPlanAndSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
354       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_SEEKABLE);
355       double cost1 = tablePlanLeft.getCost(session, conditionArg, estimatedRowCount);
356       long estimatedRow1 = tablePlanLeft.getEstimatedRows(conditionArg, estimatedRowCount, session);
357       cost1 += tablePlanRight.getCost(session, joinCondition, estimatedRow1);
358       return cost1;
359    }
360
361    /**
362     * Computes cost when passed condition belongs to right plan and local join
363     * condition is used for right seek left option. Since we are using right seek
364     * left option, there is no need of consideration of order as it will be solved
365     * at top.
366     * @param session
367     * @param conditionArg
368     * @param estimatedRowCount
369     * @return
370     * @throws DException
371     */

372
373    private double getCostWhenConditionPassedIsSolvableOnRightPlanAndSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
374       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_SEEKABLE);
375       long estimatedRow2 = tablePlanRight.getEstimatedRows(conditionArg, estimatedRowCount, session);
376       double cost2 = tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount);
377       _Order order = getOrder();
378       if (order != null) {
379          cost2 += CostCalculator.getCostForTemporaryOrder(getRowCount(session));
380       }
381       cost2 += tablePlanLeft.getCostWithoutOrder(session, joinCondition, estimatedRow2);
382       return cost2;
383    }
384
385    /**
386     * Computes cost when passed condition belongs to left plan and local join
387     * condition can't be used for seek.
388     * @param session
389     * @param conditionArg
390     * @param estimatedRowCount
391     * @return
392     * @throws DException
393     */

394
395    private double getCostWhenConditionPassedIsSolvableOnLeftPlanAndConditionIsNonSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
396       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_NONSEEKABLE);
397       return tablePlanLeft.getCost(session, conditionArg, estimatedRowCount) * tablePlanRight.getCost(session);
398    }
399
400
401    /**
402     * Computes cost when passed condition belongs to right plan and local join
403     * condition can't be used for seek. In this case order is not taken into
404     * consideration as condition belongs to right plan.
405     * @param session
406     * @param conditionArg
407     * @param estimatedRowCount
408     * @return
409     * @throws DException
410     */

411
412    private double getCostWhenConditionPassedIsSolvableOnRightPlanAndIsNonSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
413       mappingOfConditionAndWayOfExecution[mappingOfConditionAndWayOfExecution.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_NONSEEKABLE);
414       double cost2 = tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount);
415       _Order order = getOrder();
416       cost2 *= tablePlanLeft.getCostWithoutOrder(session);
417       if (order != null) {
418          cost2 += CostCalculator.getCostForTemporaryOrder(cost2);
419       }
420       return cost2;
421    }
422
423    /**
424     * Calculates the cost for conditionArg passed in this plan
425     * It checks whether the condition is solvable on LeftPlan , RightPlan or
426     * on both and computes the cost accordingly.It also takes care when the
427     * local condition is null as condition being shifted to singleTablePlan
428     * Level.(eg A LOJ B on B.B1 = 2)
429     * It maintains the mapping of condition and the way of Execution ie
430     * (solvable on which plan and condition mapping)
431     * @param conditionArg
432     * @param estimatedRowCount
433     * @return
434     * @throws DException
435     */

436    public double getCost(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
437       TableDetails[] conditionTableDetails = getTableDetailsOfCondition(conditionArg);
438       boolean solvableOntablePlanLeft = isSolvableOnTablePlanPassed(conditionTableDetails, tablePlanLeft.getTableDetails());
439       boolean solvableOntablePlanRight = isSolvableOnTablePlanPassed(conditionTableDetails, tablePlanRight.getTableDetails());
440       mappingOfConditionAndWayOfExecution = changeMappingOfConditionAndWayOfExecution(mappingOfConditionAndWayOfExecution, conditionArg);
441       if (joinCondition == null) {
442          return getCostForConditionPassedWhenLocalConditionIsNull(session, solvableOntablePlanLeft, solvableOntablePlanRight, conditionArg, estimatedRowCount);
443       }
444       if (solvableOntablePlanLeft && solvableOntablePlanRight) {
445          return getCostWhenConditionPassedIsSolvableOnBothPlan(session, conditionArg, estimatedRowCount);
446       }
447       if (solvableOntablePlanLeft) {
448          if (isConditionBelongsToBothPlanAndSeekable(joinCondition) != TypeConstants.NOSEEK) {
449             return getCostWhenConditionPassedIsSolvableOnLeftPlanAndSeekable(session, conditionArg, estimatedRowCount);
450          }
451          return getCostWhenConditionPassedIsSolvableOnLeftPlanAndConditionIsNonSeekable(session, conditionArg, estimatedRowCount);
452       }
453       if (solvableOntablePlanRight) {
454          if (isConditionBelongsToBothPlanAndSeekable(joinCondition)!= TypeConstants.NOSEEK) {
455             return getCostWhenConditionPassedIsSolvableOnRightPlanAndSeekable(session, conditionArg, estimatedRowCount);
456          }
457          return getCostWhenConditionPassedIsSolvableOnRightPlanAndIsNonSeekable(session, conditionArg, estimatedRowCount);
458       }
459       throw new DException("DSE3530", new Object JavaDoc[] {conditionArg.toString()});
460    }
461
462    /**
463     * Calculates the cost when local join condition is null.
464     * Case Arises When
465     * A Loj B on B.b1 = 1 Loj C on B.b1 = C.c1
466     * In this case local joinCondition on A Loj B is null and condition
467     * B.b1 = C.c1 is passed for computation of cost.
468     * There may be three cases for passed condition
469     * 1. It belongs to both plans
470     * 2. It belongs to left plan.
471     * 3. It belongs to right plan.
472     * Cost is calculated as per the case.
473     * @param solvableOntablePlanLeft
474     * @param solvableOntablePlanRight
475     * @param conditionArg
476     * @param estimatedRowCount
477     * @return
478     * @throws DException
479     */

480    private double getCostForConditionPassedWhenLocalConditionIsNull(_ServerSession session, boolean solvableOntablePlanLeft, boolean solvableOntablePlanRight, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
481       if (solvableOntablePlanLeft && solvableOntablePlanRight) {
482          return getCostWhenConditionNullAndConditionPassedSolvableOnBothPlan(session, conditionArg);
483       }
484       if (solvableOntablePlanLeft) {
485          return getCostWhenConditionNullAndWhenConditionPassedIsSolvableOnLeftPlan(session, conditionArg, estimatedRowCount);
486       }
487       if (solvableOntablePlanRight) {
488          return getCostWhenConditionNullAndWhenConditionPassedIsSolvableOnRightPlan(session, conditionArg, estimatedRowCount);
489       }
490       throw new DException("DSE3530", new Object JavaDoc[] {conditionArg.toString()});
491    }
492
493    /**
494     * Same as getCostWithoutOrder( booleanvalueexpression conditionArg , long estimatedRowCount)
495     * except the difference getCostWithOutOrder is called instead of getCost
496     * method.
497     * @param conditionArg
498     * @param estimatedRowCount
499     * @return
500     * @throws DException
501     */

502    public double getCostWithoutOrder(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
503       TableDetails[] conditionTableDetails = getTableDetailsOfCondition(conditionArg);
504       boolean solvableOnLeftPlan = isSolvableOnTablePlanPassed(conditionTableDetails, tablePlanLeft.getTableDetails());
505       boolean solvableOnRightPlan = isSolvableOnTablePlanPassed(conditionTableDetails, tablePlanRight.getTableDetails());
506       mappingOfConditionAndWayOfExecutionWithoutOrder = changeMappingOfConditionAndWayOfExecution(mappingOfConditionAndWayOfExecutionWithoutOrder, conditionArg);
507       if (joinCondition == null) {
508          return getCostWithoutOrderForConditionPassedWhenLocalConditionIsNull(session, solvableOnLeftPlan, solvableOnRightPlan, conditionArg, estimatedRowCount);
509       }
510       if (solvableOnLeftPlan && solvableOnRightPlan) {
511          return getCostWithoutOrderWhenConditionSolvableOnBothPlans(session, conditionArg);
512       }
513       if (solvableOnLeftPlan) {
514          if (isConditionBelongsToBothPlanAndSeekable(joinCondition)!= TypeConstants.NOSEEK) {
515             return getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionSeekable(session, conditionArg, estimatedRowCount);
516          }
517          return getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionNotSeekable(session, conditionArg, estimatedRowCount);
518       }
519       if (solvableOnRightPlan) {
520          if (isConditionBelongsToBothPlanAndSeekable(joinCondition)!= TypeConstants.NOSEEK) {
521             return getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionSeekable(session, conditionArg, estimatedRowCount);
522          }
523          return getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionNotSeekable(session, conditionArg, estimatedRowCount);
524       }
525       throw new DException("DSE3530", new Object JavaDoc[] {conditionArg.toString()});
526    }
527
528    /**
529     * This method is needed when condition is solvable on both plans. So filtered
530     * resultset with passed condition is formed on underlying resultset.
531     * @param session
532     * @param conditionArg
533     * @return
534     * @throws DException
535     */

536
537    private _Iterator executeWhenConditionSolvableOnBothPlans(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
538       return getNonIndexedFilteredIterator(execute(session), session, conditionArg);
539    }
540
541    /**
542     * This method is used to obtain resultset when passed condition is solvable
543     * on left plan and local join condition can't be used for seek. So a
544     * filtered resultset is formed on cartesian of underlying resultsets.
545     *
546     * @param session
547     * @param conditionArg
548     * @return
549     * @throws DException
550     */

551
552    private _Iterator executeWhenConditionSolvableOnLeftPlanAndConditionNonSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
553       _Iterator iter1 = tablePlanLeft.execute(session, conditionArg);
554       _Iterator iter2 = tablePlanRight.execute(session);
555       _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
556           , hasRecordColumns);
557       _Iterator iter3=getNonIndexedFilteredIterator(niter3, session, conditionArg);
558       iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
559       return iter3;
560    }
561
562    /**
563     * This method is used to obtain resultset when passed condition is solvable
564     * on right plan and local join condition is seekable. So the resultset of
565     * right plan is seeked into resultset of left plan. Since right seek left
566     * option is opted, order will be solved on the top, Thats why a sorted
567     * resultset is formed.
568     * @param session
569     * @param conditionArg
570     * @return
571     * @throws DException
572     */

573
574    private _Iterator executeWhenConditionSolvableOnRightPlanAndConditionSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
575       _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
576       _Iterator iter2 = tablePlanLeft.executeWithOutOrder(session, joinCondition);
577       _Iterator niter3 = new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanRight, joinCondition.getColumnDetails()), hasRecordColumns);
578       niter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
579       _Order ord = getOrder();
580       if (ord != null) {
581          niter3 = GeneralPurposeStaticClass.getTemporaryIndexIterator(niter3, this, session, ord);
582       }
583       return niter3;
584    }
585
586    /**
587     * This method is used to obtain resultset when passed condition is solvable
588     * on right plan and local join condition can't be used for seek. So a
589     * filtered resultset is formed on cartesian of underlying resultsets. Since
590     * condition is shifted on right plan, order will be solved on the top,
591     * Thats why a sorted resultset is also formed.
592     * @param session
593     * @param conditionArg
594     * @return
595     * @throws DException
596     */

597
598    private _Iterator executeWhenConditionSolvableOnRightPlanAndConditionNonSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
599       _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
600       _Iterator iter2 = tablePlanLeft.executeWithoutOrder(session);
601       _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
602           , hasRecordColumns);
603       niter3 = getNonIndexedFilteredIterator(niter3, session, conditionArg);
604       niter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
605       _Order ord = getOrder();
606       if (ord != null) {
607          niter3 = GeneralPurposeStaticClass.getTemporaryIndexIterator(niter3, this, session, ord);
608       }
609       return niter3;
610
611    }
612
613    /**
614     * This method is used to obtain resultset when passed condition is solvable
615     * on left plan and local join condition is null. So a resultset for
616     * cartesian of underlying resultsets is formed.
617     * @param session
618     * @param conditionArg
619     * @return
620     * @throws DException
621     */

622
623    private _Iterator executeWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
624       _Iterator iter1 = tablePlanLeft.execute(session, conditionArg);
625       _Iterator iter2 = tablePlanRight.execute(session);
626       return new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
627                                         , hasRecordColumns);
628    }
629
630    /**
631     * This method is used to obtain resultset when passed condition is solvable
632     * on right plan and local join condition is null. So a resultset for
633     * cartesian of underlying resultsets is formed. Since
634     * condition is shifted on right plan, order will be solved on the top,
635     * Thats why a sorted resultset is also formed.
636     * @param session
637     * @param conditionArg
638     * @return
639     * @throws DException
640     */

641
642    private _Iterator executeWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
643       _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
644       _Iterator iter2 = tablePlanLeft.executeWithoutOrder(session);
645       _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2} , hasRecordColumns);
646       _Order ord = getOrder();
647       if (ord != null) {
648          niter3 = GeneralPurposeStaticClass.getTemporaryIndexIterator(niter3, this, session, ord);
649       }
650       return niter3;
651
652    }
653
654    /**
655     * This method is used to obtain resultset when passed condition is solvable
656     * on both plans and local join condition is null. So a resultset for
657     * cartesian of underlying resultsets is formed.
658     * @param session
659     * @param conditionArg
660     * @return
661     * @throws DException
662     */

663
664
665    private _Iterator executeWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
666       _Iterator iter1 = tablePlanRight.execute(session);
667       _Iterator iter2 = tablePlanLeft.execute(session);
668       _Iterator iter = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
669                                                   , hasRecordColumns);
670       _Iterator iter3=getNonIndexedFilteredIterator(iter, session, conditionArg);
671       iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
672       return iter3;
673    }
674
675    /**
676     * This method returns the Iterator based on the way which is set in the
677     * corresponding getCostWithOutOrder method. It don't take care of Order.
678     * It can have following ways to execute -
679     * 1. LeftSeekRight
680     * 2. RightSeekLeft
681     * 3. NoSeek
682     * 4. Join Condition is null
683     * @param session
684     * @return
685     * @throws DException
686     */

687
688    public _Iterator executeWithoutOrder(_ServerSession session) throws DException {
689       if (executionPath == -1) {
690          getCostWithoutOrder(session);
691       }
692       switch (executionPath) {
693          case WHENLEFTSEEKRIGHT:
694             return executeWhenLeftSeekRightWithoutOrder(session);
695
696          case WHENRIGHTSEEKLEFT:
697             return executeWhenRightSeekLeftWithoutOrder(session);
698
699          case NOSEEK:
700             return executeWhenNoSeekWithoutOrder(session);
701
702          case CONITION_NULL:
703             return executeWithoutOrderWhenConditionNull(session);
704       }
705       throw new DException("DSE3531", null);
706    }
707
708    /**
709     * This method returns the Iterator based on the way which is set in the
710     * corresponding getCost method. It doesn't take care of Order.
711     * It can have following ways to execute -
712     * 1. Passed join Condition belongs to both plans
713     * i. Local Join Condition is Null
714     * ii. Local Join Condition is Non Null
715     * 2. Passed join Condition belongs to left plan
716     * i. Local Join Condition is Null
717     * ii. Local Join Condition is Seekable
718     * iii. Local Join Condition is NonSeekable
719     * 3. Passed join Condition belongs to right plan
720     * i. Local Join Condition is Null
721     * ii. Local Join Condition is Seekable
722     * iii. Local Join Condition is NonSeekable
723     * @param session
724     * @param conditionArg
725     * @return
726     * @throws DException
727     */

728
729    public _Iterator executeWithOutOrder(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
730       switch (searchCostCaluledFrom(conditionArg, false)) {
731          case SOLVABLE_ON_BOTH:
732             return executeWithOutOrderWhenConditionSolvaleOnBothPlans(session, conditionArg);
733
734          case SOLVABLE_ON_TABLEPLAN1_AND_SEEKABLE:
735             return executeWithOutOrderWhenConditionSolvableOnLeftPlanAndSeekable(session, conditionArg);
736
737          case SOLVABLE_ON_TABLEPLAN1_AND_NONSEEKABLE:
738             return executeWithOutOrderWhenConditionSolvableOnLeftPlanAndNonSeekable(session, conditionArg);
739
740          case SOLVABLE_ON_TABLEPLAN2_AND_SEEKABLE:
741             return executeWithOutOrderWhenConditionSolvableOnRightPlanAndSeekable(session, conditionArg);
742
743          case SOLVABLE_ON_TABLEPLAN2_AND_NONSEEKABLE:
744             return executeWithOutOrderWhenConditionSolvableOnRightPlanAndNonSeekable(session, conditionArg);
745
746          case SOLVABLE_ON_TABLEPLAN1_AND_CONDITION_NULL:
747             return executeWithOutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(session, conditionArg);
748
749          case SOLVABLE_ON_TABLEPLAN2_AND_CONDITION_NULL:
750             return executeWithOutOrderWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(session, conditionArg);
751
752          case SOLVABLE_ON_BOTH_AND_CONDITION_NULL:
753             return executeWithOutOrderWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(session, conditionArg);
754       }
755       throw new DException("DSE3527", new Object JavaDoc[] {conditionArg.toString()});
756    }
757
758    /**
759     * Checks whether tables involved in condition belong to plan's table.
760     * @param conditionTds
761     * @param planTds
762     * @return
763     * @throws DException
764     */

765
766    private boolean isSolvableOnTablePlanPassed(TableDetails[] conditionTds, TableDetails[] planTds) throws DException {
767       for (int i = 0, length = conditionTds.length; i < length; i++) {
768          for (int j = 0, len = planTds.length; j < len; j++) {
769             if (conditionTds[i] == planTds[j]) {
770                return true;
771             }
772          }
773       }
774       return false;
775    }
776
777    /**
778     * Returns Tables involved in the condition
779     * @param condition
780     * @return
781     * @throws DException
782     */

783
784    private TableDetails[] getTableDetailsOfCondition(booleanvalueexpression condition) throws DException {
785       ColumnDetails[] cd = condition.getColumnDetails();
786       ArrayList list = new ArrayList();
787       for (int i = 0; i < cd.length; i++) {
788         GeneralPurposeStaticClass.getChildTableDetails(list,cd[i]);
789       }
790       HashMap hMap = new HashMap(5);
791       for (int i = 0, size = list.size(); i < size; i++) {
792         TableDetails td = ((ColumnDetails) list.get(i)).getTableDetails();
793         hMap.put(td, td);
794       }
795       return (TableDetails[]) hMap.values().toArray(new TableDetails[hMap.size()]);
796    }
797
798    /**
799     * Returns the references which belong to passed plan.
800     * @param tablePlan
801     * @param references
802     * @return
803     * @throws DException
804     */

805
806    protected _Reference[] getDesiredReferences(_TablePlan tablePlan, ColumnDetails[] references) throws DException {
807       ArrayList aList = new ArrayList();
808      ArrayList childs = new ArrayList();
809       TableDetails tableNames[] = tablePlan.getTableDetails();
810       for (int i = 0; i < references.length; i++) {
811          for (int j = 0; j < tableNames.length; j++) {
812          int type = references[i].getType();
813          if (type == TypeConstants.SCALARFUNCTION ||
814              type == TypeConstants.CASEEXPRESSION ||
815              type == TypeConstants.FUNCTIONAL
816              ) {
817            childs.clear();
818            GeneralPurposeStaticClass.getChildTableDetails(childs, references[i]);
819
820            for (int k = 0; k < childs.size(); k++) {
821              ColumnDetails childColumnDetail = (ColumnDetails) childs.get(k);
822              if (childColumnDetail.getTable() != tableNames[j])
823                break;
824              if (!aList.contains(childColumnDetail))
825                aList.add(childColumnDetail);
826            }
827          }
828          else if (references[i].getTable() == tableNames[j]) {
829                aList.add(references[i]);
830                break;
831             }
832          }
833       }
834      _Reference refArray[] = (_Reference[]) aList.toArray(new ColumnDetails[
835          aList.size()]);
836       if (refArray.length == 0) {
837       }
838       return refArray;
839    }
840
841    /**
842     * It calculates the cost when left plan seeks into right plan. Algo -
843     * 1. Cost for left plan is calculated.
844     * 2. Cost for right plan, on the basis of join condition and number of rows
845     * of left plan, is calculated.
846     * 3. Cumulative cost of above two steps is resultant cost.
847     * @param session
848     * @return
849     * @throws DException
850     */

851
852    protected double getCostWhenLeftSeekRight(_ServerSession session) throws DException {
853      long rowCount1 = tablePlanLeft.getRowCount(session);
854       double costWithBVE1 = tablePlanRight.getCost(session, joinCondition, rowCount1);
855       double cost1 = tablePlanLeft.getCost(session);
856       double totalCost1 = cost1 + costWithBVE1;
857       return totalCost1;
858    }
859
860    /**
861     * It calculates the cost when right plan seeks into left plan. Algo -
862     * 1. Cost for right plan is calculated.
863     * 2. Cost for left plan, on the basis of join condition and number of rows
864     * of right plan, is calculated.
865     * 3. Cost for temporary order is calculated
866     * 4. Cumulative cost of above three steps is resultant cost.
867     * @param session
868     * @return
869     * @throws DException
870     */

871
872    protected double getCostWhenRightSeekLeft(_ServerSession session) throws DException {
873       long rowCount2 = tablePlanRight.getRowCount(session);
874       double costWithBVE2 = tablePlanLeft.getCostWithoutOrder(session, joinCondition, rowCount2);
875       double cost2 = tablePlanRight.getCostWithoutOrder(session);
876       double totalCost2 = cost2 + costWithBVE2;
877       _Order order = getOrder();
878       if (order != null) {
879          totalCost2 += CostCalculator.getCostForTemporaryOrder(getRowCount(session));
880       }
881       return totalCost2;
882    }
883
884    /**
885     * It calculates the cost when local join condition is non seekable. Algo -
886     * 1. Cost for left plan is calculated.
887     * 2. Cost for right plan is calculated.
888     * 3. Cost for condition evaluation on cartesian of rows of underlying plan,
889     * is calculated.
890     * 3. Cumulative cost of above three steps is resultant cost.
891     * @param session
892     * @return
893     * @throws DException
894     */

895
896    protected double getCostWhenNoSeek(_ServerSession session) throws DException {
897       long rows = tablePlanLeft.getRowCount(session);
898       rows *= tablePlanRight.getRowCount(session);
899       return tablePlanLeft.getCost(session) * tablePlanRight.getCost(session) + joinCondition.getCost(rows, true);
900    }
901
902    /**
903     * It allows user to obtain the resultset when left seek right option is
904     * opted. Algo -
905     * 1. Resultset for left plan is obtained.
906     * 2. Resultset for right plan is obtained on the basis of join condition.
907     * 3. Finally a join resultset is formed with the help of both resultsets
908     * obtained in step1 and step2.
909     * @param session
910     * @return
911     * @throws DException
912     */

913
914    protected _Iterator executeWhenLeftSeekRight(_ServerSession session) throws DException {
915       _Iterator iter1 = tablePlanLeft.execute(session);
916       ColumnDetails[] references = joinCondition.getColumnDetails();
917       _Iterator iter2 = tablePlanRight.execute(session, joinCondition);
918       _Iterator iter3 = new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanLeft, references), hasRecordColumns);
919       iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition() );
920       return iter3;
921    }
922
923    /**
924     * It allows user to obtain the resultset when right seek left option is
925     * opted. Algo -
926     * 1. Resultset for right plan is obtained.
927     * 2. Resultset for left plan is obtained on the basis of join condition.
928     * 3. Then a join resultset is formed with the help of both resultsets
929     * obtained in step1 and step2.
930     * 4. Finally a sorted resultset is formed based on the step 3.
931     * @param session
932     * @return
933     * @throws DException
934     */

935
936    protected _Iterator executeWhenRightSeekLeft(_ServerSession session) throws DException {
937       _Iterator iter1 = tablePlanRight.executeWithoutOrder(session);
938       _Iterator iter2 = tablePlanLeft.executeWithOutOrder(session, joinCondition);
939       ColumnDetails[] references = joinCondition.getColumnDetails();
940       _Iterator iter3 = new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanRight, references), hasRecordColumns);
941       iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
942       _Order order = getOrder();
943       if (order != null) {
944          iter3 = GeneralPurposeStaticClass.getTemporaryIndexIterator(iter3, this, session, order);
945       }
946       return iter3;
947    }
948
949    /**
950     * It allows user to obtain the resultset when local join conditon is not
951     * seekable. Algo -
952     * 1. Resultset for left plan is obtained.
953     * 2. Resultset for rigth plan is obtained on the basis of join condition.
954     * 3. Finally a resultset for applying condition on both resultsets
955     * obtained in step1 and step2, is formed.
956     * @param session
957     * @return
958     * @throws DException
959     */

960
961    private _Iterator executeWhenNoSeek(_ServerSession session) throws DException {
962       _Iterator iter1 = tablePlanLeft.execute(session);
963       _Iterator iter2 = tablePlanRight.execute(session);
964       _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}, hasRecordColumns);
965       if (joinCondition == null) {
966          return niter3;
967       }
968       _Iterator iter= getNonIndexedFilteredIterator(niter3, session, joinCondition);
969       iter.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
970       return iter;
971    }
972
973    /**
974     * method is used to search the execution plan for the condition passed.
975     * boolean is used to decide which mapping is to search for.
976     * true: mapping with order
977     * false: mapping without order
978     * @param conditionArg
979     * @param orderOrWithoutOrder
980     * @return
981     * @throws DException
982     */

983    protected int searchCostCaluledFrom(booleanvalueexpression conditionArg, boolean orderOrWithoutOrder) throws DException {
984       Object JavaDoc[][] mappingOfExecution = orderOrWithoutOrder ? mappingOfConditionAndWayOfExecution : mappingOfConditionAndWayOfExecutionWithoutOrder;
985       try {
986          for (int i = 0; i < mappingOfExecution.length; i++) {
987             if (mappingOfExecution[i][0] == conditionArg) {
988                return ( (Integer JavaDoc) mappingOfExecution[i][1]).intValue();
989             }
990          }
991       } catch (NullPointerException JavaDoc npe) {
992          P.print(mappingOfExecution);
993          throw npe;
994       }
995       throw new DException("DSE3527", new Object JavaDoc[] {conditionArg.toString()});
996    }
997
998    /**
999     * This method returns the resultset based on the way which is set in the
1000    * corresponding getCost method. It can have following ways to execute -
1001    * 1. LeftSeekRight
1002    * 2. RightSeekLeft
1003    * 3. NoSeek
1004    * 4. Join Condition is null
1005    * @param session
1006    * @return
1007    * @throws DException
1008    */

1009
1010   public _Iterator execute(_ServerSession session) throws DException {
1011      switch (executionPath) {
1012         case WHENLEFTSEEKRIGHT:
1013            return executeWhenLeftSeekRight(session);
1014         case WHENRIGHTSEEKLEFT:
1015            return executeWhenRightSeekLeft(session);
1016         case NOSEEK:
1017            return executeWhenNoSeek(session);
1018         case CONITION_NULL:
1019            return executeWhenConditionNull(session);
1020      }
1021      throw new DException("DSE3531", null);
1022   }
1023
1024   /**
1025    * This method returns the resultset based on the way which is set in the
1026    * corresponding getCost method. It can have following ways to execute -
1027    * 1. Passed join Condition belongs to both plans
1028    * i. Local Join Condition is Null
1029    * ii. Local Join Condition is Non Null
1030    * 2. Passed join Condition belongs to left plan
1031    * i. Local Join Condition is Null
1032    * ii. Local Join Condition is Seekable
1033    * iii. Local Join Condition is NonSeekable
1034    * 3. Passed join Condition belongs to right plan
1035    * i. Local Join Condition is Null
1036    * ii. Local Join Condition is Seekable
1037    * iii. Local Join Condition is NonSeekable
1038    * @param session
1039    * @param conditionArg
1040    * @return
1041    * @throws DException
1042    */

1043
1044   public _Iterator execute(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1045      switch (searchCostCaluledFrom(conditionArg, true)) {
1046         case SOLVABLE_ON_BOTH:
1047            return executeWhenConditionSolvableOnBothPlans(session, conditionArg);
1048
1049         case SOLVABLE_ON_TABLEPLAN1_AND_SEEKABLE:
1050            return executeWhenConditionSolvableOnLeftPlanAndConditionSeekable(session, conditionArg);
1051
1052         case SOLVABLE_ON_TABLEPLAN1_AND_NONSEEKABLE:
1053            return executeWhenConditionSolvableOnLeftPlanAndConditionNonSeekable(session, conditionArg);
1054
1055         case SOLVABLE_ON_TABLEPLAN2_AND_SEEKABLE:
1056            return executeWhenConditionSolvableOnRightPlanAndConditionSeekable(session, conditionArg);
1057
1058         case SOLVABLE_ON_TABLEPLAN2_AND_NONSEEKABLE:
1059            return executeWhenConditionSolvableOnRightPlanAndConditionNonSeekable(session, conditionArg);
1060
1061         case SOLVABLE_ON_TABLEPLAN1_AND_CONDITION_NULL:
1062            return executeWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(session, conditionArg);
1063
1064         case SOLVABLE_ON_TABLEPLAN2_AND_CONDITION_NULL:
1065            return executeWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(session, conditionArg);
1066
1067         case SOLVABLE_ON_BOTH_AND_CONDITION_NULL:
1068            return executeWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(session, conditionArg);
1069      }
1070      throw new DException("DSE3527", new Object JavaDoc[] {conditionArg.toString()});
1071   }
1072
1073   /**
1074    * This method allows user to obtain resultset when condition is solvable on
1075    * left plan and local join condition is seekable. Algo -
1076    * 1. Resultset of left plan is obtained with passed condition.
1077    * 2. Resultset of right plan is obtained with local join condition.
1078    * 3. Finally a join resultset on the both resultsets is formed.
1079    * @param session
1080    * @param conditionArg
1081    * @return
1082    * @throws DException
1083    */

1084
1085   private _Iterator executeWhenConditionSolvableOnLeftPlanAndConditionSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1086      _Iterator iter1 = tablePlanLeft.execute(session, conditionArg);
1087      _Iterator iter2 = tablePlanRight.execute(session, joinCondition);
1088      _Iterator iter3=new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanLeft, joinCondition.getColumnDetails()), hasRecordColumns);
1089      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1090      return iter3;
1091   }
1092
1093   public String JavaDoc getVerifier(String JavaDoc tablePlanType) throws DException {
1094      inc();
1095      StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1096      buffer.append(tabW("[ " + tablePlanType + " ]"));
1097      buffer.append("\n" + tablePlanLeft.getVerifier());
1098      buffer.append("\n" + tablePlanRight.getVerifier());
1099      inc();
1100      buffer.append(tab("[" + joinCondition + "]"));
1101      switch (executionPath) {
1102         case -1:
1103            buffer.append(tab("[-1]"));
1104            break;
1105         case WHENLEFTSEEKRIGHT:
1106            buffer.append(tab("[LSR]"));
1107            break;
1108         case WHENRIGHTSEEKLEFT:
1109            buffer.append(tab("[RSL]"));
1110            break;
1111         case NOSEEK:
1112            buffer.append(tab("[NO]"));
1113            break;
1114      }
1115      dec();
1116      buffer.append(tab("[/ " + tablePlanType + " ]"));
1117      dec();
1118      return buffer.toString();
1119   }
1120
1121   public String JavaDoc toString(String JavaDoc tablePlanType) {
1122      StringBuffer JavaDoc strbuffer = new StringBuffer JavaDoc();
1123      strbuffer.append(tablePlanType);
1124      strbuffer.append("\n\t[" + tablePlanLeft + "]");
1125      strbuffer.append("\n\t[" + tablePlanRight + "]");
1126      strbuffer.append("\n\t[" + joinCondition + "]");
1127      switch (executionPath) {
1128         case -1:
1129            strbuffer.append("[-1]");
1130            break;
1131         case WHENLEFTSEEKRIGHT:
1132            strbuffer.append("[LSR]");
1133            break;
1134         case WHENRIGHTSEEKLEFT:
1135            strbuffer.append("[RSL]");
1136            break;
1137         case NOSEEK:
1138            strbuffer.append("[NO]");
1139            break;
1140      }
1141      return strbuffer.toString();
1142   }
1143
1144   /**
1145    * This method is used to check how many tables belong to passed plan.
1146    * @param tableDetails
1147    * @param tablePlan
1148    * @return
1149    * @throws DException
1150    */

1151
1152   protected short checkForTablesInTablePlan(TableDetails tableDetails[], _TablePlan tablePlan) throws DException {
1153      TableDetails[] tableDetailsFromPlan = tablePlan.getTableDetails();
1154      int length1 = tableDetails.length;
1155      int length2 = tableDetailsFromPlan.length;
1156      short count = 0;
1157      for (int i = 0; i < length1; i++) {
1158         for (int j = 0; j < length2; j++) {
1159            if (tableDetails[i] == tableDetailsFromPlan[j]) {
1160               count++;
1161            }
1162         }
1163      }
1164      return count;
1165   }
1166
1167   /**
1168    * Check whether plan is of qualified type or not.
1169    * @param type
1170    * @return
1171    * @throws DException
1172    */

1173
1174   protected boolean qualifiedPlan(int type) throws DException {
1175      return (type == QUALIFIEDLEFTPLAN || type == QUALIFIEDRIGHTPLAN || type == QUALIFIEDFULLPLAN || type == QUALIFIEDCROSSPLAN) ? true : false;
1176   }
1177
1178   /**
1179    * This method is used to calculate the cost when local join condition is
1180    * null.
1181    * @param session
1182    * @return
1183    * @throws DException
1184    */

1185
1186   protected double getCostWhenConditionNull(_ServerSession session) throws DException {
1187      return tablePlanLeft.getCost(session) * tablePlanRight.getCost(session);
1188   }
1189
1190   /**
1191    * This method is used to obtain the resultset when local join condition is
1192    * null. Algo -
1193    * 1. Resultset of left plan is obtained.
1194    * 2. Resultset of right plan is obtained.
1195    * 3. Finally a cartesian resultset on the both resultsets is formed.
1196    * @param session
1197    * @return
1198    * @throws DException
1199    */

1200
1201   protected _Iterator executeWhenConditionNull(_ServerSession session) throws DException {
1202      return new NestedLoopJoinIterator(new _Iterator[] {tablePlanLeft.execute(session), tablePlanRight.execute(session)}
1203                                        , hasRecordColumns);
1204   }
1205
1206   /**
1207    * This method is used to check whether the joinCondition is seekable and
1208    * belongs to both the child plans or not.
1209    * @param joinCondition
1210    * @return
1211    * @throws DException
1212    */

1213
1214   protected boolean isConditionBelongsToBothPlanAndSeekableold(booleanvalueexpression joinCondition) throws DException {
1215      if (joinCondition.canUseForSeek() == TypeConstants.NOSEEK) {
1216         return false;
1217      }
1218      ArrayList list = new ArrayList(3);
1219      ColumnDetails[] cd = joinCondition.getColumnDetails();
1220      for (int i = 0; i < cd.length; i++) {
1221         TableDetails td = cd[i].getTableDetails();
1222         if (td != null) {
1223            list.add(td);
1224         }
1225      }
1226      TableDetails tDArray[] = (TableDetails[]) list.toArray(new TableDetails[list.size()]);
1227      int length = tDArray.length;
1228      int i = 0;
1229      for (; i < length; i++) {
1230         if (tablePlanLeft.ifExists(tDArray[i])) {
1231            break;
1232         }
1233      }
1234      if (i == length) {
1235         return false;
1236      }
1237      for (i = 0; i < length; i++) {
1238         if (tablePlanRight.ifExists(tDArray[i])) {
1239            break;
1240         }
1241      }
1242      if (i == length) {
1243         return false;
1244      }
1245      return true;
1246   }
1247/**
1248 * This method is used to check whether the joinCondition is seekable and
1249 * belongs to both the child plans or not.
1250 * @param joinCondition
1251 * @return
1252 * @throws DException
1253 */

1254
1255protected int isConditionBelongsToBothPlanAndSeekable(booleanvalueexpression joinCondition) throws DException {
1256  int seekType = joinCondition.canUseForSeek();
1257  if (seekType == TypeConstants.NOSEEK) {
1258    return seekType;
1259   }
1260   TableDetails tDArray[] = GeneralPurposeStaticClass.getAllTableDetails(joinCondition);
1261   int length = tDArray.length;
1262   int i = 0;
1263   for (; i < length; i++) {
1264      if (tablePlanLeft.ifExists(tDArray[i])) {
1265         break;
1266      }
1267   }
1268   if (i == length) {
1269      return TypeConstants.NOSEEK;
1270   }
1271   for (i = 0; i < length; i++) {
1272      if (tablePlanRight.ifExists(tDArray[i])) {
1273         break;
1274      }
1275   }
1276   if (i == length) {
1277      return TypeConstants.NOSEEK;
1278   }
1279   return seekType;
1280}
1281
1282   /**
1283    * This method is used to check whether any functional column is present in
1284    * join condition or not.
1285    * @param tableDetails
1286    * @return
1287    * @throws DException
1288    */

1289
1290   protected boolean isTableInvolvedIsNull(_JoinRelation joinRelation) throws DException {
1291      TableDetails[] tableDetails = joinRelation.getTableDetails();
1292      for (int i = 0; i < tableDetails.length; i++) {
1293         if (tableDetails[i] == null) {
1294            return true;
1295         }
1296      }
1297      return false;
1298   }
1299
1300   /**
1301    * Returns the Order of Plan , It merges the Order Of Left and Right Plans
1302    * @return
1303    * @throws DException
1304    */

1305
1306   public _Order getOrder() throws DException {
1307      _Order order1 = tablePlanLeft.getOrder();
1308      _Order order2 = tablePlanRight.getOrder();
1309      return (_Order) GeneralPurposeStaticClass.getJoinOrdered(order1, order2);
1310   }
1311
1312   /**
1313    * This method merges the joinRelation and passed Table plan with the
1314    * lowest level appropriate plan which belongs to passed TableDetail.
1315    * @param tablePlans
1316    * @return
1317    * @throws DException
1318    */

1319
1320   public void merge(_TablePlan tablePlan, _JoinRelation joinRelation, TableDetails tableDetails) throws DException {
1321      boolean leftMatch = tablePlanLeft.ifExists(tableDetails);
1322      _TablePlan tPlan = leftMatch ? tablePlanLeft : tablePlanRight;
1323      int type = tPlan.getType();
1324      if (!qualifiedPlan(type)) {
1325         if (leftMatch) {
1326            tablePlanLeft = handleWhileTablePlanPassedIsSingleTablePlan(tablePlan, joinRelation, leftMatch);
1327            childPlans[0] = tablePlanLeft;
1328         } else {
1329            tablePlanRight = handleWhileTablePlanPassedIsSingleTablePlan(tablePlan, joinRelation, leftMatch);
1330            childPlans[1] = tablePlanRight;
1331         }
1332         return;
1333      }
1334      ( (_QualifiedPlan) tPlan).merge(tablePlan, joinRelation, tableDetails);
1335   }
1336
1337   /**
1338    * This method is used to merge passed tableplan with this table plan based
1339    * on the passed condition, when passed tableplan is SingleTablePlan. In this
1340    * case TwoTableJoinPlan is formed and returned.
1341    * @param tablePlan
1342    * @param joinRelation
1343    * @param leftMatch
1344    * @return
1345    * @throws DException
1346    */

1347
1348   private _TablePlan handleWhileTablePlanPassedIsSingleTablePlan(_TablePlan tablePlan, _JoinRelation joinRelation, boolean leftMatch) throws DException {
1349      return leftMatch ? new TwoTableJoinPlan(tablePlanLeft, tablePlan, joinRelation.getCondition()) :
1350          new TwoTableJoinPlan(tablePlanRight, tablePlan, joinRelation.getCondition());
1351   }
1352
1353   /**
1354    * This method is used to remove the cover of unExecutable plans like
1355    * OrderSequencePlan and TemporaryMergePlan.
1356    * @return
1357    * @throws DException
1358    */

1359
1360   public _TablePlan joinMissingLink() throws DException {
1361      tablePlanLeft = tablePlanLeft.joinMissingLink();
1362      tablePlanRight = tablePlanRight.joinMissingLink();
1363      childPlans = new _TablePlan[] {tablePlanLeft, tablePlanRight};
1364      return this;
1365   }
1366
1367   /**
1368    * The following methods are same as corresponding counterparts getCost
1369    * methods. In these method getCostWithoutOrder is called instead of getCost
1370    * methods.
1371    */

1372
1373   private double getCostWithoutOrderWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1374      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(TableExpressionConstants.SOLVABLE_ON_BOTH_AND_CONDITION_NULL);
1375      return (tablePlanLeft.getCostWithoutOrder(session) * tablePlanRight.getCostWithoutOrder(session) + conditionArg.getEstimatedRows(tablePlanLeft.getRowCount(session) * tablePlanRight.getRowCount(session)));
1376   }
1377
1378   private double getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1379      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_CONDITION_NULL);
1380      return tablePlanLeft.getCostWithoutOrder(session, conditionArg, estimatedRowCount) * tablePlanRight.getCostWithoutOrder(session);
1381   }
1382
1383   private double getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1384      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_CONDITION_NULL);
1385      double cost = tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount) * tablePlanLeft.getCostWithoutOrder(session);
1386      return cost;
1387   }
1388
1389   private double getCostWithoutOrderWhenConditionSolvableOnBothPlans(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1390      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_BOTH);
1391      double cost11 = getCostWithoutOrder(session);
1392      cost11 += conditionArg.getCost(getRowCount(session), false);
1393      cost11 *= getRowCount(session) * 110 / 100;
1394      return cost11;
1395   }
1396
1397   private double getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionNotSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1398      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_NONSEEKABLE);
1399      return tablePlanLeft.getCostWithoutOrder(session, conditionArg, estimatedRowCount) * tablePlanRight.getCostWithoutOrder(session);
1400   }
1401
1402   private double getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1403      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN1_AND_SEEKABLE);
1404      double cost1 = tablePlanLeft.getCostWithoutOrder(session, conditionArg, estimatedRowCount);
1405      long estimatedRow1 = tablePlanLeft.getEstimatedRows(conditionArg, estimatedRowCount, session);
1406      cost1 += tablePlanRight.getCostWithoutOrder(session, joinCondition, estimatedRow1);
1407      return cost1;
1408   }
1409
1410   private double getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionNotSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1411      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_NONSEEKABLE);
1412      return tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount) * tablePlanLeft.getCostWithoutOrder(session);
1413   }
1414
1415   private double getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionSeekable(_ServerSession session, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1416      mappingOfConditionAndWayOfExecutionWithoutOrder[mappingOfConditionAndWayOfExecutionWithoutOrder.length - 1][1] = new Integer JavaDoc(SOLVABLE_ON_TABLEPLAN2_AND_SEEKABLE);
1417      long estimatedRow2 = tablePlanRight.getEstimatedRows(conditionArg, estimatedRowCount, session);
1418      double cost2 = tablePlanRight.getCostWithoutOrder(session, conditionArg, estimatedRowCount);
1419      cost2 += tablePlanLeft.getCostWithoutOrder(session, joinCondition, estimatedRow2);
1420      return cost2;
1421   }
1422
1423   private double getCostWithoutOrderForConditionPassedWhenLocalConditionIsNull(_ServerSession session, boolean solvableOnLeftPlan, boolean solvableOnRightPlan, booleanvalueexpression conditionArg, long estimatedRowCount) throws DException {
1424      if (solvableOnLeftPlan && solvableOnRightPlan) {
1425         return getCostWithoutOrderWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(session, conditionArg);
1426      } else if (solvableOnLeftPlan) {
1427         return getCostWithoutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(session, conditionArg, estimatedRowCount);
1428      } else if (solvableOnRightPlan) {
1429         return getCostWithoutOrderWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(session, conditionArg, estimatedRowCount);
1430      }
1431      throw new DException("DSE3530", new Object JavaDoc[] {conditionArg.toString()});
1432   }
1433
1434   protected double getCostWhenLeftSeekRightWithoutOrder(_ServerSession session) throws DException {
1435      long rowCount1 = tablePlanLeft.getRowCount(session);
1436      double costWithBVE1 = tablePlanRight.getCostWithoutOrder(session, joinCondition, rowCount1);
1437      double cost1 = tablePlanLeft.getCostWithoutOrder(session);
1438      double totalCost1 = cost1 + costWithBVE1;
1439      return totalCost1;
1440   }
1441
1442   protected double getCostWhenRightSeekLeftWithoutOrder(_ServerSession session) throws DException {
1443      long rowCount2 = tablePlanRight.getRowCount(session);
1444      double costWithBVE2 = tablePlanLeft.getCostWithoutOrder(session, joinCondition, rowCount2);
1445      double cost2 = tablePlanRight.getCostWithoutOrder(session);
1446      double totalCost2 = cost2 + costWithBVE2;
1447      return totalCost2;
1448   }
1449
1450   protected double getCostWhenNoSeekWithoutOrder(_ServerSession session) throws DException {
1451      long rows = tablePlanLeft.getRowCount(session);
1452      rows *= tablePlanRight.getRowCount(session);
1453      return tablePlanLeft.getCostWithoutOrder(session) + tablePlanRight.getCostWithoutOrder(session) + joinCondition.getCost(rows, true);
1454   }
1455
1456   protected double getCostWithoutOrderWhenConditionNull(_ServerSession session) throws DException {
1457      return tablePlanLeft.getCostWithoutOrder(session) * tablePlanRight.getCostWithoutOrder(session);
1458   }
1459
1460   /**
1461    * The following methods are same as corresponding counterparts execute
1462    * methods. In these method executeWithoutOrder is called instead of execute
1463    * methods.
1464    */

1465
1466   private _Iterator executeWithOutOrderWhenConditionSolvaleOnBothPlans(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1467      return getNonIndexedFilteredIterator(executeWithoutOrder(session), session, conditionArg);
1468   }
1469
1470   private _Iterator executeWithOutOrderWhenConditionSolvableOnLeftPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1471      _Iterator iter1 = tablePlanLeft.executeWithOutOrder(session, conditionArg);
1472      _Iterator iter2 = tablePlanRight.executeWithoutOrder(session);
1473      return new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
1474                                        , hasRecordColumns);
1475   }
1476
1477   private _Iterator executeWithOutOrderWhenConditionSolvableOnRightPlanAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1478      _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
1479      _Iterator iter2 = tablePlanLeft.executeWithoutOrder(session);
1480      return new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
1481                                        , hasRecordColumns);
1482
1483   }
1484
1485   private _Iterator executeWithOutOrderWhenConditionSolvableOnBothPlansAndJoinConditionIsNull(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1486      _Iterator iter1 = tablePlanRight.executeWithoutOrder(session);
1487      _Iterator iter2 = tablePlanLeft.executeWithoutOrder(session);
1488      _Iterator iter = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
1489                                                  , hasRecordColumns);
1490      _Iterator iter3=getNonIndexedFilteredIterator(iter, session, conditionArg);
1491      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1492      return iter3;
1493   }
1494
1495   private _Iterator executeWithOutOrderWhenConditionSolvableOnRightPlanAndSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1496      _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
1497      _Iterator iter2 = tablePlanLeft.executeWithOutOrder(session, joinCondition);
1498      _Iterator iter3=new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanRight, joinCondition.getColumnDetails()), hasRecordColumns);
1499      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1500      return iter3;
1501
1502   }
1503
1504   private _Iterator executeWithOutOrderWhenConditionSolvableOnRightPlanAndNonSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1505      _Iterator iter1 = tablePlanRight.executeWithOutOrder(session, conditionArg);
1506      _Iterator iter2 = tablePlanLeft.executeWithoutOrder(session);
1507      _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}, hasRecordColumns);
1508      _Iterator iter3=getNonIndexedFilteredIterator(niter3, session, joinCondition);
1509      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1510      return iter3;
1511   }
1512
1513   private _Iterator executeWithOutOrderWhenConditionSolvableOnLeftPlanAndSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1514      _Iterator iter1 = tablePlanLeft.executeWithOutOrder(session, conditionArg);
1515      _Iterator iter2 = tablePlanRight.executeWithOutOrder(session, joinCondition);
1516      _Iterator iter3=new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanLeft, joinCondition.getColumnDetails()), hasRecordColumns);
1517      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1518      return iter3;
1519   }
1520
1521   private _Iterator executeWithOutOrderWhenConditionSolvableOnLeftPlanAndNonSeekable(_ServerSession session, booleanvalueexpression conditionArg) throws DException {
1522      _Iterator iter1 = tablePlanLeft.executeWithOutOrder(session, conditionArg);
1523      _Iterator iter2 = tablePlanRight.executeWithoutOrder(session);
1524      _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}, hasRecordColumns);
1525      _Iterator iter3=getNonIndexedFilteredIterator(niter3, session, joinCondition);
1526      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1527      return iter3;
1528   }
1529
1530   protected _Iterator executeWhenLeftSeekRightWithoutOrder(_ServerSession session) throws DException {
1531      _Iterator iter1 = tablePlanLeft.executeWithoutOrder(session);
1532      ColumnDetails[] references = joinCondition.getColumnDetails();
1533      _Iterator iter2 = tablePlanRight.executeWithOutOrder(session, joinCondition);
1534      _Iterator iter3=new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanLeft, references), hasRecordColumns);
1535      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1536      return iter3;
1537   }
1538
1539   protected _Iterator executeWhenRightSeekLeftWithoutOrder(_ServerSession session) throws DException {
1540      _Iterator iter1 = tablePlanRight.executeWithoutOrder(session);
1541      _Iterator iter2 = tablePlanLeft.executeWithOutOrder(session, joinCondition);
1542      ColumnDetails[] references = joinCondition.getColumnDetails();
1543      _Iterator iter3 = new JoinIterator(iter1, iter2, getDesiredReferences(tablePlanRight, references), hasRecordColumns);
1544      iter3.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1545      return iter3;
1546   }
1547
1548   protected _Iterator executeWhenNoSeekWithoutOrder(_ServerSession session) throws DException {
1549      _Iterator iter1 = tablePlanLeft.executeWithoutOrder(session);
1550      _Iterator iter2 = tablePlanRight.executeWithoutOrder(session);
1551      _Iterator niter3 = new NestedLoopJoinIterator(new _Iterator[] {iter1, iter2}
1552          , hasRecordColumns);
1553      if (joinCondition == null) {
1554         return niter3;
1555      }
1556      VariableValues variableValues = new VariableValues(joinCondition.getReferences(getTableDetails()), session);
1557      variableValues.setIterator(niter3);
1558      _Iterator iter = new NonIndexedFilterIterator(niter3, new ConditionVariableValue(variableValues, joinCondition));
1559      iter.setSpecificUnderlyingReferences(getUnderLyingReferencesOfJoinCondition());
1560      return iter;
1561   }
1562
1563   protected _Iterator executeWithoutOrderWhenConditionNull(_ServerSession session) throws DException {
1564      return new NestedLoopJoinIterator(new _Iterator[] {tablePlanLeft.executeWithoutOrder(session), tablePlanRight.executeWithoutOrder(session)}
1565                                        , hasRecordColumns);
1566   }
1567
1568   protected _Reference[] getUnderLyingReferencesOfJoinCondition() throws DException{
1569     _Reference[] toRet=null;
1570       TableDetails td1[] = tablePlanLeft.getTableDetails();
1571       TableDetails td2[] = tablePlanRight.getTableDetails();
1572       TableDetails[] td=new TableDetails[td1.length+td2.length];
1573       System.arraycopy(td1,0,td,0,td1.length);
1574       System.arraycopy(td2,0,td,td1.length,td2.length);
1575       toRet=GeneralPurposeStaticClass.getUnderLyingReferencesOnly(underlyingRef,td);
1576     return toRet;
1577   }
1578}
1579
Popular Tags