KickJava   Java API By Example, From Geeks To Geeks.

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


1 package com.daffodilwoods.daffodildb.server.sql99.dql.iterator.table;
2
3 import com.daffodilwoods.daffodildb.client.*;
4 import com.daffodilwoods.daffodildb.server.serversystem.*;
5 import com.daffodilwoods.daffodildb.server.sql99.common.*;
6 import com.daffodilwoods.daffodildb.server.sql99.dql.iterator.*;
7 import com.daffodilwoods.daffodildb.server.sql99.utils.*;
8 import com.daffodilwoods.daffodildb.utils.*;
9 import com.daffodilwoods.daffodildb.utils.comparator.*;
10 import com.daffodilwoods.database.resource.*;
11 import com.daffodilwoods.database.utility.*;
12
13 /**
14  * This Class handles the retrieval of records from a query having DISTINCT
15  * clause with the select column list. With DISTINCT clause, given query
16  * retrieves the unique values of specified columns in selectcolumnlist.
17  * The underlying iterator has SORTED DATA.
18  */

19
20
21 public class DistinctIterator extends BaseSingleIterator implements TypeConstants /*, _TableOperations, _UserTableOperations */ {
22
23    /**
24     * Variable representing the values of previous record to check the uniqueness.
25     */

26    private Object JavaDoc previousRecord;
27    /**
28     * List of the columns specified in the select list.
29     */

30    private _Reference[] selectReferences;
31    /**
32     * Variable required to retrive the values of those columns that has
33     * references i.e ? (question marks).
34     */

35    private _VariableValues variableValues;
36    /**
37     * Variable to represent the state of the distinct iterator.
38     */

39    private int state;
40    /**
41     * Variable required to compare one set of selected column values with
42     * another set of values
43     */

44    private SuperComparator superComparator;
45
46
47    public DistinctIterator(_Iterator iterator0, _Reference[] selectReferences0, _Reference[] selectListQuestionReferences, _ServerSession serverSession) {
48       super(iterator0);
49       selectReferences = selectReferences0;
50       state = INVALIDSTATE;
51       variableValues = new VariableValues(selectListQuestionReferences, serverSession); // For SubQuery References and Question Marks
52
try {
53          variableValues.setIterator(iterator0); // For Values of Functional Columns
54
} catch (DException ex) {
55       }
56    }
57
58    /**
59     * The following methods are navigation methods for DISTINCT iterator.
60     * Since, the data of the underlying iterator is sorted, once, one distinct
61     * set of selected column values found, the same record will never occur
62     * again. Thus, selected column values of the the previous record are compared
63     * with that of new record got after navigating the underlying iterator. IF
64     * values are same, new record is skipped and navigation is continued till
65     * till distinct record is found, Else record is returned.
66    */

67    /**
68     * This method is responsible for retrieving the first record from the iterator.
69     * If the underlying iterator has no records returns false, else selected
70     * column values from the first record are cached to ensure uniqueness of the
71     * columns specified in the select list and return true.
72     * @return true if a record found, false otherwise.
73     * @throws DException
74     */

75    public boolean first() throws DException {
76       boolean flag = iterator.first();
77       if (flag) {
78          state = VALIDSTATE;
79          previousRecord = getReferenceValues();
80       } else {
81          state = AFTERLAST;
82       }
83       return flag;
84    }
85
86    /**
87     * This method is responsible for retrival of the next record.
88     * 1. If next Record is retrived from the underlying iterator, goto step 2,
89     * else return false.
90     * 2. Get selected column values from next record and compare these values
91     * with cached (previous) record values, If values are distinct, update
92     * cached previous selected column values. Return true, Else goto step 1
93     * to find next distinct set of selected column values.
94     * @return true if record is found, false otherwise.
95     * @throws DException
96     */

97    public boolean next() throws DException {
98       switch (state) {
99          case INVALIDSTATE:
100             throw new DException("DSE4116", null);
101          case BEFOREFIRST:
102             return first();
103          case AFTERLAST:
104             return false;
105       }
106       boolean flag = moveForward();
107       previousRecord = flag ? getReferenceValues() : previousRecord;
108       if(!flag)
109         state=AFTERLAST;
110
111       return flag;
112    }
113
114    /**
115     * This method is responsible for retrival of the previous record.
116     * 1. If previous Record is retrived from the underlying iterator,
117     * goto step 2, else return false.
118     * 2. Get selected column values from previous record and compare these values
119     * with cached (previous) record values, If values are distinct, update
120     * cached previous selected column values. Return true, Else goto step 1
121     * to find previous distinct set of selected column values.
122     * @return true if record is found, false otherwise.
123     * @throws DException
124     */

125    public boolean previous() throws DException {
126       switch (state) {
127          case INVALIDSTATE:
128             throw new DException("DSE4117", null);
129          case BEFOREFIRST:
130             return false;
131          case AFTERLAST:
132             return last();
133       }
134       boolean flag = moveBackward();
135       previousRecord = flag ? getReferenceValues() : previousRecord;
136       if(!flag)
137         state=BEFOREFIRST;
138       return flag;
139    }
140
141    /**
142     * This method is responsible for retrieving the last record from the iterator.
143     * If the underlying iterator has no records returns false, else selected
144     * column values from the first record are cached to ensure uniqueness of the
145     * columns specified in the select list and return true.
146     * @return true if a record found, false otherwise.
147     * @throws DException
148     */

149    public boolean last() throws DException {
150       boolean flag = iterator.last();
151       if (flag) {
152          state = VALIDSTATE;
153          previousRecord = getReferenceValues();
154       } else {
155          state = BEFOREFIRST;
156       }
157       return flag;
158    }
159
160    /**
161     * Navigates the underlying iterator in forward direction until distinct
162     * record is found. Records with same values are skipped.
163     * @return true if distinct record found, false otherwise.
164     * @throws DException
165     */

166    private boolean moveForward() throws DException {
167       boolean flag;
168       while ( (flag = iterator.next()) && checkForDistinctRecord(getReferenceValues())) {
169          ;
170       }
171       return flag;
172    }
173
174    /**
175     * Navigates the underlying iterator in backward direction untill
176     * distinct record is found.
177     * @return true if distinct record found, false otherwise.
178     * @throws DException
179     */

180    private boolean moveBackward() throws DException {
181       boolean flag;
182       while ( (flag = iterator.previous()) && checkForDistinctRecord(getReferenceValues())) {
183          ;
184       }
185       return flag;
186    }
187
188    /**
189     * This method is responsible to compare a set of selected column values
190     * with that of other set. It uses the comparator to compare records.
191     * @param nextRecord new record to be compared with the previous cached
192     * record values.
193     * @return true if records are same, false otherwise.
194     * @throws DException
195     */

196    private boolean checkForDistinctRecord(Object JavaDoc nextRecord) throws DException {
197       try {
198          boolean b = superComparator.compare(previousRecord, nextRecord) == 0;
199          return b;
200       } catch (NullPointerException JavaDoc ex) {
201          superComparator = getAppropriateComparator(selectReferences);
202          boolean b = superComparator.compare(previousRecord, nextRecord) == 0;
203          return b;
204       }
205    }
206
207    /**
208     * This method is responsible to get the comparator to compare the an array
209     * of values of columns passed in the select list with another set of values.
210     * @param columns columns corresponding to which comparator is to retrun
211     * @return comparator to compare the records with values of columns specified
212     * in select column list of query
213     * @throws DException
214     */

215    private SuperComparator getAppropriateComparator(_Reference[] columns) throws DException {
216       int length = columns.length;
217       SuperComparator[] comparators = new SuperComparator[length];
218       for (int i = 0; i < length; i++) {
219          if (! ( (ColumnDetails) columns[i]).canUseByteComparison()) {
220             comparators[i] = new CPckfduDpnqbsbups();
221             continue;
222          }
223          int type = ( (ColumnDetails) columns[i]).getType();
224          switch (type) {
225             case FUNCTIONAL:
226             case GROUPING:
227             case CASEEXPRESSION:
228             case SCALARFUNCTION:
229             case CONSTANT:
230             case USERFUNCTION :
231               comparators[i] = new CPckfduDpnqbsbups();
232                break;
233             case REFERENCE:
234                try {
235                   comparators[i] = GetByteComparator.getComparator(columns[i].getDatatype(), true,
236                       ( (ColumnDetails) columns[i]).getTable().getColumnCharacteristics().getCollator());
237                } catch (DException ex) {
238                   throw ex;
239                }
240                break;
241          }
242       }
243       return new DistinctComparator(comparators);
244    }
245
246    /**
247     * This method is used to retrieve the values of the columns specified
248     * in select column list.
249     * @return values of the current.
250     * @throws DException
251     */

252    private Object JavaDoc getReferenceValues() throws DException {
253       int i = 0, length = selectReferences.length;
254       Object JavaDoc[] values = new Object JavaDoc[length];
255       for (; i < length; i++) {
256          values[i] = getSingleReferenceValue(selectReferences[i]);
257       }
258       return values;
259    }
260
261    /**
262     * This method checks, if passed column in the column list corresponds to
263     * the table, its values are retrived from the iterator, otherwise, call
264     * is transferred to evaluate the expression passed in column list.
265     * @param reference column for which value is to be retrieved
266     * @return NonShared FieldBase denoting the value of passed column.
267     * Non Shared FieldBases are those for which BufferRange is not shared with
268     * some other FieldBase.
269     * @throws DException
270     */

271    private Object JavaDoc getSingleReferenceValue(_Reference reference) throws DException {
272       ColumnDetails column = (ColumnDetails) reference;
273       return column.getTableDetails() != null ? iterator.getColumnValues(reference)
274           : column.run(variableValues);
275    }
276
277    /**
278     * The following methods are used for retrival of values of current record.
279     */

280    /**
281     * This method is used to retrieve the values of passed references.
282     * @param leftColumnReferences reference for which values are to be retrived.
283     * Reference may be column or parameter.
284     * @return NonShared FieldBases denoting the value of References. Non Shared
285     * FieldBases are those for which BufferRange is not shared with some other
286     * FieldBase.
287     * @throws DException
288     */

289    public Object JavaDoc getColumnValues(_Reference[] leftColumnReferences) throws DException {
290       int length = leftColumnReferences.length;
291       Object JavaDoc[] value = new Object JavaDoc[length];
292       for (int i = 0; i < length; i++) {
293          value[i] = iterator.getColumnValues(leftColumnReferences[i]);
294       }
295       return value;
296    }
297
298    /**
299     * This method is used to retrieve the value of passed reference.
300     * @param references reference for which value is to be retrived.
301     * Reference may be column or parameter.
302     * @return NonShared FieldBase denoting the value of Reference. Non Shared
303     * FieldBases are those for which BufferRange is not shared with some other
304     * FieldBase.
305     * @throws DException
306     */

307    public Object JavaDoc getColumnValues(_Reference references) throws DException {
308       return iterator.getColumnValues(references);
309    }
310
311    /**
312     * This method is used to retrieve the values of passed references.
313     * @param parm1 column indexes for which values are to be retrived.
314     * @return NonShared FieldBases denoting the value of References. Non Shared
315     * FieldBases are those for which BufferRange is not shared with some other
316     * FieldBase.
317     * @throws DException
318     */

319    public Object JavaDoc getColumnValues(int[] parm1) throws com.daffodilwoods.database.resource.DException {
320       return iterator.getColumnValues();
321    }
322
323    public Object JavaDoc getColumnValues() throws DException {
324       Object JavaDoc[] value = (Object JavaDoc[]) previousRecord;
325       int length = value.length;
326       Object JavaDoc[] newValues = new Object JavaDoc[length + 1];
327       System.arraycopy(value, 0, newValues, 0, length);
328       newValues[length] = new Long JavaDoc(1);
329       return newValues;
330    }
331
332    /**
333     * This method is responsible to display the executionPlan of a Select Query.
334     * @return _ExecutionPlan
335     * @throws DException
336     */

337    public _ExecutionPlan getExecutionPlan() throws DException {
338       _ExecutionPlan plan = iterator.getExecutionPlan();
339       _ExecutionPlan cplans[] = plan == null ? null : new _ExecutionPlan[] {plan};
340       return new ExecutionPlan("DistinctIterator", cplans, null, null, null);
341    }
342
343    /**
344     * This method is responsible to display the iterators hierarchy of a Select Query.
345     * @return ExecutionPlanForBrowser
346     * @throws DException
347     */

348    public ExecutionPlanForBrowser getExecutionPlanForBrowser() throws DException {
349       int length = 1;
350       ExecutionPlanForBrowser cplans[] = new ExecutionPlanForBrowser[length];
351       cplans[0] = iterator.getExecutionPlanForBrowser();
352       return new ExecutionPlanForBrowser("Distinct", "DistinctIterator", cplans, null, null, null);
353    }
354
355    /**
356     * This method is used to release the resources releated with iterator.
357     * Since, the paramerters may be of different types, comparator are
358     * required to reinitialize corresponding to passed values. These
359     * resources are released.
360     * @throws DException
361     */

362    public void releaseResource() throws DException {
363       variableValues.releaseResource();
364       iterator.releaseResource();
365       superComparator = null;
366    }
367
368    /**
369     * The following methods of this class are used a intermediate in the
370     * iterator hierarchy. These methods simply transfer the call to the
371     * underlying iterator with the same arguments.
372     */

373
374    public _Iterator getBaseIterator(ColumnDetails column) throws com.daffodilwoods.database.resource.DException {
375       return iterator.getBaseIterator(column);
376    }
377
378    public void setConditionVariableValue(_Reference[] references, Object JavaDoc[] values, int priority) throws DException {
379      if(underlyingRef!=null){
380             references = GeneralPurposeStaticClass.getJointReferences(references,underlyingRef);
381             values = GeneralPurposeStaticClass.getJointValues(this, values,underlyingRef.length);
382           }
383      iterator.setConditionVariableValue(references, values, priority);
384       variableValues.setConditionVariableValue(references, values, priority);
385    }
386
387    public boolean seekFromTop(_IndexPredicate[] parm1) throws com.daffodilwoods.database.resource.DException {
388       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._IndexIterator method*/
389       throw new java.lang.UnsupportedOperationException JavaDoc("Method seekFromTop() not yet implemented.");
390    }
391
392    public boolean seekFromBottom(_IndexPredicate[] parm1) throws com.daffodilwoods.database.resource.DException {
393       /**@todo: Implement this com.daffodilwoods.daffodildb.server.datasystem.interfaces._IndexIterator method*/
394       throw new java.lang.UnsupportedOperationException JavaDoc("Method seekFromBottom() not yet implemented.");
395    }
396
397
398    public String JavaDoc toString() {
399       String JavaDoc str = "DISTINCTITERATOR";
400       str += "[" + iterator + "]";
401       return str;
402    }
403 }
404
Popular Tags