KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > daffodilwoods > daffodildb > server > sql99 > dql > iterator > table > JoinIterator


1 package com.daffodilwoods.daffodildb.server.sql99.dql.iterator.table;
2
3 import java.util.*;
4
5 import com.daffodilwoods.daffodildb.client.*;
6 import com.daffodilwoods.daffodildb.server.sql99.common.*;
7 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
8 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
9 import com.daffodilwoods.daffodildb.utils.field.*;
10 import com.daffodilwoods.database.resource.*;
11 import com.daffodilwoods.database.sqlinitiator.*;
12 import com.daffodilwoods.database.utility.P;
13 import com.daffodilwoods.daffodildb.server.sql99.dql.execution._OrderCount;
14 import com.daffodilwoods.daffodildb.server.sql99.dql.execution.OrderCount;
15 import com.daffodilwoods.daffodildb.utils.field.FieldBase;
16 import java.math.BigDecimal JavaDoc;
17 import com.daffodilwoods.daffodildb.utils.byteconverter.CCzufDpowfsufs;
18
19
20 /**
21  * <p>Title: JoinIterator</p>
22  * <p>Description: This Class is responsible for retrieval of records from a
23  * query having INNER JOIN of two tables with seekable join condition.
24  * A seekable join condition is condition in which two tables are seperated by
25  * equals operator having one table on one side and other table on another side
26  * of equal operator. For e.g. leftTable.leftTableColumn = rightTable.rightTableColumn.
27  * This Class has two Iterators from which records are to be retrieved. Join
28  * Condition is shifted to Right Iterator for better(optimized) execution of the
29  * condition. The Purpose of this class is to align both underlying iterators at
30  * valid record satisfying the given join condition.
31  * </p>
32  * <p>Copyright: Copyright (c) 2003</p>
33  * <p>Company: Daffodil S/W Ltd.</p>
34  * @author SelectTeam
35  * @version 1.0
36  */

