KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.MaterializedResultSet
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.ResultSet;
32
33 import org.apache.derby.iapi.types.RowLocation;
34
35 import org.apache.derby.iapi.sql.execute.CursorResultSet;
36 import org.apache.derby.iapi.sql.execute.ExecRow;
37 import org.apache.derby.iapi.sql.execute.ExecutionContext;
38 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
39 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
40
41 import org.apache.derby.iapi.sql.Activation;
42
43 import org.apache.derby.iapi.services.loader.GeneratedMethod;
44
45 import org.apache.derby.iapi.store.access.ConglomerateController;
46 import org.apache.derby.iapi.store.access.ScanController;
47 import org.apache.derby.iapi.store.access.TransactionController;
48
49 import org.apache.derby.iapi.error.StandardException;
50 import org.apache.derby.iapi.reference.SQLState;
51
52 import org.apache.derby.iapi.services.io.FormatableBitSet;
53
54 /**
55  * Materialize the underlying ResultSet tree into a temp table on the 1st open.
56  * Return rows from temp table on subsequent scans.
57  */

58
59 class MaterializedResultSet extends NoPutResultSetImpl
60     implements CursorResultSet
61 {
62     /*
63     ** Set in constructor and not altered during life of object.
64     */

65
66     public NoPutResultSet source;
67
68
69
70     private ExecRow materializedRowBuffer;
71     protected long materializedCID;
72     public boolean materializedCreated;
73     private boolean fromSource = true;
74     protected ConglomerateController materializedCC;
75     protected ScanController materializedScan;
76     private TransactionController tc;
77     private boolean sourceDrained;
78
79     public long createTCTime;
80     public long fetchTCTime;
81
82     /**
83      * Constructor for a MaterializedResultSet
84      *
85      * @param source The NoPutResultSet from which to get rows
86      * to be materialized
87      * @param activation The activation for this execution
88      * @param resultSetNumber The resultSetNumber
89      *
90      * @exception StandardException on error
91      */

92
93     public MaterializedResultSet(NoPutResultSet source,
94                               Activation activation, int resultSetNumber,
95                               double optimizerEstimatedRowCount,
96                               double optimizerEstimatedCost) throws StandardException
97     {
98         super(activation, resultSetNumber,
99               optimizerEstimatedRowCount, optimizerEstimatedCost);
100         this.source = source;
101
102         // Get the current transaction controller
103
tc = activation.getTransactionController();
104
105         constructorTime += getElapsedMillis(beginTime);
106     }
107
108
109     //
110
// ResultSet interface (leftover from NoPutResultSet)
111
//
112

113     /**
114      * open a scan on the source. scan parameters are evaluated
115      * at each open, so there is probably some way of altering
116      * their values...
117      *
118      * @exception StandardException thrown on failure
119      */

120     public void openCore() throws StandardException
121     {
122         beginTime = getCurrentTimeMillis();
123         if (SanityManager.DEBUG)
124             SanityManager.ASSERT( ! isOpen, "MaterializedResultSet already open");
125
126         source.openCore();
127         isOpen = true;
128         numOpens++;
129
130         openTime += getElapsedMillis(beginTime);
131     }
132
133     /**
134      * reopen a scan on the table. scan parameters are evaluated
135      * at each open, so there is probably some way of altering
136      * their values...
137      *
138      * @exception StandardException thrown if cursor finished.
139      */

140     public void reopenCore() throws StandardException
141     {
142         boolean constantEval = true;
143
144         beginTime = getCurrentTimeMillis();
145
146         if (SanityManager.DEBUG)
147             SanityManager.ASSERT(isOpen, "MaterializedResultSet already open");
148
149         // Finish draining the source into the temp table
150
while (! sourceDrained)
151         {
152             getNextRowFromSource();
153         }
154
155         // Results will now come from the temp table
156
fromSource = false;
157
158         // Close the temp table if open
159
if (materializedScan != null)
160         {
161             materializedScan.close();
162         }
163
164         /* Open a scan on the temp conglomerate,
165          * if one exists.
166          */

167         if (materializedCID != 0)
168         {
169             materializedScan =
170                 tc.openScan(materializedCID,
171                     false, // hold
172
0, // for update
173
TransactionController.MODE_TABLE,
174                     TransactionController.ISOLATION_SERIALIZABLE,
175                     (FormatableBitSet) null, // all fields as objects
176
null, // start key value
177
0, // start operator
178
null, // qualifier
179
null, // stop key value
180
0); // stop operator
181

182             isOpen = true;
183         }
184
185         numOpens++;
186
187         openTime += getElapsedMillis(beginTime);
188     }
189
190     /**
191      *
192      * @exception StandardException thrown on failure
193      */

194     public ExecRow getNextRowCore() throws StandardException
195     {
196         ExecRow result = null;
197
198         beginTime = getCurrentTimeMillis();
199         if (!isOpen)
200             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
201
202         /* Should we get the next row from the source or the materialized result set? */
203         if (fromSource)
204         {
205             result = getNextRowFromSource();
206         }
207         else
208         {
209             result = getNextRowFromTempTable();
210         }
211
212         if (result != null)
213         {
214             rowsSeen++;
215         }
216
217         currentRow = result;
218         setCurrentRow(currentRow);
219
220         nextTime += getElapsedMillis(beginTime);
221
222         return result;
223     }
224
225     /* Get the next row from the source ResultSet tree and insert into the temp table */
226     private ExecRow getNextRowFromSource() throws StandardException
227     {
228         // Nothing to do if source is already drained
229
if (sourceDrained)
230         {
231             return null;
232         }
233
234         ExecRow sourceRow = null;
235         ExecRow result = null;
236
237         sourceRow = source.getNextRowCore();
238
239         if (sourceRow != null)
240         {
241             long beginTCTime = getCurrentTimeMillis();
242             /* If this is the first row from the source then clone it as our own
243              * for use when fetching from temp table.
244              * This is also the place where we create the temp table.
245              */

246             if (materializedRowBuffer == null)
247             {
248                 materializedRowBuffer = sourceRow.getClone();
249
250                 tc = activation.getTransactionController();
251
252                 materializedCID = tc.createConglomerate("heap", materializedRowBuffer.getRowArray(),
253                                                         null, null,
254                                                         TransactionController.IS_TEMPORARY |
255                                                         TransactionController.IS_KEPT);
256                 materializedCreated = true;
257                 materializedCC =
258                     tc.openConglomerate(
259                         materializedCID,
260                         false,
261                         TransactionController.OPENMODE_FORUPDATE,
262                         TransactionController.MODE_TABLE,
263                         TransactionController.ISOLATION_SERIALIZABLE);
264             }
265             materializedCC.insert(sourceRow.getRowArray());
266
267             createTCTime += getElapsedMillis(beginTCTime);
268         }
269         // Remember whether or not we've drained the source
270
else
271         {
272             sourceDrained = true;
273         }
274
275         return sourceRow;
276     }
277
278     /* Get the next Row from the temp table */
279     private ExecRow getNextRowFromTempTable() throws StandardException
280     {
281         long beginTCTime = getCurrentTimeMillis();
282         /* Get and return the next row from the temp conglomerate,
283          * if one exists.
284          */

285         if (materializedScan != null && materializedScan.fetchNext(materializedRowBuffer.getRowArray()))
286         {
287             fetchTCTime += getElapsedMillis(beginTCTime);
288             return materializedRowBuffer;
289         }
290         else
291         {
292             return null;
293         }
294     }
295
296     /**
297      * If the result set has been opened,
298      * close the open scan.
299      *
300      * @exception StandardException thrown on error
301      */

302     public void close() throws StandardException
303     {
304         beginTime = getCurrentTimeMillis();
305         if ( isOpen )
306         {
307             currentRow = null;
308             source.close();
309
310             if (materializedScan != null)
311                 materializedScan.close();
312             materializedScan = null;
313
314             if (materializedCC != null)
315                 materializedCC.close();
316             materializedCC = null;
317
318             if (materializedCreated)
319                 tc.dropConglomerate(materializedCID);
320
321             materializedCreated = false;
322
323             super.close();
324         }
325         else
326             if (SanityManager.DEBUG)
327                 SanityManager.DEBUG("CloseRepeatInfo","Close of MaterializedResultSet repeated");
328
329         closeTime += getElapsedMillis(beginTime);
330     }
331
332     /**
333      * Return the total amount of time spent in this ResultSet
334      *
335      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
336      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
337      *
338      * @return long The total amount of time spent (in milliseconds).
339      */

340     public long getTimeSpent(int type)
341     {
342         long totTime = constructorTime + openTime + nextTime + closeTime;
343
344         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
345         {
346             return totTime - source.getTimeSpent(ENTIRE_RESULTSET_TREE);
347         }
348         else
349         {
350             return totTime;
351         }
352     }
353
354     //
355
// CursorResultSet interface
356
//
357

358     /**
359      * Gets information from its source. We might want
360      * to have this take a CursorResultSet in its constructor some day,
361      * instead of doing a cast here?
362      *
363      * @see CursorResultSet
364      *
365      * @return the row location of the current cursor row.
366      *
367      * @exception StandardException thrown on failure
368      */

369     public RowLocation getRowLocation() throws StandardException
370     {
371         if (SanityManager.DEBUG)
372             SanityManager.ASSERT(source instanceof CursorResultSet, "source not CursorResultSet");
373         return ( (CursorResultSet)source ).getRowLocation();
374     }
375
376     /**
377      * Gets information from last getNextRow call.
378      *
379      * @see CursorResultSet
380      *
381      * @return the last row returned.
382      */

383     /* RESOLVE - this should return activation.getCurrentRow(resultSetNumber),
384      * once there is such a method. (currentRow is redundant)
385      */

386     public ExecRow getCurrentRow()
387     {
388         return currentRow;
389     }
390
391     //
392
// class implementation
393
//
394
}
395
Popular Tags