KickJava   Java API By Example, From Geeks To Geeks.

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


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.serversystem.*;
7 import com.daffodilwoods.daffodildb.server.sql99.common.*;
8 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
9 import com.daffodilwoods.daffodildb.server.sql99.dql.listenerevents.*;
10 import com.daffodilwoods.daffodildb.server.sql99.expression.booleanvalueexpression.*;
11 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
12 import com.daffodilwoods.daffodildb.utils.*;
13 import com.daffodilwoods.daffodildb.utils.field.*;
14 import com.daffodilwoods.database.resource.*;
15 import java.util.*;
16 import com.daffodilwoods.database.utility.P;
17
18
19 /**
20  * <p>Title: SpecialRightJoinIterator </p>
21  * <p>Description: This Class assists to retrive the result of FULL OUTER JOIN.
22  * This class is not completely responsible for full outer join. FULL OUTER JOIN
23  * is retrived by Union All of LOJ of given underlying iterators and this iterator.
24  * The purpose of this iterator is to return all the records from the right iterator
25  * that dissatisfy the given Join Condition. The underlying iterators data is
26  * not sorted. For retrival of records null is returned corresponding to columns
27  * of right table.
28  *
29  * For each valid state of iterator, rightNull must be true. It is redundant
30  * variable. There is no need to check it.
31  *
32  * </p>
33  * <p>Copyright: Copyright (c) 2004</p>
34  * <p>Company: </p>
35  * @author not attributable
36  * @version 1.0
37  */

