KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > UnionResultSet


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.UnionResultSet
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.execute;
23
24 import org.apache.derby.iapi.services.monitor.Monitor;
25
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27
28 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
29 import org.apache.derby.iapi.services.stream.InfoStreams;
30
31 import org.apache.derby.iapi.sql.execute.CursorResultSet;
32 import org.apache.derby.iapi.sql.execute.ExecRow;
33 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
34
35 import org.apache.derby.iapi.error.StandardException;
36
37 import org.apache.derby.iapi.sql.Activation;
38 import org.apache.derby.iapi.sql.ResultSet;
39 import org.apache.derby.iapi.sql.ResultDescription;
40
41 import org.apache.derby.iapi.services.loader.GeneratedMethod;
42
43 import org.apache.derby.iapi.types.RowLocation;
44
45
46 /**
47  * Takes two result sets and returns their union (all).
48  * (Any duplicate elimination is performed above this ResultSet.)
49  *
50  * @author ames
51  */

52 class UnionResultSet extends NoPutResultSetImpl
53     implements CursorResultSet {
54
55     /* Run time statistics variables */
56     public int rowsSeenLeft;
57     public int rowsSeenRight;
58     public int rowsReturned;
59
60     private int whichSource = 1; // 1 or 2, == the source we are currently on.
61
private int source1FinalRowCount = -1;
62
63     // these are set in the constructor and never altered
64
public NoPutResultSet source1;
65     public NoPutResultSet source2;
66
67
68     //
69
// class interface
70
//
71
/*
72      * implementation alternative: an array of sources,
73      * using whichSource to index into the current source.
74      */

75     public UnionResultSet(NoPutResultSet source1, NoPutResultSet source2,
76                           Activation activation,
77                           int resultSetNumber,
78                           double optimizerEstimatedRowCount,
79                           double optimizerEstimatedCost)
80     {
81         
82         super(activation, resultSetNumber,
83               optimizerEstimatedRowCount, optimizerEstimatedCost);
84         this.source1 = source1;
85         this.source2 = source2;
86         constructorTime += getElapsedMillis(beginTime);
87     }
88
89     //
90
// ResultSet interface (leftover from NoPutResultSet)
91
//
92

93     /**
94      * Returns the description of the first source.
95      * Assumes the compiler ensured both sources
96      * had the same description.
97      */

98     public ResultDescription getResultDescription() {
99         return source1.getResultDescription();
100     }
101
102     /**
103      * open the first source.
104      * @exception StandardException thrown on failure
105      */

106     public void openCore() throws StandardException
107     {
108         beginTime = getCurrentTimeMillis();
109         if (SanityManager.DEBUG)
110             SanityManager.ASSERT( ! isOpen, "UnionResultSet already open");
111
112         isOpen = true;
113         source1.openCore();
114         numOpens++;
115
116         openTime += getElapsedMillis(beginTime);
117     }
118
119     /**
120      * If there are rows still on the first source, return the
121      * next one; otherwise, switch to the second source and
122      * return a row from there.
123      * @exception StandardException thrown on failure
124      */

125     public ExecRow getNextRowCore() throws StandardException {
126         ExecRow result = null;
127
128         beginTime = getCurrentTimeMillis();
129         if ( isOpen ) {
130             switch (whichSource) {
131                 case 1 : result = source1.getNextRowCore();
132                          if ( result == (ExecRow) null ) {
133                             //source1FinalRowCount = source1.rowCount();
134
source1.close();
135                             whichSource = 2;
136                             source2.openCore();
137                             result = source2.getNextRowCore();
138                             if (result != null)
139                             {
140                                 rowsSeenRight++;
141                             }
142                          }
143                          else
144                          {
145                              rowsSeenLeft++;
146                          }
147                          break;
148                 case 2 : result = source2.getNextRowCore();
149                          if (result != null)
150                          {
151                             rowsSeenRight++;
152                          }
153                          break;
154                 default:
155                     if (SanityManager.DEBUG)
156                         SanityManager.THROWASSERT( "Bad source number in union" );
157                     break;
158             }
159         }
160
161         currentRow = result;
162         setCurrentRow(result);
163         if (result != null)
164         {
165             rowsReturned++;
166         }
167
168         nextTime += getElapsedMillis(beginTime);
169         return result;
170     }
171
172     /**
173      * If the result set has been opened,
174      * close the currently open source.
175      *
176      * @exception StandardException thrown on error
177      */

178     public void close() throws StandardException
179     {
180         beginTime = getCurrentTimeMillis();
181         if ( isOpen ) {
182
183             // we don't want to keep around a pointer to the
184
// row ... so it can be thrown away.
185
// REVISIT: does this need to be in a finally
186
// block, to ensure that it is executed?
187
clearCurrentRow();
188
189             switch (whichSource) {
190                 case 1 : source1.close();
191                          break;
192                 case 2 : source2.close();
193                          source1FinalRowCount = -1;
194                          whichSource = 1;
195                          break;
196                 default:
197                     if (SanityManager.DEBUG)
198                         SanityManager.THROWASSERT( "Bad source number in union" );
199                     break;
200             }
201
202             super.close();
203         }
204         else
205             if (SanityManager.DEBUG)
206                 SanityManager.DEBUG("CloseRepeatInfo","Close of UnionResultSet repeated");
207
208         closeTime += getElapsedMillis(beginTime);
209     }
210
211     public void finish() throws StandardException
212     {
213         source1.finish();
214         source2.finish();
215         finishAndRTS();
216     }
217
218
219     /**
220      * Return the total amount of time spent in this ResultSet
221      *
222      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
223      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
224      *
225      * @return long The total amount of time spent (in milliseconds).
226      */

227     public long getTimeSpent(int type)
228     {
229         long totTime = constructorTime + openTime + nextTime + closeTime;
230
231         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
232         {
233             return totTime - source1.getTimeSpent(ENTIRE_RESULTSET_TREE) -
234                               source2.getTimeSpent(ENTIRE_RESULTSET_TREE);
235         }
236         else
237         {
238             return totTime;
239         }
240     }
241
242     //
243
// CursorResultSet interface
244
//
245

246     /**
247         A union has a single underlying row at a time, although
248         from one of several sources.
249     
250         @see CursorResultSet
251      
252         @return the row location of the current cursor row.
253         @exception StandardException thrown on failure
254      */

255     public RowLocation getRowLocation() throws StandardException {
256         switch (whichSource) {
257             case 1 :
258                 if (SanityManager.DEBUG)
259                     SanityManager.ASSERT(source1 instanceof CursorResultSet, "source not CursorResultSet");
260                 return ((CursorResultSet)source1).getRowLocation();
261             case 2 :
262                 if (SanityManager.DEBUG)
263                     SanityManager.ASSERT(source2 instanceof CursorResultSet, "source2 not CursorResultSet");
264                 return ((CursorResultSet)source2).getRowLocation();
265             default:
266                 if (SanityManager.DEBUG)
267                     SanityManager.THROWASSERT( "Bad source number in union" );
268                 return null;
269         }
270     }
271
272     /**
273         A union has a single underlying row at a time, although
274         from one of several sources.
275     
276         @see CursorResultSet
277      
278         @return the current row.
279      * @exception StandardException thrown on failure.
280      */

281     /* RESOLVE - this should return activation.getCurrentRow(resultSetNumber),
282      * once there is such a method. (currentRow is redundant)
283      */

284     public ExecRow getCurrentRow() throws StandardException{
285         ExecRow result = null;
286
287         if (SanityManager.DEBUG) {
288             SanityManager.ASSERT(isOpen, "TSRS expected to be open");
289             if (!(whichSource == 1 || whichSource == 2))
290             {
291                 SanityManager.THROWASSERT("whichSource expected to be 1 or 2, not "
292                     + whichSource);
293             }
294         }
295
296         switch (whichSource)
297         {
298             case 1:
299                 result = ((CursorResultSet) source1).getCurrentRow();
300                 break;
301
302             case 2:
303                 result = ((CursorResultSet) source2).getCurrentRow();
304                 break;
305         }
306
307
308         currentRow = result;
309         setCurrentRow(result);
310         return result;
311     }
312
313 }
314
Popular Tags