37
38 public class JoinIterator extends BaseJoinIterator {
39
40   /**
41    * Variable representing join condition column of left Iterator.
42    */

43   _Reference[] leftColumnReferences;
44   /**
45    * A mapping of tables involved in the query and flag to denote LEFT or RIGHT
46    * tables corresponding to join condition.
47    */

48   private Object JavaDoc[][] tableDetailsMapping;
49   /**
50    * Variable representing the number of key columns of left iterator. It assists
51    * to move to a particular record for a non-group by query.
52    */

53   private int leftCount = -1; //to be Used for Counting the keyColumnInformation from leftIterator.
54
/**
55    * Variable representing the number of grouped columns that uniquely specify
56    * a record of left iterator. It assists to move to a particular record for a
57    * group by query.
58    */

59   private int leftKeyCount = 0;
60   /**
61    * Variable representing the number of grouped columns that uniquely specify
62    * a record of right iterator. It assists to move to a particular record for a
63    * group by query.
64    */

65   private int rightKeyCount = 0;
66   /**
67    * Left side Table of join
68    */

69   private TableDetails[] leftTableDetails = null;
70   /**
71    * Right side Table of join
72    */

73   private TableDetails[] rightTableDetails = null;
74
75   /**
76    * Initializes the required variables for retrieval of records.
77    * @param leftIterator table on left side of join condition
78    * @param rightIterator table on right side of join condition
79    * @param columnReferences join conditional columns of left iterator
80    * @param hasRecordReferences0 hasRecord references
81    */

82   public JoinIterator(_Iterator leftIterator, _Iterator rightIterator, _Reference[] columnReferences, ColumnDetails[] hasRecordReferences0) {
83       super(leftIterator, rightIterator, hasRecordReferences0);
84       leftColumnReferences = columnReferences;
85       if (leftColumnReferences == null || leftColumnReferences.length == 0) {
86          Thread.dumpStack();
87       }
88       state = INVALIDSTATE;
89    }
90
91    /**
92     * NAVIGATION METHODS OF JOIN ITERATOR.
93     * All the navigation method uses the same algorithm to retrieve the valid
94     * record from Join Iterator. These methods alignes both the underlying
95     * Iterators according to the join Condition. The retrieval process is as follows:
96     * 1. A record is retrieved from the left iterator acc. to navigation method.
97     * 2. Conditional column's values are retrived from left iterator record
98     * 3. These values are set to the right iterator into join condition i.e.
99     * ? = rightTableColumn. Now, record is retrieved from right iterator, thus,
100     * aligning the both iterators and satisfying the join condition.
101     * 4. If records are not found from right iterator, Next record is retrieved
102     * from left iterator and step 1 to 4 are repeated to find a matching set of
103     * records from both tables satisfying the join condition.
104     */

105    /**
106     * This method is responsible for retrieving the first record from the join
107     * iterator satisfying the join condition. The Algo used is as follows:
108     * 1. First record is retrieved from the left iterator, if there is no record,
109     * return false.
110     * 2. Get the values of conditional columns from left Iterator record and set
111     * these conditional columns values to Right Iterator. First record is retrieved
112     * from right Iterator which will have matching values satisfying the join condition.
113     * 3. If there are no records in right iterator it means there are no records
114     * in right iterator that can be matched with current record of left iterator
115     * satisfying join condition. Hence, next record is retreived from the left
116     * iterator, Goto step 2 to find some next record from left iterator that has
117     * its matching row in right iterator satisfying join condition.
118     * @return true if a record found, false otherwise.
119     * @throws DException
120     */

121    public boolean first() throws DException {
122       if (!leftIterator.first()) {
123          state = AFTERLAST;
124          return false;
125       }
126       getAndSetConditionValues();
127       while (!rightIterator.first()) {
128          if (!leftIterator.next()) {
129             state = AFTERLAST;
130             return false;
131          }
132          getAndSetConditionValues();
133       }
134       state = VALIDSTATE;
135       return true;
136    }
137
138    /**
139     * This method is responsible for retrieving the last record from the join
140     * iterator satisfying the join condition. The Algo used is as follows:
141     * 1. Last record is retrieved from the left iterator, if there is no record,
142     * return false.
143     * 2. Get the values of conditional columns from left Iterator record and set
144     * these conditional columns values to Right Iterator. Last record is retrieved
145     * from right Iterator which will have matching values satisfying the join condition.
146     * 3. If there are no records in right iterator it means there are no records
147     * in right iterator that can be matched with current record of left iterator
148     * satisfying join condition. Hence, previous record is retreived from the left
149     * iterator, Goto step 2 to find some previous record from left iterator that has
150     * its matching row in right iterator satisfying join condition.
151     * @return true if a record found, false otherwise.
152     * @throws DException
153     */

154    public boolean last() throws DException {
155       if (!leftIterator.last()) {
156          state = BEFOREFIRST;
157          return false;
158       }
159
160       getAndSetConditionValues();
161       while (!rightIterator.last()) {
162          if (!leftIterator.previous()) {
163             state = BEFOREFIRST;
164             return false;
165          }
166          getAndSetConditionValues();
167       }
168       state = VALIDSTATE;
169       return true;
170    }
171
172    /**
173     * This method is responsible for retrieving the next record from the join
174     * iterator satisfying the join condition. The Algo used is as follows:
175     * 1. If next record is retrieved from the right iterator. It means more
176     * records are satisfied for the current row of left iteratror. Return true.
177     * 2. Next record is retrieved from LEFT iterator, if no record found, return false.
178     * 3. Get the values of conditional columns from left Iterator record and set
179     * these conditional columns values to Right Iterator.
180     * 4. First record is retrieved from right Iterator which will have matching
181     * values satisfying the join condition, return true.
182     * 5. If there are no records in right iterator it means there are no records
183     * in right iterator that can be matched with current record of left iterator
184     * satisfying join condition. Hence, next record is retreived from the left
185     * iterator, Goto step 2 to find some next record from left iterator that has
186     * its matching row in right iterator satisfying join condition.
187     * @return true if a record found, false otherwise.
188     * @throws DException
189     */

190    public boolean next() throws DException {
191       switch (state) {
192          case INVALIDSTATE:
193             throw new DException("DSE4116", null);
194          case AFTERLAST:
195             return false;
196          case BEFOREFIRST:
197             return first();
198          default: {
199             boolean left = rightIterator.next();
200             if (!left) {
201                do {
202                   if (!leftIterator.next()) {
203                      state = AFTERLAST;
204                      return false;
205                   }
206                   getAndSetConditionValues();
207                   left = rightIterator.first();
208                } while (!left);
209             }
210             state = VALIDSTATE;
211             return true;
212          }
213       }
214    }
215
216    /**
217     * This method is responsible for retrieving previous record from the join
218     * iterator satisfying the join condition. The Algo used is as follows:
219     * 1. If previous record is retrieved from the right iterator,return true, since,
220     * join condition is satisfied, it is previous record of Join Iterator.
221     * 2. Previous record is retrieved from LEFT iterator, if no record found, return false.
222     * 3. Get the values of conditional columns from left Iterator record and set
223     * these conditional column values to Right Iterator.
224     * 4. Last record is retrieved from right Iterator which will have matching
225     * values satisfying the join condition, return true.
226     * 5. If there are no records in right iterator it means there are no records
227     * in right iterator that can be matched with current record of left iterator
228     * satisfying join condition. Hence, previous record is retreived from the left
229     * iterator and goto step 2 to find some next record from left iterator that has
230     * its matching row in right iterator satisfying join condition.
231     * @return true if a record found, false otherwise.
232     * @throws DException
233     */

234    public boolean previous() throws DException {
235       switch (state) {
236          case INVALIDSTATE:
237             throw new DException("DSE4117", null);
238          case AFTERLAST:
239             return last();
240          case BEFOREFIRST:
241             return false;
242          default: {
243             boolean right = rightIterator.previous();
244             if (!right) {
245                do {
246                   if (!leftIterator.previous()) {
247                      state = BEFOREFIRST;
248                      return false;
249                   }
250                   getAndSetConditionValues();
251                   right = rightIterator.last();
252                } while (!right);
253             }
254             state = VALIDSTATE;
255             return true;
256          }
257       }
258    }
259
260    /**
261     * This method is used to get the key of the record in bytes.
262     * @usage to persist the temporary index keys in the database file
263     * @return byte key of the record
264     * @throws DException
265     */

266    public byte[] getByteKey() throws DException {
267       byte[] leftKeys =leftIterator.getByteKey();
268       byte[] rightKeys = rightIterator.getByteKey();
269       byte[] resultantKeys=new byte[leftKeys.length+rightKeys.length+4];
270       short leftLength = (short)leftKeys.length;
271       System.arraycopy(CCzufDpowfsufs.getBytes(leftLength),0,resultantKeys,0,2);
272       System.arraycopy(leftKeys,0,resultantKeys,2,leftKeys.length);
273       System.arraycopy(rightKeys,0,resultantKeys,leftKeys.length+2,rightKeys.length);
274       return resultantKeys;
275   }
276
277   /**
278    * This method is used to move the iterator according to the passed byte key.
279    * First Byte of the passed key represents the byte key length of the left
280    * iterator. It extractes the byte keys of left and right iterators and moves
281    * the underlying iterators acc. to extracted keys.
282    * @param key byte key where to point the underlying iterator
283    * @throws DException
284    */

285   public void moveByteKey(byte[] key) throws DException {
286     if(leftKeyCount != 0 || rightKeyCount !=0 ){
287       moveAcctoGroupByteKey(key);
288       return;
289     }
290     byte[] leftKeys = new byte[CCzufDpowfsufs.getShortValue(key,0)];
291     System.arraycopy(key,2,leftKeys,0,leftKeys.length);
292     leftIterator.moveByteKey(leftKeys);
293     getAndSetConditionValues();
294     byte[] rightKeys = new byte[key.length-leftKeys.length-2];
295     System.arraycopy(key,leftKeys.length+2,rightKeys,0,rightKeys.length);
296     rightIterator.moveByteKey(rightKeys);
297     state=VALIDSTATE;
298
299   }
300
301
302   /**
303    * THIS METHOD IS NOT USED
304    * @param keys
305    * @param leftTdCount
306    * @param rightTdCount
307    * @throws DException
308    */

309   private void moveAcctoGroupByteKeyold(byte[] keys,int leftTdCount,int rightTdCount) throws DException {
310       int k=0;
311       int[] t=null;
312         if (leftKeyCount == 0)
313             leftIterator.first();
314         else{
315            t=getLegthOfArray(keys,leftTdCount,rightTdCount,0);
316           byte[] leftKeys =new byte[t[0]];
317           for(int j=0;j<leftTdCount;j++){
318             leftKeys[k] =(byte) keys[k];
319             System.arraycopy(keys,k+1,leftKeys,k+1,keys[0]);
320             k+=keys[k];
321           }
322           leftIterator.move(leftKeys);
323         }
324         getAndSetConditionValues();
325         if (rightKeyCount == 0)
326             rightIterator.first();
327         else{
328           int rightKeysLength = 0;
329            byte[] rightKeys =new byte[t[1]];
330           for(int j=0;j<rightTdCount;j++){
331             rightKeys[k] =(byte) keys[k];
332             System.arraycopy(keys,1,rightKeys,k+1,keys[0]);
333             k+=keys[k];
334           }
335           rightIterator.move(rightKeys);
336
337         }
338         state = VALIDSTATE;
339     }
340
341     /**
342      * This method is responsible to align both underlying iterator acc. to byte
343      * key pasesed. It is used for a Join Iterator created for query having groupby
344      * clause. If any of the iterator's key length is zero, its first record is
345      * retrieved, since for this group, aggregates will be computed for all the
346      * records belonging to that group. Otherwise, key for left/right iterators
347      * are extracted from passed keys and move both the iterators to its corresponding keys.
348      * @param keys represents key where to align underling iterators. keys
349      * have the values of group by columns.
350      * @throws DException
351      */

352     private void moveAcctoGroupByteKey(byte[] keys) throws DException {
353       int index =0;
354             if (leftKeyCount == 0)
355                 leftIterator.first();
356             else{
357               index = moveBytes(leftTableDetails,leftIterator,index,keys);
358             }
359             getAndSetConditionValues();
360             if (rightKeyCount == 0)
361                 rightIterator.first();
362             else{
363               index = moveBytes(rightTableDetails ,rightIterator,index,keys);
364             }
365             state = VALIDSTATE;
366     }
367
368     /**
369      * This method is used to move left or right iterator acc. to passed key.
370      * @param td left or right side tables
371      * @param iter left or right side iterators
372      * @param index it is 0
373      * @param keys where to move left or right iterator
374      * @return total keys length including all the tables of left/right hand side
375      * @throws DException
376      */

377     private int moveBytes(TableDetails[] td,_Iterator iter,int index,byte[] keys) throws DException{
378       byte[] temp;
379       int length = 0;
380       for (int j = 0; j < td.length; j++) {
381         length += CCzufDpowfsufs.getShortValue(keys,index);
382         index = length + 2;
383       }
384       byte[] resultantKeys = new byte[length];
385       System.arraycopy(keys, 0, resultantKeys, 0, resultantKeys.length);
386       iter.move(resultantKeys);
387       return index;
388     }
389
390     /**
391      * THIS METHOD IS NOT USED
392      * @param keys
393      * @param lefTdCount
394      * @param rightTdCount
395      * @param index
396      * @return
397      */

398     private int[] getLegthOfArray(byte[] keys, int lefTdCount, int rightTdCount,
399                                   int index) {
400       int leftKeysLength = 0, rightKeysLength = 0;
401       for (int i = 0; i < lefTdCount; i++) {
402         leftKeysLength += keys[index];
403         index += keys[index];
404       }
405       int lengthOfLeftAndRight[] = new int[2];
406       lengthOfLeftAndRight[0] = leftKeysLength + lefTdCount;
407       for (int i = 0; i < rightTdCount; i++) {
408         rightKeysLength += keys[index];
409         index += keys[index];
410       }
411       lengthOfLeftAndRight[1] = rightKeysLength + rightTdCount;
412       return lengthOfLeftAndRight;
413     }
414
415    /**
416     * This method returns the key by concating the key of both underlying Iterator.
417     * @return Array of Object having the key
418     * @throws DException
419     */

420
421    public Object JavaDoc getKey() throws DException {
422       ArrayList list = new ArrayList();
423       Object JavaDoc[] leftKeys = (Object JavaDoc[]) leftIterator.getKey();
424       this.leftCount = leftKeys.length;
425       list.addAll(Arrays.asList(leftKeys));
426       list.addAll(Arrays.asList( (Object JavaDoc[]) rightIterator.getKey()));
427       return list.toArray();
428    }
429
430    /**
431     * This method is responsible to align both underlying iterator acc. to key
432     * pasesed. For a Join Iterator created for query having group by clause,
433     * transfers the call to moveAcctoGroupKey method.
434     * For a non-group by Join Query, left iterator and right keys are extracted
435     * from the passed key. First, left iterator is aligned to the left iterator
436     * key and gets the conditional column values from left iterator record, and
437     * sets these values in to rightIterator. After that, rightIterator is aligned
438     * to key of right iterator.
439     * @param keys key where to point to Join iterator
440     * @throws DException
441     */

442    public void move(Object JavaDoc keys) throws DException {
443       if (leftKeyCount != 0 || rightKeyCount != 0) {
444          moveAcctoGroupKey( (Object JavaDoc[]) keys);
445          return;
446       }
447       Object JavaDoc[] leftKeys = new Object JavaDoc[leftCount];
448       Object JavaDoc[] rightKeys = new Object JavaDoc[ ( (Object JavaDoc[]) keys).length - leftCount];
449       System.arraycopy(keys, 0, leftKeys, 0, leftCount);
450       System.arraycopy(keys, leftCount, rightKeys, 0, rightKeys.length);
451       leftIterator.move(leftKeys);
452       getAndSetConditionValues();
453       rightIterator.move(rightKeys);
454       state = VALIDSTATE;
455    }
456
457    /**
458     * This method is responsible to align both underlying iterator acc. to key
459     * pasesed. It is used for a Join Iterator created for query having groupby
460     * clause. If any of the iterator's key length is zero, its first record is
461     * retrieved, since for this group, aggregates will be computed for all the
462     * records belonging to that group. Otherwise, key for left/right iterators
463     * are extracted from passed keys and move both the iterators to its corresponding keys.
464     * @param keys represents key where to align, underling iterators. Also keys
465     * have the values of group by columns.
466     * @throws DException
467     */

468    private void moveAcctoGroupKey(Object JavaDoc[] keys) throws DException {
469       if (leftKeyCount == 0) {
470          leftIterator.first();
471       } else {
472          Object JavaDoc[] leftKeys = new Object JavaDoc[leftKeyCount];
473          System.arraycopy(keys, 0, leftKeys, 0, leftKeyCount);
474          leftIterator.move(leftKeys);
475       }
476       getAndSetConditionValues();
477       if (rightKeyCount == 0) {
478          rightIterator.first();
479       } else {
480          int rightLength = keys.length - leftKeyCount;
481          Object JavaDoc[] rightKeys = new Object JavaDoc[rightLength];
482          System.arraycopy(keys, leftKeyCount, rightKeys, 0, rightLength);
483          rightIterator.move(rightKeys);
484       }
485       state = VALIDSTATE;
486    }
487
488    /**
489     * The following methods are used for getting values of current record.
490     * All retrival methods use the following logic.
491     * The retrival method checks the table of column. If the column corresponds
492     * to LEFT table, values are retrived from left iterator, otherwise,from right
493     * iterator.
494     */

495    /**
496     * This method is used to retrieve the values of passed references.
497     * @param leftColumnReferences reference for which values are to be retrived.
498     * Reference may be column or parameter.
499     * @return NonShared FieldBases denoting the value of References. Non Shared
500     * FieldBases are those for which BufferRange is not shared with some other
501     * FieldBase.
502     * @throws DException
503     */

504    public Object JavaDoc getColumnValues(_Reference[] leftColumnReferences) throws DException {
505       int len = leftColumnReferences.length;
506       Object JavaDoc[] values = new Object JavaDoc[len];
507       for (int i = 0; i < len; i++) {
508          values[i] = getColumnValues(leftColumnReferences[i]);
509       }
510       return values;
511    }
512
513    /**
514     * This method is used to retrieve the values of passed column indexes.
515     * @param parm1 column indexes for which values are to be retrived.
516     * @return NonShared FieldBases denoting the value of References. Non Shared
517     * FieldBases are those for which BufferRange is not shared with some other
518     * FieldBase.
519     * @throws DException
520     */

521    public Object JavaDoc getColumnValues(int[] parm1) throws DException {
522       return getColumnValues();
523    }
524
525    /**
526     * This method is used to retrieve all the values from the join query.
527     * This method retrives all the values from the left iterator and values from
528     * right iterator and merge these values to return the valid record of join iterator.
529     * @return NonShared FieldBases denoting the values of all columns of join query.
530     * Non Shared FieldBases are those for which BufferRange is not shared with
531     * some other FieldBase.
532     * @throws DException
533     */

534    public Object JavaDoc getColumnValues() throws DException {
535       ArrayList aList = new ArrayList();
536       Object JavaDoc obj = leftIterator.getColumnValues();
537       if (obj != null) {
538          aList.addAll(Arrays.asList( (Object JavaDoc[]) obj));
539       }
540       obj = rightIterator.getColumnValues();
541       if (obj != null) {
542          aList.addAll(Arrays.asList( (Object JavaDoc[]) obj));
543       }
544       return aList.toArray();
545    }
546
547    /**
548     * This method is used to retrieve the value of passed reference.
549     * It checks the table of column, if the column corresponds to LEFT table, values
550     * are retrived from left iterator, otherwise from right table.
551     * @param references reference for which value is to be retrived.
552     * Reference may be column or parameter.
553     * @return NonShared FieldBase denoting the value of Reference. Non Shared
554     * FieldBases are those for which BufferRange is not shared with some other
555     * FieldBase.
556     * @throws DException
557     */

558    public Object JavaDoc getColumnValues(_Reference references) throws DException {
559       TableDetails tDetails = ( (ColumnDetails) references).getTable();
560       int index = searchInMapping(tDetails);
561       return index != -1 ? index == SimpleConstants.LEFT ? leftIterator.getColumnValues(references)
562           : rightIterator.getColumnValues(references)
563           : GeneralPurposeStaticClass.getColumnValuesFromBoth(leftIterator, rightIterator, references);
564    }
565
566    /**
567     * This method return the shared FieldBase for the passed reference. By Shared
568     * FieldBase we mean, BufferRange of FieldBase is shared with other FieldBase
569     * objects.
570     * @param references reference for which value is to be retrived
571     * @return shared field base correspondition to passed column reference
572     * @throws DException
573     */

574    public FieldBase field(_Reference references) throws DException {
575       TableDetails tDetails = ( (ColumnDetails) references).getTable();
576       int index = searchInMapping(tDetails);
577       return index != -1 ? index == SimpleConstants.LEFT ? leftIterator.field(references)
578           : rightIterator.field(references)
579           : GeneralPurposeStaticClass.getFieldValuesFromBoth(leftIterator, rightIterator, references);
580    }
581
582    /**
583     * This method return the shared FieldBases for the passed references. By Shared
584     * FieldBase we mean, BufferRange of FieldBase is shared with other FieldBase
585     * objects.
586     * @param leftColumnReferences reference for which values are to be retrived
587     * @return shared field base correspondition to passed column reference
588     * @throws DException
589     */

590    public FieldBase[] fields(_Reference[] leftColumnReferences) throws DException {
591       int len = leftColumnReferences.length;
592       FieldBase[] values = new FieldBase[len];
593       for (int i = 0; i < len; i++) {
594          values[i] = field(leftColumnReferences[i]);
595       }
596       return values;
597    }
598
599    /**
600     * This method is responsible to check whether the passed tables
601     * corresponds to left iterator or right iterator.
602     * @param tDetails table to check
603     * @return table belongs to LEFT or RIGHT iterator.
604     * @throws DException
605     */

606    private int searchInMapping(TableDetails tDetails) throws DException {
607       for (int i = 0; i < tableDetailsMapping.length; i++) {
608          if (tableDetailsMapping[i][0] == tDetails) {
609             return ( (Integer JavaDoc) tableDetailsMapping[i][1]).intValue();
610          }
611       }
612       return -1;
613    }
614
615    /**
616     * OTHER SUPPORTING METHODS
617     */

618
619    /**
620     * This method is used to align the right iterator based on the current value
621     * of left iterator and join condition. It retrieves the conditional columns
622     * values from left iterator and sets these values to Right Iterator.
623     * ConditionalColumns of left Iterator will act as parameters in the join
624     * condition placed in right iterator
625     * E.g if condition is RightTable.rightColumn = LeftTable.leftColumn,
626     * then it will be placed in rightIterator. The condition will act as
627     * RightTable.rightColumn = ? and the value of '?' is provided by JoinIterator.
628     * @throws DException
629     */

630    public void getAndSetConditionValues() throws DException {
631      Object JavaDoc[] values = (Object JavaDoc[]) leftIterator.getColumnValues(leftColumnReferences);
632      rightIterator.setConditionVariableValue(leftColumnReferences, values, 1);
633    }
634
635    /**
636     * This method is responsible for setting the length of left and right
637     * iterators's group key.
638     * @param tableAndKeyCount a mapping of tables involved in the query and
639     * length of their corresponding key.
640     * @throws DException
641     */

642    public void setKeyCount(Object JavaDoc[][] tableAndKeyCount) throws DException {
643       int[] counts = GeneralPurposeStaticClass.getLeftandRightKeyCount(
644         leftIterator, rightIterator, tableAndKeyCount, tableDetailsMapping);
645       leftKeyCount = counts[0];
646       rightKeyCount = counts[1];
647    }
648
649    /**
650     * This method returns all the tables involved in the join iterator.
651     * It retrieves the tables involved in left iterator and right iterator
652     * and merges the tables involved with flag denoting the LEFT or RIGHT
653     * side.
654     * @return resultant tables involved in the left and right iterator
655     * @throws DException
656     */

657    public TableDetails[] getTableDetails() throws DException {
658       TableDetails[] tableDetails1 = leftIterator.getTableDetails();
659       TableDetails[] tableDetails2 = rightIterator.getTableDetails();
660       int len = tableDetails1.length + tableDetails2.length;
661       tableDetailsMapping = new Object JavaDoc[len][2];
662       int i = 0;
663       Integer JavaDoc flag = new Integer JavaDoc(SimpleConstants.LEFT);
664       for (int j = 0; j < tableDetails1.length; j++) {
665          tableDetailsMapping[i][0] = tableDetails1[j];
666          tableDetailsMapping[i++][1] = flag;
667       }
668       flag = new Integer JavaDoc(SimpleConstants.RIGHT);
669       for (int j = 0; j < tableDetails2.length; j++) {
670          tableDetailsMapping[i][0] = tableDetails2[j];
671          tableDetailsMapping[i++][1] = flag;
672       }
673       TableDetails[] resultantTableDetails = new TableDetails[len];
674       System.arraycopy(tableDetails1, 0, resultantTableDetails, 0, tableDetails1.length);
675       System.arraycopy(tableDetails2, 0, resultantTableDetails, tableDetails1.length, tableDetails2.length);
676       return resultantTableDetails;
677    }
678
679    /**
680     * This method is responsible to retrive the composite key column information
681     * of Join iterator. This method sets the variable leftCount i.e. the number
682     * of key columns in the left iterator, which is used in moving to a particular
683     * record of Join Iterator.
684     * @return Merged key column information of iterator
685     * @throws DException
686     */

687    public _KeyColumnInformation[] getKeyColumnInformations() throws DException {
688       _KeyColumnInformation[] leftKeyColumnInformation = leftIterator.getKeyColumnInformations();
689       _KeyColumnInformation[] rightKeyColumnInformation = rightIterator.getKeyColumnInformations();
690       this.leftCount = leftKeyColumnInformation.length;
691       int len = leftKeyColumnInformation.length + rightKeyColumnInformation.length;
692       _KeyColumnInformation[] resultantKeyColumnInformation = new _KeyColumnInformation[len];
693       System.arraycopy(leftKeyColumnInformation, 0, resultantKeyColumnInformation, 0, leftKeyColumnInformation.length);
694       System.arraycopy(rightKeyColumnInformation, 0, resultantKeyColumnInformation, leftKeyColumnInformation.length, rightKeyColumnInformation.length);
695       return resultantKeyColumnInformation;
696    }
697
698    /**
699     * This method is used to get the lowest level iterator of the passed column.
700     * This is used for optimised retrieval of record from the maintained
701     * mapping of iterators rather than navigating in iterators hierarchy.
702     * @usage - top level resulset of select query.
703     * @param column corresponding to which, iterator has to return
704     * @return base table iterator corresponding to column passed
705     * @throws DException
706     */

707    public _Iterator getBaseIterator(ColumnDetails column) throws DException {
708       int len = tableDetailsMapping.length;
709       for (int i = 0; i < len; i++) {
710          if (tableDetailsMapping[i][0] == column.getTableDetails()) {
711             return (tableDetailsMapping[i][1].hashCode() == SimpleConstants.LEFT) ? leftIterator.getBaseIterator(column) : rightIterator.getBaseIterator(column);
712          }
713       }
714       _Iterator left = leftIterator.getBaseIterator(column);
715       return left != null ? left : rightIterator.getBaseIterator(column);
716    }
717
718    /**
719     * This method is responsible to display the executionPlan of a Select Query.
720     * @return _ExecutionPlan
721     * @throws DException
722     */

723    public _ExecutionPlan getExecutionPlan() throws DException {
724       _ExecutionPlan plan = leftIterator.getExecutionPlan();
725       _ExecutionPlan plan1 = rightIterator.getExecutionPlan();
726       _ExecutionPlan cplans[] = new _ExecutionPlan[] {plan, plan1};
727       return new ExecutionPlan("JoinIterator", cplans, null, null, null);
728    }
729
730    /**
731     * This method is responsible to display the iterators hierarchy of a Select Query.
732     * @return ExecutionPlanForBrowser
733     * @throws DException
734     */

735    public ExecutionPlanForBrowser getExecutionPlanForBrowser() throws DException {
736       int length = 2;
737       ExecutionPlanForBrowser cplans[] = new ExecutionPlanForBrowser[length];
738       cplans[0] = leftIterator.getExecutionPlanForBrowser();
739       cplans[1] = rightIterator.getExecutionPlanForBrowser();
740       String JavaDoc refer = leftColumnReferences == null ? "" : "" + Arrays.asList(leftColumnReferences);
741       refer = " Outer Reference " + refer;
742       return new ExecutionPlanForBrowser("Nested Join/Inner Join" + refer, "Join Iterator", cplans, null, null, null);
743    }
744
745    /**
746     * The following methods of this class are used a intermediate in the
747     * iterator hierarchy. These methods simply transfer the call to the
748     * underlying iterator with the same arguments.
749     */

750
751    public Object JavaDoc[] getUniqueColumnReference() throws DException {
752       return GeneralPurposeStaticClass.getUniqueColumnReference(leftIterator, rightIterator);
753    }
754
755    public boolean seek(Object JavaDoc indexKey) throws DException {
756       return GeneralPurposeStaticClass.seek(indexKey, leftIterator, rightIterator);
757    }
758
759    /**
760     * Returns the default order for this join.
761     * @return _Order
762     * @throws DException
763     */

764
765    public _Order getDefaultOrder() throws DException {
766       return GeneralPurposeStaticClass.getJoinOrdered(leftIterator.getDefaultOrder(), rightIterator.getDefaultOrder());
767    }
768
769
770    public String JavaDoc toString() {
771       return "JoinIterator[" + leftIterator + "]\n\n\n[" + rightIterator + "]";
772    }
773 }
774
Popular Tags