38 public class SpecialRightJoinIterator extends SemiJoinFilteredIterator implements _HasRecordIterator {
39
40   /**
41    * Swaps the left iterator with that of the right iterator. Now, this iterator
42    * is responsible to return all the records of the left iterator that dissatisfy
43    * the given join condition;
44    * @param leftIterator0 left underlying result set i.e right iterator data
45    * from given full join query
46    * @param rightIterator0 right resultset i.e left table data in the given full
47    * join query
48    * @param condition given join codition i.e. on codition
49    * @param leftKeyColumnInformation0 number of columns involved in group of left iterator
50    * @param rightKeyColumnInformation0 number of columns involved in group of right iterator
51    * @param hasRecordReferences0 hasRecord refererences
52    * @param session serversession to create instance of _VariableValues
53    * @throws DException
54    */

55    public SpecialRightJoinIterator(_Iterator leftIterator0, _Iterator rightIterator0, booleanvalueexpression condition, _KeyColumnInformation[] leftKeyColumnInformation0, _KeyColumnInformation[] rightKeyColumnInformation0, ColumnDetails[] hasRecordReferences0, _ServerSession session) throws DException {
56       super(rightIterator0, leftIterator0, condition, rightKeyColumnInformation0, leftKeyColumnInformation0, hasRecordReferences0, session);
57    }
58
59    /**
60     * This method is responsible to retrieve the first record from iterator.
61     * 1. First record from left iterator is retrieved. If no record found,
62     * return false.
63     * 2. Right iterator is navigated in forward direction starting from the
64     * first record till record is found that satisfies the given join condition.
65     * IF there exists no record in the right iterator that satisfies the
66     * given join condition, it will be first record of this iterator, return TRUE.
67     * ELSE, It means that there exists an record in the right iterator that
68     * satisfies given join condition with the current record from left iterator,
69     * goto step3.
70     * 3. Next record is retrieved from the left iterator, If no record found,
71     * return false, else goto step 2.
72     * @return true if record found, false otherwise.
73     * @throws DException
74     */

75    public boolean first() throws DException {
76       if (!leftIterator.first()) {
77          state = AFTERLAST;
78          return false;
79       }
80     rightNull = false;
81     while (rightIterator.first() && ifConditionSolvedForward()) {
82       if (!leftIterator.next()) {
83         state = AFTERLAST;
84         return false;
85       }
86     }
87     state = VALIDSTATE;
88     rightNull = true;
89     return true;
90   }
91
92
93
94
95   /**
96    * This method is responsible to retrieve the next record from iterator.
97    * 1. Next record from left iterator is retrieved. If no record found,
98    * return false, Else goto step 2.
99    * 2. Right iterator is navigated in forward direction starting from the
100    * first record till record is found that satisfies the given join condition.
101    * IF there exists no record in the right iterator that satisfies the
102    * given join condition, it will be next record of this iterator, return TRUE.
103    * ELSE, It means that there exists an record in the right iterator that
104    * satisfies given join condition with the current record from left iterator,
105    * goto step 1.
106    * @return true if record found, false otherwise.
107    * @throws DException
108    */

109    public boolean next() throws DException {
110       switch (state) {
111          case INVALIDSTATE:
112             throw new DException("DSE4116", null);
113          case BEFOREFIRST:
114             return first();
115          case AFTERLAST:
116             return false;
117          default: {
118             do {
119                rightNull = false;
120                if (!leftIterator.next()) {
121                   state = AFTERLAST;
122                   return false;
123                }
124             } while (rightIterator.first() && ifConditionSolvedForward());
125             state = VALIDSTATE;
126             rightNull = true;
127             return true;
128          }
129       }
130    }
131
132    /**
133     * This method is responsible to retrieve the last record from iterator.
134     * 1. Last record from left iterator is retrieved. If no record found,
135     * return false.
136     * 2. Right iterator is navigated in backward direction starting from the
137     * last record till record is found that satisfies the given join condition.
138     * IF there exists no record in the right iterator that satisfies the
139     * given join condition, it will be last record of this iterator, return TRUE.
140     * ELSE, It means that there exists an record in the right iterator that
141     * satisfies given join condition with the current record from left iterator,
142     * goto step3.
143     * 3. Previous record is retrieved from the left iterator, If no record found,
144     * return false, else goto step 2.
145     * @return true if record found, false otherwise.
146     * @throws DException
147     */

148    public boolean last() throws DException {
149       if (!leftIterator.last()) {
150          state = BEFOREFIRST;
151          return false;
152       }
153       rightNull = false;
154       while (rightIterator.last() && ifConditionSolvedBackward()) {
155          if (!leftIterator.previous()) {
156             state = BEFOREFIRST;
157             return false;
158          }
159       }
160       rightNull = true;
161       state = VALIDSTATE;
162       return true;
163    }
164
165    /**
166     * This method is responsible to retrieve the previous record from iterator.
167     * 1. Previous record from left iterator is retrieved. If no record found,
168     * return false, Else goto step 2.
169     * 2. Right iterator is navigated in backward direction starting from the
170     * last record till record is found that satisfies the given join condition.
171     * IF there exists no record in the right iterator that satisfies the
172     * given join condition, it will be previous record of this iterator, return TRUE.
173     * ELSE, It means that there exists an record in the right iterator that
174     * satisfies given join condition with the current record from left iterator,
175     * goto step 1.
176     * @return true if record found, false otherwise.
177     * @throws DException
178     */

179    public boolean previous() throws DException {
180       rightNull = false;
181       switch (state) {
182          case INVALIDSTATE:
183             throw new DException("DSE4117", null);
184          case BEFOREFIRST:
185             return false;
186          case AFTERLAST:
187             return last();
188          default: {
189             do {
190                if (!leftIterator.previous()) {
191                   state = BEFOREFIRST;
192                   return false;
193                }
194             } while (rightIterator.last() && ifConditionSolvedBackward());
195             rightNull = true;
196             state = VALIDSTATE;
197             return true;
198          }
199       }
200    }
201
202    /**
203     * This method assists to navigate the iterator in forward direction.
204     * It navigates the right iterator in the forward direction till the
205     * condition is satisfied. If the join condition is satisfied, returns
206     * true to indicate there is an matching record in the right iterator
207     * corresponding to current record from the left iterator.
208     * @return false if join condition is dissatisfied for all records from the
209     * right iterator, true otherwise.
210     * @throws DException
211     */

212    private boolean ifConditionSolvedForward() throws DException {
213       do {
214          if (conditionVariableValue.run().hashCode() == 0) {
215             state = VALIDSTATE;
216             return true;
217          }
218       } while (rightIterator.next());
219       return false;
220    }
221
222    /**
223     * This method assists to navigate the iterator in backward direction.
224     * It navigates the right iterator in the backward direction till the
225     * condition is satisfied. If the join condition is satisfied, returns
226     * true to indicate there is an matching record in the right iterator
227     * corresponding to current record from the left iterator.
228     * @return false if join condition is dissatisfied for all records from the
229     * right iterator, true otherwise.
230     * @throws DException
231     */

232    private boolean ifConditionSolvedBackward() throws DException {
233       do {
234          if (conditionVariableValue.run().hashCode() == 0) {
235             state = VALIDSTATE;
236             return true;
237          }
238       } while (rightIterator.previous());
239       return false;
240    }
241
242    /**
243     * This method returns the key by concating the key of underlying Iterator.
244     * it returns the merged key of left iterator and null corresponding to the
245     * right table.
246     * @return key of special right join iterator
247     * @throws com.daffodilwoods.database.resource.DException
248     */

249    public Object JavaDoc getKey() throws com.daffodilwoods.database.resource.DException {
250       ArrayList list = new ArrayList();
251       Object JavaDoc[] leftKeys = (Object JavaDoc[]) leftIterator.getKey();
252       list.addAll(java.util.Arrays.asList(leftKeys));
253       for (int i = 0; i < rightCount; i++) {
254          list.add(null);
255       }
256       return list.toArray();
257    }
258
259    private void moveAcctoGroupKey(Object JavaDoc[] keys) throws DException {
260       if (leftKeyCount == 0) {
261          leftIterator.first();
262       } else {
263          Object JavaDoc[] leftKeys = new Object JavaDoc[leftKeyCount];
264          System.arraycopy(keys, 0, leftKeys, 0, leftKeyCount);
265          leftIterator.move(leftKeys);
266       }
267       if (rightKeyCount == 0) {
268          rightIterator.first();
269       } else {
270          int rightLength = keys.length - leftKeyCount;
271          Object JavaDoc[] rightKeys = new Object JavaDoc[rightLength];
272          System.arraycopy(keys, leftKeyCount, rightKeys, 0, rightLength);
273          if (isKeyNull(rightKeys)) {
274             rightNull = true;
275          } else {
276             rightNull = false;
277             rightIterator.move(rightKeys);
278          }
279       }
280       state = VALIDSTATE;
281    }
282
283    /**
284     * This method is responsible to align both underlying iterator acc. to key
285     * pasesed. For a Special right join Iterator created on query having group
286     * by clause, call is transfered to moveAcctoGroupKey method.
287     * For a non-group by Join Query, left iterator keys are are extracted
288     * from the passed key and left iterator is aligned acc. to the extracted keys.
289     * @param keys key where to point to Special right join iterator
290     * @throws com.daffodilwoods.database.resource.DException
291     */

292    public void move(Object JavaDoc keys) throws com.daffodilwoods.database.resource.DException {
293       if (leftKeyCount != 0 || rightKeyCount != 0) {
294          moveAcctoGroupKey( (Object JavaDoc[]) keys);
295          return;
296       }
297       Object JavaDoc[] rightKeys = new Object JavaDoc[rightCount];
298       int leftCount = ( (Object JavaDoc[]) keys).length - rightCount;
299       Object JavaDoc[] leftKeys = new Object JavaDoc[leftCount];
300       System.arraycopy(keys, 0, leftKeys, 0, leftCount);
301       System.arraycopy(keys, leftCount, rightKeys, 0, rightCount);
302       leftIterator.move(leftKeys);
303       if (isKeyNull(rightKeys)) {
304          rightNull = true;
305       } else {
306          rightNull = false;
307          rightIterator.move(rightKeys);
308       }
309       state = 0;
310    }
311
312    /**
313     * The following methods are used for getting values of current record.
314     * All retrival methods use the following logic.
315     * The retrival method checks passed column, if the column corresponds to
316     * LEFT table, values are retrived from left iterator, otherwise, Null value
317     * is returned.
318     */

319    /**
320     * This method is used to retrieve the values of passed references.
321     * @param columnReferences reference for which values are to be retrived.
322     * Reference may be column or parameter.
323     * @return NonShared FieldBases denoting the value of References. Non Shared
324     * FieldBases are those for which BufferRange is not shared with some other
325     * FieldBase.
326     * @throws DException
327     */

328    public Object JavaDoc getColumnValues(_Reference[] columnReferences) throws DException {
329       int len = columnReferences.length;
330       Object JavaDoc[] values = new Object JavaDoc[len];
331       for (int i = 0; i < len; i++) {
332          values[i] = getColumnValues(columnReferences[i]);
333       }
334       return values;
335    }
336
337    /**
338     * This method is responsible to check whether the passed tables
339     * corresponds to left iterator or right iterator.
340     * @param tDetails table to check
341     * @return table belongs to LEFT or RIGHT iterator.
342     * @throws DException
343     */

344    private int searchInMapping(TableDetails tDetails) throws DException {
345       for (int i = 0; i < tableDetailsMapping.length; i++) {
346          if (tableDetailsMapping[i][0] == tDetails) {
347             return ( (Integer JavaDoc) tableDetailsMapping[i][1]).intValue();
348          }
349       }
350       return -1;
351    }
352
353    /**
354     * This method is used to retrieve all the values from the join query.
355     * This method returns an merged array having an array of null values of
356     * length equal to number of columns corresponding to right table and an array
357     * having all the values from the left iterator.
358     * @return NonShared FieldBases denoting the values of all columns of join query.
359     * Non Shared FieldBases are those for which BufferRange is not shared with
360     * some other FieldBase.
361     * @throws DException
362     */

363    public Object JavaDoc getColumnValues() throws DException {
364       ArrayList aList = new ArrayList();
365       Object JavaDoc[] obj2 = null;
366       obj2= makeNullFieldLiteralArray(rightColumnCount);//Done by Sandeep on 10/02/2005 to solve NPEin JDBCRecord.getRecord
367
aList.addAll(Arrays.asList( (Object JavaDoc[]) obj2));
368       Object JavaDoc obj1 = leftIterator.getColumnValues();
369       aList.addAll(Arrays.asList( (Object JavaDoc[]) obj1));
370
371       return aList.toArray();
372    }
373
374    /**
375     * This method is used to retrieve the value of passed reference.
376     * It checks the table of column, if the column corresponds to LEFT table,
377     * values are retrived from left iterator, otherwise, NULL is returned.
378     * @param references reference for which value is to be retrived.
379     * Reference may be column or parameter.
380     * @return NonShared FieldBase denoting the value of Reference. Non Shared
381     * FieldBases are those for which BufferRange is not shared with some other
382     * FieldBase.
383     * @throws DException
384     */

385    public Object JavaDoc getColumnValues(_Reference references) throws DException {
386       Object JavaDoc values;
387       ColumnDetails refColumnDetail = (ColumnDetails) references;
388       TableDetails tDetails = refColumnDetail.getTable();
389       int index = searchInMapping(tDetails);
390       if (index == -1) {
391          return GeneralPurposeStaticClass.getColumnValuesFromQualified(leftIterator, rightIterator, references, rightNull);
392       }
393       if (index == SimpleConstants.LEFT) {
394          values = leftIterator.getColumnValues(references);
395       } else {
396          if (rightNull) {
397             values = new FieldLiteral(FieldUtility.NULLBUFFERRANGE, ( (ColumnDetails) references).getDatatype());
398          } else {
399             values = rightIterator.getColumnValues(references);
400          }
401       }
402       return values;
403    }
404
405    /**
406     * This method return the shared FieldBase for the passed reference. By Shared
407     * FieldBase we mean, BufferRange of FieldBase is shared with other FieldBase
408     * objects.
409     * @param references reference for which value is to be retrived
410     * @return shared field base correspondition to passed column reference
411     * @throws DException
412     */

413    public FieldBase field(_Reference references) throws com.daffodilwoods.database.resource.DException {
414       FieldBase values;
415       ColumnDetails refColumnDetail = (ColumnDetails) references;
416       TableDetails tDetails = refColumnDetail.getTable();
417       int index = searchInMapping(tDetails);
418       if (index == -1) {
419          return GeneralPurposeStaticClass.getFieldFromQualified(leftIterator, rightIterator, references, rightNull);
420       }
421       if (index == SimpleConstants.LEFT) {
422          values = leftIterator.field(references);
423       } else
424       if (rightNull) {
425          values = new FieldLiteral(FieldUtility.NULLBUFFERRANGE, ( (ColumnDetails) references).getDatatype());
426       } else {
427          values = rightIterator.field(references);
428       }
429       return values;
430    }
431
432    /**
433     * This method return the shared FieldBases for the passed references. By Shared
434     * FieldBase we mean, BufferRange of FieldBase is shared with other FieldBase
435     * objects.
436     * @param columnReferences reference for which values are to be retrived
437     * @return shared field base correspondition to passed column reference
438     * @throws DException
439     */

440    public FieldBase[] fields(_Reference[] columnReferences) throws com.daffodilwoods.database.resource.DException {
441       int len = columnReferences.length;
442       FieldBase[] values = new FieldBase[len];
443       for (int i = 0; i < len; i++) {
444          values[i] = field(columnReferences[i]);
445       }
446       return values;
447    }
448
449    /**
450     * This method is responsible to display the executionPlan of a Select Query.
451     * @return _ExecutionPlan
452     * @throws DException
453     */

454    public _ExecutionPlan getExecutionPlan() throws DException {
455       _ExecutionPlan plan = leftIterator.getExecutionPlan();
456       _ExecutionPlan plan1 = rightIterator.getExecutionPlan();
457       _ExecutionPlan cplans[] = new _ExecutionPlan[] {plan, plan1};
458       return new ExecutionPlan("SpecialRightJoinIterator", cplans, null, null, null);
459    }
460
461    /**
462     * This method is used to get the lowest level iterator of the passed column.
463     * For the passed column, Base iterator can not be either of the underlying
464     * iterator, since the column may correspond to either of the table. The value
465     * of passed column are retrieved by checking, column belongs to which table.
466     * Since, if column corresponds to right iterator, NULL will be returned,
467     * otherwise, value is retrived from left iterator.
468     * @param column corresponding to which, iterator has to return
469     * @return base table iterator corresponding to column passed
470     * @throws DException
471     */

472    public _Iterator getBaseIterator(ColumnDetails column) throws com.daffodilwoods.database.resource.DException {
473       return this;
474    }
475
476    /**
477     * The following methods of this class are used a intermediate in the
478     * iterator hierarchy. These methods simply transfer the call to the
479     * underlying iterator with the same arguments.
480     */

481
482    public byte[] getByteKey() throws DException{
483      return leftIterator.getByteKey();
484    }
485
486    public void moveByteKey(byte[] key) throws DException{
487       leftIterator.moveByteKey(key);
488       rightNull = true;
489     }
490
491   public String JavaDoc toString() {
492      try {
493         return "SpecialRightJoinIterator[" + leftIterator + "][" + rightIterator + "]" + conditionVariableValue.getCondition() + "]";
494      } catch (DException ex) {
495         return null;
496      }
497   }
498 }
499
Popular Tags