KickJava   Java API By Example, From Geeks To Geeks.

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


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.datasystem.utility._Record;
7 import com.daffodilwoods.daffodildb.server.sql99.common.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.execution.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
10 import com.daffodilwoods.daffodildb.server.sql99.dql.listenerevents.*;
11 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
12 import com.daffodilwoods.daffodildb.utils.field.*;
13 import com.daffodilwoods.database.resource.*;
14 import com.daffodilwoods.database.sqlinitiator.*;
15 import com.daffodilwoods.daffodildb.utils.byteconverter.CCzufDpowfsufs;
16 import com.daffodilwoods.database.utility.P;
17
18 /**
19  * <p>Title: </p>
20  * <p>Description: This Class is responsible for retrieval of records from a
21  * query having CROSS JOIN of two or more tables. If n tables have a1,a2,a3...
22  * ...an records, the number of records of this iterator will be a1*a2*a3*..*an.
23  * </p>
24  * <p>Copyright: Copyright (c) 2004</p>
25  * <p>Company: </p>
26  * @author not attributable
27  * @version 1.0
28  */

29 public class NestedLoopJoinIterator implements _Iterator, _HasRecordIterator {
30
31   /**
32    * An array of iterators representing the data of tables specified in join query.
33    */

34   _Iterator[] iterators;
35   /**
36    * A mapping of tables involved in the query and int variable to denote index
37    * of table in specified list of tables.
38    */

39   private Object JavaDoc[][] tableDetailsMapping; // Here mapping 'll be ----> [tableDetail ---- iterator Number]
40
/**
41    * An array of number of key columns in corresponding iterator. It assists
42    * to move to a particular record for a non-group by query.
43    */

44   private int[] keymapping; // implies the count of keys for each iterator
45
/**
46    * Variable representing the state of Iterator. State can be ValidState,
47    * AFTERLAST,BEFOREFIRST and INVALIDSTATE.
48    */

49   private int state; //VALID/INVALID
50
/**
51    * An array having the number of grouped columns that uniquely specify a record
52    * of corresponding iterator. It assists to move to a particular record for a
53    * group by query.
54    */

55   private int[] keyCountsInGroup;
56
57   /**
58    * Represents the number of columns involved in order for each resultset
59    */

60
61   private int[] orderCountmapping; // implies the count of keys for each iterator
62

63   /**
64    * Represents the columns for hasRecord.
65    */

66
67   private ColumnDetails[] hasRecordReferences;
68
69   private _Reference[] underlyingReferences;
70
71    public NestedLoopJoinIterator(_Iterator[] iterators1, ColumnDetails[] hasRecordReferences0) {
72       iterators = iterators1;
73       state = INVALIDSTATE;
74       hasRecordReferences = hasRecordReferences0;
75    }
76
77    public NestedLoopJoinIterator(_Iterator[] iterators1) {
78       iterators = iterators1;
79       state = INVALIDSTATE;
80    }
81
82    /**
83     * The following methods are used for navigaton of records.
84     */

85    /**
86     * This method is responsible for retrieval of FIRST record. First record is
87     * retrived from each iterator, it any of the iterator has no records, returns
88     * false.
89     * @return true if record found, false otherwise.
90     * @throws DException
91     */

92    public boolean first() throws DException {
93       int len = iterators.length;
94       for (int i = 0; i < len; i++) {
95          if (!iterators[i].first()) {
96             state = AFTERLAST;
97             return false;
98          }
99       }
100       state = VALIDSTATE;
101       return true;
102    }
103
104    /**
105     * This method is responsible for retrieval of NEXT record. The process is as
106     * follows:
107     * 1. Next record is retrieved from last iterator. If record found, return true.
108     * 2. Next record is retrived from previous iterator. If record found, align the
109     * succesive iterators to their first record, else goto step3.
110     * 3. repeat step 2, utill the first iterator has no next record, return false.
111     * @return true if record found , false otherwise.
112     * @throws DException
113     */

114    public boolean next() throws DException {
115       switch (state) {
116          case INVALIDSTATE:
117             throw new DException("DSE4116", null);
118          case BEFOREFIRST:
119             return first();
120          case AFTERLAST:
121             return false;
122          default: {
123             int last = iterators.length - 1;
124             if (!iterators[last].next()) {
125               if (last == 0) {
126                 state = AFTERLAST;
127                 return false;
128               }
129               while (!iterators[--last].next()) {
130                 if (last == 0) {
131                   state = AFTERLAST;
132                   return false;
133                 }
134               }
135               while (++last < iterators.length) {
136                 iterators[last].first();
137               }
138             }
139             state = VALIDSTATE;
140             return true;
141          }
142       }
143    }
144
145    /**
146     * This method is responsible for retrieval of LAST record. Last record is
147     * retrived from each iterator, it any of the iterator has no records,
148     * returns false.
149     * @return true if record found, false otherwise.
150     * @throws DException
151     */

152    public boolean last() throws DException {
153       int len = iterators.length;
154       for (int i = 0; i < len; i++) {
155          if (!iterators[i].last()) {
156             state = BEFOREFIRST;
157             return false;
158          }
159       }
160       state = VALIDSTATE;
161       return true;
162    }
163
164    /**
165     * This method is responsible for retrieval of PREVIOUS record.
166     * The process is as follows:
167     * 1. Previous record is retrieved from last iterator. If record found, return true.
168     * 2. Previous record is retrived from previous iterator. If record found, align the
169     * succesive iterators to their last record, else goto step3.
170     * 3. Repeat step 2, utill the first iterator has no previous record, return false.
171     * @return true if record found , false otherwise.
172     * @throws DException
173     */

174    public boolean previous() throws DException {
175       switch (state) {
176          case INVALIDSTATE:
177             throw new DException("DSE4116", null);
178          case BEFOREFIRST:
179             return false;
180          case AFTERLAST:
181             return last();
182          default: {
183             int last = iterators.length - 1;
184             if (!iterators[last].previous()) {
185                if (last == 0) {
186                   state = BEFOREFIRST;
187                   return false;
188                } while (!iterators[--last].previous()) {
189                   if (last == 0) {
190                      state = BEFOREFIRST;
191                      return false;
192                   }
193                } while (++last < iterators.length) {
194                   iterators[last].last();
195                }
196             }
197             state = VALIDSTATE;
198             return true;
199          }
200       }
201    }
202
203    /**
204     * This method returns the key by concating the keys of all Iterators.
205     * @return Array of Object having the key
206     * @throws DException
207     */

208    public Object JavaDoc getKey() throws DException {
209       ArrayList keyColumnsList = new ArrayList();
210       int len = iterators.length;
211       if (keymapping != null && keymapping[0] != 0) {
212          for (int i = 0; i < len; i++) {
213             keyColumnsList.addAll(Arrays.asList( (Object JavaDoc[]) iterators[i].getKey()));
214          }
215          return keyColumnsList.toArray(new Object JavaDoc[keyColumnsList.size()]);
216       }
217       this.keymapping = new int[len];
218       for (int i = 0; i < len; i++) {
219          Object JavaDoc[] tempKeys = (Object JavaDoc[]) iterators[i].getKey();
220          this.keymapping[i] = tempKeys.length;
221          keyColumnsList.addAll(Arrays.asList(tempKeys));
222       }
223       return keyColumnsList.toArray(new Object JavaDoc[keyColumnsList.size()]);
224    }
225
226    /**
227     * This method is responsible to align all underlying iterators acc. to key
228     * pasesed. It is used for a for query having group by clause. If any of the
229     * iterator's key length is zero, its first record is retrieved, since for
230     * this group, aggregates will be computed for all the records belonging to
231     * that group. Otherwise, iterator is moved to its corresponding key extracted
232     * from key passed. In this case, keys have the values of group by columns.
233     * @param parm1 key where to align, underling iterators
234     * @throws DException
235     */

236    private void moveAcctoGroup(Object JavaDoc[] parm1) throws DException {
237      int len = iterators.length;
238      int index = 0;
239      Object JavaDoc[] source = (Object JavaDoc[]) parm1;
240      for (int i = 0; i < len; i++) {
241         int count = keyCountsInGroup[i];
242         if (count == 0) {
243            iterators[i].first();
244            continue;
245         }
246         Object JavaDoc[] keys = new Object JavaDoc[count];
247         System.arraycopy(source, index, keys, 0, keyCountsInGroup[i]);
248         iterators[i].move(keys);
249         index += keyCountsInGroup[i];
250      }
251      state = VALIDSTATE;
252    }
253
254    /**
255     * This method is responsible to align all underlying iterator acc. to key
256     * pasesed. For a query having group by clause, it transfers the call to
257     * moveAcctoGroupKey method. For a non-group by Join Query, corresponding keys
258     * of all iterators are extracted and these iterator are moved to their
259     * corresponding extracted key from passed key.
260     * @param parm1 key where to point to Nested loop join iterator
261     * @throws DException
262     */

263    public void move(Object JavaDoc parm1) throws DException {
264       if (keyCountsInGroup != null) {
265          moveAcctoGroup( (Object JavaDoc[]) parm1);
266          return;
267       }
268       int len = iterators.length;
269       int index = 0;
270       Object JavaDoc[] source = (Object JavaDoc[]) parm1;
271       for (int i = 0; i < len; i++) {
272          Object JavaDoc[] keys = new Object JavaDoc[this.keymapping[i]];
273          System.arraycopy(source, index, keys, 0, this.keymapping[i]);
274          iterators[i].move(keys);
275          index += this.keymapping[i];
276       }
277       state = VALIDSTATE;
278    }
279
280    /**
281     * The following methods are used for getting values of current record.
282     * All retrival methods use following logic. The retrival methods determine
283     * that passed column belongs to which iterator and call is delegated to
284     * corresponding iterator.
285     */

286    /**
287     * This method is used to retrieve the values of passed references.
288     * @param columnReferences reference for which values are to be retrived.
289     * Reference may be column or parameter.
290     * @return NonShared FieldBases denoting the value of References. Non Shared
291     * FieldBases are those for which BufferRange is not shared with some other
292     * FieldBase.
293     * @throws DException
294     */

295    public Object JavaDoc getColumnValues(_Reference[] columnReferences) throws DException {
296       int length = columnReferences.length, len = iterators.length;
297       Object JavaDoc[] values = new Object JavaDoc[length];
298       for (int i = 0; i < length; i++) {
299          values[i] = getColumnValues(columnReferences[i]);
300       }
301       return values;
302    }
303
304
305    /**
306     * This method is used to retrieve the all the values of record.
307     * @return NonShared FieldBases denoting the values of all columns. Non Shared
308     * FieldBases are those for which BufferRange is not shared with some other
309     * FieldBase.
310     * @throws DException
311     */

312    public Object JavaDoc getColumnValues() throws DException {
313       ArrayList aList = new ArrayList();
314       for (int i = 0; i < iterators.length; i++) {
315          Object JavaDoc obj = iterators[i].getColumnValues();
316          if (obj != null) {
317             aList.addAll(Arrays.asList( (Object JavaDoc[]) obj));
318          }
319       }
320       return aList.toArray();
321    }
322
323
324    /**
325     * This method is used to retrieve the values of passed reference.
326     * @param columnReferences reference for which value is to be retrived.
327     * Reference may be column or parameter.
328     * @return NonShared FieldBases denoting the value of References. Non Shared
329     * FieldBases are those for which BufferRange is not shared with some other
330     * FieldBase.
331     * @throws DException
332     */

333    public Object JavaDoc getColumnValues(_Reference columnReferences) throws DException {
334       int index = getIndexFromMapping( ( (ColumnDetails) columnReferences).getTable());
335       return index != -1 ? iterators[tableDetailsMapping[index][1].hashCode()].getColumnValues(columnReferences)
336           : getColumnValueFromAll(columnReferences);
337    }
338
339    /**
340     * This method is responsible for retriving the values of passed reference.
341     * @param reference column for which value is to be retrieved
342     * @return NonShared FieldBase denoting the value of passed reference. Non Shared
343     * FieldBases are those for which BufferRange is not shared with some other
344     * FieldBase.
345     * @throws DException if column passed does't belong to either of the tables
346     * involved in query.
347     */

348    private Object JavaDoc getColumnValueFromAll(_Reference reference) throws DException {
349       for (int i = 0, length = iterators.length; i < length; i++) {
350          Object JavaDoc value = null;
351          try {
352             return iterators[i].getColumnValues(reference);
353          } catch (DException ex) {
354             continue;
355          }
356       }
357       throw new DException("DSE3520", new Object JavaDoc[] {reference.getColumn()});
358    }
359
360    /**
361     * This method is responsible for retriving the values of the columns for
362     * which tablemapping is not found. This method tries to get column value from
363     * each iterator, An exception is catched to handle the case i.e. column passed
364     * does't belong to table from which its values are retrived.
365     * @param leftColumnReferences column for which value is to be retrieved
366     * @return shared field base correspondition to passed column reference
367     * @throws DException if column passed does't belong to either of the tables
368     * involved in query.
369     */

370    private FieldBase getFieldValueFromAll(_Reference leftColumnReferences) throws DException {
371       for (int i = 0, length = iterators.length; i < length; i++) {
372          FieldBase value = null;
373          try {
374             return iterators[i].field(leftColumnReferences);
375          } catch (DException ex) {
376             continue;
377          }
378       }
379       throw new DException("DSE3520", new Object JavaDoc[] {leftColumnReferences.getColumn()});
380    }
381
382    /**
383     * This method is responsible for retriving the values of the columns for
384     * which tablemapping is not found. This method tries to get column value from
385     * each iterator, An exception is catched to handle the case i.e. column passed
386     * does't belong to table from which its values are retrived.
387     * @param columnReferences column for which value is to be retrieved
388     * @return shared field base correspondition to passed column reference
389     * @throws DException if column passed does't belong to either of the tables
390     * involved in query.
391     */

392    public FieldBase field(_Reference columnReferences) throws DException {
393       int index = getIndexFromMapping( ( (ColumnDetails) columnReferences).getTable());
394       return index != -1 ? iterators[tableDetailsMapping[index][1].hashCode()].field(columnReferences)
395           : getFieldValueFromAll(columnReferences);
396    }
397
398    /**
399     * This method is used to retrieve the values of passed references.
400     * @param columnReferences reference for which values are to be retrived.
401     * Reference may be column or parameter.
402     * @return shared field bases correspondition to passed column references
403     * @throws DException
404     */

405    public FieldBase[] fields(_Reference[] columnReferences) throws DException {
406       int length = columnReferences.length, len = iterators.length;
407       FieldBase[] values = new FieldBase[length];
408       for (int i = 0; i < length; i++) {
409          values[i] = field(columnReferences[i]);
410       }
411       return values;
412    }
413
414    public FieldBase[] fields(int[] columns) throws DException {
415       throw new java.lang.UnsupportedOperationException JavaDoc("Method fields() not yet implemented.");
416    }
417
418    public Object JavaDoc getColumnValues(int[] parm1) throws DException {
419       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._TableIterator method*/
420       throw new java.lang.UnsupportedOperationException JavaDoc("Method getColumnValues() not yet implemented.");
421    }
422
423    /**
424     * This method returns all the tables involved in the iterator.
425     * It retrieves the tables involved in each iterator and merges the tables
426     * involved with flag denoting the index of the iterator.
427     * @return resultant tables involved query
428     * @throws DException
429     */

430    public TableDetails[] getTableDetails() throws DException {
431       int len = iterators.length;
432       int[] tDetailsCount = new int[len];
433       ArrayList tableDetailsList = new ArrayList();
434       TableDetails[] tempTabledetails;
435       for (int i = 0; i < len; i++) {
436          tempTabledetails = iterators[i].getTableDetails();
437          tableDetailsList.addAll(Arrays.asList(tempTabledetails));
438          tDetailsCount[i] = tempTabledetails.length;
439       }
440       tempTabledetails = (TableDetails[]) tableDetailsList.toArray(new TableDetails[0]);
441       this.tableDetailsMapping = new Object JavaDoc[tempTabledetails.length][2];
442       int resultantMappingPosition = 0;
443       for (int i = 0; i < len; i++) {
444          int count = tDetailsCount[i];
445          for (int j = 0; j < count; j++) {
446             tableDetailsMapping[resultantMappingPosition][0] = tempTabledetails[resultantMappingPosition];
447             tableDetailsMapping[resultantMappingPosition][1] = new Integer JavaDoc(i);
448             resultantMappingPosition++;
449          }
450       }
451       return tempTabledetails;
452    }
453
454
455    /**
456     * This method is responsible to align all underlying iterators acc. to key
457     * pasesed. It is used for a for query having group by clause. If any of the
458     * iterator's key length is zero, its first record is retrieved, since for
459     * this group, aggregates will be computed for all the records belonging to
460     * that group. Otherwise, iterator is moved to its corresponding key extracted
461     * from key passed. In this case, keys have the values of group by columns.
462     * @param parm1 key where to align underling iterators
463     * @throws DException
464     */

465     private void moveAcctoGroupByte(byte[] keys) throws DException {
466       int len = iterators.length;
467       int index = 0;
468       for (int i = 0; i < len; i++) {
469         int count = keyCountsInGroup[i];
470         if (count == 0) {
471           iterators[i].first();
472           continue;
473         }
474         int length = 0;
475         index = moveBytes(iterators[i], iterators[i].getTableDetails(), index,
476                           keys);
477
478       }
479     }
480
481     /**
482      * This method is used to move underlying iterator acc. to passed key.
483      * @param td left or right side tables
484      * @param iter left or right side iterators
485      * @param index it is 0
486      * @param keys where to move left or right iterator
487      * @return total keys length including all the tables of left/right hand side
488      * @throws DException
489      */

490     private int moveBytes(_Iterator iter,TableDetails[] td,int index,byte[] keys) throws DException{
491       int length=0;
492     int startIndex =index;
493       for(int j=0;j<td.length;j++){
494         length+=CCzufDpowfsufs.getShortValue(keys,index);
495         index =length+2;
496        }
497        byte[] resultantKeys =new byte[length];
498        System.arraycopy(keys,startIndex,resultantKeys,0,resultantKeys.length);
499        iter.move(resultantKeys);
500        return index;
501
502     }
503
504     /**
505      * This method is used to get the merged key of all the underlying iterators
506      * in bytes.
507      * @usage to persist the temporary index keys in the database file
508      * @return byte key of the record
509      * @throws DException
510      */

511     public byte[] getByteKey() throws DException {
512       int len =0;
513       byte[] resultant = null;
514       for(int i=0;i< iterators.length;i++){
515         resultant = getResultantArray(iterators[i].getByteKey(), resultant);
516       }
517       return resultant;
518     }
519
520     /**
521      * This method is used to get merged key of passed key with the passed array
522      * of merged keys. For each iterator, one extra byte is put for setting the
523      * length of passed byte keys of particular iterator.
524      * @param keys byte key of particular iterator
525      * @param resultant byte keys before being merged the passed key
526      * @return resultant byte keys after being merged the passed key
527      */

528     private byte[] getResultantArray(byte[] keys,byte[] resultant){
529       byte resultant1[] = null ;
530        if(resultant == null){
531          resultant1 = new byte[keys.length + 2];
532          short keyslength = (short)keys.length;
533          System.arraycopy(CCzufDpowfsufs.getBytes(keyslength),0,resultant1,0,2 );
534          System.arraycopy(keys, 0, resultant1, 2, keys.length);
535        }
536        else{
537          resultant1 = new byte[keys.length + 2 + resultant.length];
538          System.arraycopy(resultant, 0, resultant1, 0, resultant.length);
539          short keyLength =(short)keys.length;
540          System.arraycopy(CCzufDpowfsufs.getBytes(keyLength),0,resultant1,resultant.length,2);
541          System.arraycopy(keys, 0, resultant1, resultant.length + 2, keys.length);
542        }
543        return resultant1;
544
545     }
546
547     /**
548      * This method is used to move all the underlying iterators acc. to passed
549      * key. For each underlying iterator, a new key is generated using
550      * @param sourcekey key of nested loop join iterator where to move the iterator
551      * @throws DException
552      */

553     public void moveByteKey(byte[] sourcekey) throws DException {
554         /** @todo Group by work have to be done */
555         if (keyCountsInGroup != null){
556             moveAcctoGroupByte(sourcekey);
557             return;
558         }
559         for(int i=0,index=0;i<iterators.length;i++){
560           int len = CCzufDpowfsufs.getShortValue(sourcekey,index);
561           byte[] keys = new byte[len];
562           System.arraycopy(sourcekey,index+2,keys,0,len);
563           iterators[i].moveByteKey(keys);
564           index+=len+2;
565         }
566         state=VALIDSTATE;
567     }
568
569    /**
570     * This method is responsible to retrive the composite key column information.
571     * This method sets the keyMapping variable at corresponding index i.e. the number
572     * of key columns in the corresponding iterator, which is used in moving to a
573     * particular record of Nested loop join Iterator.
574     * @return Merged key column information of iterator
575     * @throws DException
576     */

577    public _KeyColumnInformation[] getKeyColumnInformations() throws DException {
578       int len = iterators.length;
579       ArrayList keyColumnsList = new ArrayList();
580       this.keymapping = new int[len];
581       _KeyColumnInformation[] tempKeyColumnInformation;
582       for (int i = 0; i < len; i++) {
583          tempKeyColumnInformation = iterators[i].getKeyColumnInformations();
584          keyColumnsList.addAll(Arrays.asList(tempKeyColumnInformation));
585          this.keymapping[i] = tempKeyColumnInformation.length;
586       }
587       tempKeyColumnInformation = (_KeyColumnInformation[]) keyColumnsList.toArray(new _KeyColumnInformation[0]);
588       return tempKeyColumnInformation;
589    }
590
591    /**
592     * This method is used to get the lowest level iterator of the passed column.
593     * This is used for optimisation purpose retrieval of record from the maintained
594     * mapping of iterators rather than navigating in iterators hierarchy.
595     * @param column corresponding to which, iterator has to return
596     * @return base table iterator corresponding to column passed
597     * @throws DException
598     */

599    public _Iterator getBaseIterator(ColumnDetails column) throws DException {
600       TableDetails tableDetails = column.getTableDetails();
601       int len = tableDetailsMapping.length;
602       for (int i = 0; i < len; i++) {
603          if (this.tableDetailsMapping[i][0] == tableDetails) {
604             return iterators[this.tableDetailsMapping[i][1].hashCode()].getBaseIterator(column);
605          }
606       }
607       return baseIterator(column);
608    }
609
610    private _Iterator baseIterator(ColumnDetails column) throws DException {
611       int len = tableDetailsMapping.length;
612       for (int i = 0; i < len; i++) {
613          _Iterator iter = iterators[this.tableDetailsMapping[i][1].hashCode()].getBaseIterator(column);
614          if (iter == null) {
615             continue;
616          }
617          return iter;
618       }
619       throw new DException("DSE3571", new Object JavaDoc[] {column.getColumn()});
620    }
621
622    /**
623     * This method is used to release the resources(e.g. comparator) releated with
624     * particular iterator.
625     * @throws DException
626     */

627    public void releaseResource() throws DException {
628       for (int i = 0; i < iterators.length; i++) {
629          iterators[i].releaseResource();
630       }
631    }
632
633    /**
634     * This method is called when given select query has group by clause. It is
635     * responsible for creating a mapping of number of columns involved in group
636     * by clause corresponding to each iterator.
637     * @param tableAndKeyCount a mapping of tables involved in the query and
638     * length of their corresponding key.
639     * @throws DException
640     */

641    public void setKeyCount(Object JavaDoc[][] tableAndKeyCount) throws DException {
642       int length2 = iterators.length;
643       ArrayList[] list = new ArrayList[length2]; // Will move according to tableDetailsCC 2 index
644
keyCountsInGroup = new int[length2];
645
646       for (int i = 0, length = tableAndKeyCount.length; i < length; i++) {
647          TableDetails table = (TableDetails) tableAndKeyCount[i][0];
648          for (int j = 0, length1 = tableDetailsMapping.length; j < length1; j++) {
649             if (table == tableDetailsMapping[j][0]) {
650                int index = tableDetailsMapping[j][1].hashCode(); // index of iterator
651
keyCountsInGroup[index] += tableAndKeyCount[i][1].hashCode(); // new key count
652
ArrayList array = (ArrayList) list[index]; // array at this position
653
array = array == null ? new ArrayList(4)
654                    : array;
655                array.add(tableAndKeyCount[i]);
656                break;
657             }
658          }
659       }
660       for (int i = 0; i < length2; i++) {
661          if (list[i] == null) {
662             continue;
663          }
664          Object JavaDoc[][] array = (Object JavaDoc[][]) list[i].toArray(new Object JavaDoc[list[i].size()][2]);
665          iterators[i].setKeyCount(array);
666       }
667    }
668
669    /**
670     * Check whether the passed table is present in maintained table mapping.
671     * @param tableDetails table to check
672     * @return index of the passed table in maintained table mapping, if table
673     * exists in mapping, -1 otherwise.
674     * @throws DException
675     */

676    private int getIndexFromMapping(TableDetails tableDetails) throws DException {
677       int length = tableDetailsMapping.length;
678       for (int i = 0; i < length; i++) {
679          if (tableDetails == tableDetailsMapping[i][0]) {
680             return i;
681          }
682       }
683       return -1;
684    }
685
686    /**
687     * This method is responsible to get the base level iterator for the passed
688     * has record column. This checks the passed column if the column corresponds
689     * to the columns defined in cross join query, this iterator will be base
690     * iterator, otherwise, call is delegated to appropriate underlying iterator.
691     * @param hasRecordColumn for which base iterator is required
692     * @return base level iterator for passed has record column
693     * @throws DException
694     */

695    public _Iterator getBaseIteratorHasRecord(ColumnDetails hasRecordColumn) throws DException {
696       if (hasRecordReferences != null) {
697          for (int i = 0; i < hasRecordReferences.length; i++) {
698             if (hasRecordReferences[i] == hasRecordColumn) {
699                return this;
700             }
701          }
702       }
703       for (int i = 0, length = iterators.length; i < length; i++) {
704          _Iterator iterator = iterators[i].getBaseIteratorHasRecord(hasRecordColumn);
705          if (iterator != null) {
706             return iterator;
707          }
708       }
709       throw new DException("DSE565", new Object JavaDoc[] {"getBaseIterator"});
710    }
711
712    /**
713     * This method is required to get hasRecord column value which will be always
714     * true for cross join.
715     * @return which is true for each row of cross join
716     * @throws DException
717     */

718    public Object JavaDoc getHasRecordColumnValues() throws DException {
719       return new Boolean JavaDoc(true);
720    }
721
722    /**
723     * This method is responsible to display the executionPlan of a Select Query.
724     * @return _ExecutionPlan
725     * @throws DException
726     */

727    public _ExecutionPlan getExecutionPlan() throws DException {
728       int length = iterators.length;
729       _ExecutionPlan[] cplans = new _ExecutionPlan[length];
730       for (int i = 0; i < length; i++) {
731          cplans[i] = iterators[i].getExecutionPlan();
732       }
733       return new ExecutionPlan("NestedLoopJoinIterator", cplans, null, null, null);
734    }
735
736    /**
737     * This method is responsible to display the iterators hierarchy of a Select Query.
738     * @return ExecutionPlanForBrowser
739     * @throws DException
740     */

741    public ExecutionPlanForBrowser getExecutionPlanForBrowser() throws DException {
742       int length = iterators.length;
743       ExecutionPlanForBrowser cplans[] = new ExecutionPlanForBrowser[length];
744       for (int i = 0; i < length; i++) {
745          cplans[i] = iterators[i].getExecutionPlanForBrowser();
746       }
747       return new ExecutionPlanForBrowser("Nested Loops / Inner Join", "Nested Loop Join Iterator", cplans, null, null, null);
748    }
749
750    public _Record getRecord() throws DException {
751       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._TableIterator method*/
752       throw new java.lang.UnsupportedOperationException JavaDoc("Method getRecord() not yet implemented.");
753    }
754
755    public Object JavaDoc[] getUniqueColumnReference() throws DException {
756       /**@todo: Implement this com.daffodilwoods.daffodildb.server.sql99.utils._Iterator method*/
757       throw new java.lang.UnsupportedOperationException JavaDoc("Method getUniqueColumnReference() not yet implemented.");
758    }
759
760    public boolean seek(Object JavaDoc indexKey) throws DException {
761       /**@todo: Implement this com.daffodilwoods.daffodildb.server.sql99.utils._Iterator method*/
762       throw new java.lang.UnsupportedOperationException JavaDoc("Method seek() not yet implemented.");
763    }
764
765    public boolean seekFromTop(_IndexPredicate[] parm1) throws DException {
766       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._IndexIterator method*/
767       throw new java.lang.UnsupportedOperationException JavaDoc("Method seekFromTop() not yet implemented.");
768    }
769
770    public boolean seekFromBottom(_IndexPredicate[] parm1) throws DException {
771       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._IndexIterator method*/
772       throw new java.lang.UnsupportedOperationException JavaDoc("Method seekFromBottom() not yet implemented.");
773    }
774
775    /**
776     * The following methods of this class are used a intermediate in the
777     * iterator hierarchy. These methods simply transfer the call to the
778     * underlying iterator with the same arguments.
779     */

780
781    /**
782     * This method is used to get the number of columns involved in the order
783     * by clause. This method gets the columns from each of the underlying iterator,
784     * merges these columns and returns the joined order applied on the query.
785     * @return joined order applied on the query
786     * @throws DException
787     */

788    public _OrderCount getOrderCounts() throws DException {
789       int len = iterators.length;
790       this.orderCountmapping = new int[len];
791       int count = 0;
792       _Order order = null;
793       for (int i = 0; i < len; i++) {
794          _OrderCount tempOrderCount = iterators[i].getOrderCounts();
795          int tempCount = tempOrderCount.getOrderCount();
796          orderCountmapping[i] = tempCount;
797          count += tempCount;
798          order = GeneralPurposeStaticClass.getJoinOrdered(order, tempOrderCount.getOrders());
799       }
800       return new OrderCount(count, order);
801    }
802
803    public _Order getDefaultOrder() throws DException {
804       _Order selectOrder = null;
805       for (int i = 0; i < iterators.length; i++) {
806          _Order order = iterators[i].getDefaultOrder();
807          selectOrder = GeneralPurposeStaticClass.getJoinOrdered(selectOrder, order);
808       }
809       return selectOrder;
810    }
811
812    public Object JavaDoc[][] getFunctionalColumnMapping() throws DException {
813       Object JavaDoc[][] finalMapping = null;
814       for (int i = 0, length = iterators.length; i < length; i++) {
815          finalMapping = GeneralPurposeStaticClass.getMappingOfTableBVE(finalMapping, iterators[i].getFunctionalColumnMapping());
816       }
817       return finalMapping;
818    }
819
820    public void setConditionVariableValue(_Reference[] references, Object JavaDoc[] values, int priority) throws DException {
821      if(underlyingReferences!=null){
822           references = GeneralPurposeStaticClass.getJointReferences(references,underlyingReferences);
823           values = GeneralPurposeStaticClass.getJointValues(this, values,underlyingReferences.length);
824         }
825
826      for (int i = 0; i < iterators.length; i++) {
827          iterators[i].setConditionVariableValue(references, values, priority);
828       }
829    }
830
831    public boolean seekFromTopRelative(Object JavaDoc parm1) throws DException {
832       boolean flag = true;
833       Object JavaDoc[] keys = (Object JavaDoc[]) parm1, tempKeys;
834       for (int i = 0, length = iterators.length, count = 0; i < length; i++) {
835          if (orderCountmapping[i] == 0) {
836             if (!iterators[i].first()) {
837                return false;
838             }
839             continue;
840          }
841          tempKeys = new Object JavaDoc[orderCountmapping[i]];
842          try {
843             System.arraycopy(keys, count, tempKeys, 0, orderCountmapping[i]);
844          } catch (ArrayIndexOutOfBoundsException JavaDoc ex) {
845             throw ex;
846          }
847          count += orderCountmapping[i];
848          if (!iterators[i].seekFromTopRelative(tempKeys)) {
849             return false;
850          }
851       }
852       return true;
853    }
854
855    public boolean seekFromBottomRelative(Object JavaDoc parm1) throws DException {
856       boolean flag = true;
857       Object JavaDoc[] keys = (Object JavaDoc[]) parm1, tempKeys;
858       for (int i = 0, length = iterators.length, count = 0; i < length; i++) {
859          if (orderCountmapping[i] == 0) {
860             if (!iterators[i].last()) {
861                return false;
862             }
863             continue;
864          }
865          tempKeys = new Object JavaDoc[orderCountmapping[i]];
866          try {
867             System.arraycopy(keys, count, tempKeys, 0, orderCountmapping[i]);
868          } catch (ArrayIndexOutOfBoundsException JavaDoc ex) {
869             throw ex;
870          }
871          count += orderCountmapping[i];
872          if (!iterators[i].seekFromBottomRelative(tempKeys)) {
873             return false;
874          }
875       }
876       return true;
877    }
878
879    public void setSpecificUnderlyingReferences(_Reference[] specificUnderlyingReferences) throws DException{
880      underlyingReferences=specificUnderlyingReferences;
881    }
882
883    public String JavaDoc toString() {
884       StringBuffer JavaDoc sBuffer = new StringBuffer JavaDoc("NestedLoopJoinIterator");
885       for (int i = 0; i < iterators.length; i++) {
886          sBuffer.append("[");
887          if (iterators[i] != null) {
888             sBuffer.append(iterators[i].toString() + "\n\n\n");
889          } else {
890             sBuffer.append("null");
891          }
892          sBuffer.append("]");
893       }
894       return sBuffer.toString();
895    }
896 }
897
Popular Tags