KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.LastIndexKeyResultSet
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.sql.execute.CursorResultSet;
25 import org.apache.derby.iapi.error.StandardException;
26
27 import org.apache.derby.iapi.sql.ResultSet;
28 import org.apache.derby.iapi.sql.execute.ExecRow;
29 import org.apache.derby.iapi.sql.execute.ExecIndexRow;
30 import org.apache.derby.iapi.sql.execute.ExecutionContext;
31 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
32
33 import org.apache.derby.iapi.sql.Activation;
34
35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
36
37 import org.apache.derby.iapi.store.access.ConglomerateController;
38 import org.apache.derby.iapi.store.access.GenericScanController;
39 import org.apache.derby.iapi.store.access.Qualifier;
40 import org.apache.derby.iapi.store.access.ScanController;
41 import org.apache.derby.iapi.store.access.TransactionController;
42
43 import org.apache.derby.iapi.services.sanity.SanityManager;
44
45 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
46
47 import org.apache.derby.iapi.services.loader.GeneratedMethod;
48
49 import org.apache.derby.iapi.services.io.FormatableBitSet;
50
51 import java.util.Properties JavaDoc;
52
53 /**
54  * Return the last key in an index. Used to perform
55  * max().
56  *
57  * @author jamie
58  */

59 class LastIndexKeyResultSet extends NoPutResultSetImpl
60 {
61     protected ExecRow candidate;
62
63     // set in constructor and not altered during
64
// life of object.
65
protected long conglomId;
66     protected GeneratedMethod resultRowAllocator;
67     protected GeneratedMethod startKeyGetter;
68     protected int startSearchOperator;
69     protected GeneratedMethod stopKeyGetter;
70     protected int stopSearchOperator;
71     protected Qualifier[][] qualifiers;
72     public String JavaDoc tableName;
73     public String JavaDoc userSuppliedOptimizerOverrides;
74     public String JavaDoc indexName;
75     protected boolean runTimeStatisticsOn;
76     protected FormatableBitSet accessedCols;
77
78     public int isolationLevel;
79     public int lockMode;
80
81     // Run time statistics
82
public String JavaDoc stopPositionString;
83     public boolean coarserLock;
84     public boolean returnedRow;
85
86     /**
87      * A last index key result set returns the last row from
88      * the index in question. It is used as an ajunct to max().
89      *
90      * @param activation the activation for this result set,
91      * which provides the context for the row allocation operation.
92      * @param resultSetNumber The resultSetNumber for the ResultSet
93      * @param resultRowAllocator a reference to a method in the activation
94      * that creates a holder for the result row of the scan. May
95      * be a partial row. <verbatim>
96      * ExecRow rowAllocator() throws StandardException; </verbatim>
97      * @param conglomId the conglomerate of the table to be scanned.
98      * @param tableName The full name of the table
99      * @param userSuppliedOptimizerOverrides Overrides specified by the user on the sql
100      * @param indexName The name of the index, if one used to access table.
101      * @param colRefItem An saved item for a bitSet of columns that
102      * are referenced in the underlying table. -1 if
103      * no item.
104      * @param lockMode The lock granularity to use (see
105      * TransactionController in access)
106      * @param tableLocked Whether or not the table is marked as using table locking
107      * (in sys.systables)
108      * @param isolationLevel Isolation level (specified or not) to use on scans
109      * @param optimizerEstimatedRowCount Estimated total # of rows by
110      * optimizer
111      * @param optimizerEstimatedCost Estimated total cost by optimizer
112      *
113      * @exception StandardException thrown when unable to create the
114      * result set
115      */

116     public LastIndexKeyResultSet
117     (
118         Activation activation,
119         int resultSetNumber,
120         GeneratedMethod resultRowAllocator,
121         long conglomId,
122         String JavaDoc tableName,
123         String JavaDoc userSuppliedOptimizerOverrides,
124         String JavaDoc indexName,
125         int colRefItem,
126         int lockMode,
127         boolean tableLocked,
128         int isolationLevel,
129         double optimizerEstimatedRowCount,
130         double optimizerEstimatedCost
131     ) throws StandardException
132     {
133         super(activation,
134                 resultSetNumber,
135                 optimizerEstimatedRowCount,
136                 optimizerEstimatedCost);
137
138         this.conglomId = conglomId;
139
140         if (SanityManager.DEBUG)
141         {
142             SanityManager.ASSERT( activation!=null, "this scan must get activation context");
143             SanityManager.ASSERT( resultRowAllocator!= null, "this scan must get row allocator");
144         }
145
146         this.resultRowAllocator = resultRowAllocator;
147         this.tableName = tableName;
148         this.userSuppliedOptimizerOverrides = userSuppliedOptimizerOverrides;
149         this.indexName = indexName;
150         this.lockMode = lockMode;
151         if (colRefItem != -1)
152         {
153             this.accessedCols = (FormatableBitSet)(activation.getPreparedStatement().
154                         getSavedObject(colRefItem));
155         }
156         /* Isolation level - translate from language to store */
157         // If not specified, get current isolation level
158
if (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL)
159         {
160             isolationLevel = lcc.getCurrentIsolationLevel();
161         }
162
163         if (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)
164         {
165             this.isolationLevel = TransactionController.ISOLATION_SERIALIZABLE;
166         }
167         else
168         {
169             /* NOTE: always do row locking on READ COMMITTED/UNCOMMITTED
170              * and repeatable read scans unless the table is marked as
171              * table locked (in sys.systables).
172              *
173              * We always get instantaneous locks as we will complete
174              * the scan before returning any rows and we will fully
175              * requalify the row if we need to go to the heap on a next().
176              */

177
178             if (! tableLocked)
179             {
180                 this.lockMode = TransactionController.MODE_RECORD;
181             }
182
183             if (isolationLevel ==
184                     ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL)
185             {
186                 this.isolationLevel =
187                     TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK;
188             }
189             else if (isolationLevel ==
190                         ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL)
191             {
192                 this.isolationLevel =
193                     TransactionController.ISOLATION_READ_UNCOMMITTED;
194             }
195             else if (isolationLevel ==
196                         ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL)
197             {
198                 this.isolationLevel =
199                     TransactionController.ISOLATION_REPEATABLE_READ;
200             }
201         }
202
203         if (SanityManager.DEBUG)
204         {
205             SanityManager.ASSERT(
206                 ((isolationLevel ==
207                       ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) ||
208                  (isolationLevel ==
209                       ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) ||
210                  (isolationLevel ==
211                       ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) ||
212                  (isolationLevel ==
213                       ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)),
214
215                 "Invalid isolation level - " + isolationLevel);
216         }
217
218         runTimeStatisticsOn = getLanguageConnectionContext().getRunTimeStatisticsMode();
219
220         /* Only call row allocators once */
221         candidate = (ExecRow) resultRowAllocator.invoke(activation);
222         constructorTime += getElapsedMillis(beginTime);
223
224         /*
225         ** If scan tracing is turned on, print information about this
226         ** LastIndexKeyResultSet when it is first opened.
227         */

228         if (SanityManager.DEBUG)
229         {
230             if (SanityManager.DEBUG_ON("ScanTrace"))
231             {
232                 //traceScanParameters();
233
}
234         }
235
236         activation.informOfRowCount(this, 1);
237     }
238
239     /////////////////////////////////////////////////////
240
//
241
// ResultSet interface (leftover from NoPutResultSet)
242
//
243
/////////////////////////////////////////////////////
244

245     /**
246     * open a scan on the table. scan parameters are evaluated
247     * at each open, so there is probably some way of altering
248     * their values...
249      *
250      * @exception StandardException thrown on failure to open
251     */

252     public void openCore() throws StandardException
253     {
254         ExecRow candidateCopy = candidate.getClone();
255
256         beginTime = getCurrentTimeMillis();
257         if (SanityManager.DEBUG)
258         {
259             SanityManager.ASSERT(!isOpen, "LastIndexKeyResultSet already open");
260         }
261
262         isOpen = true;
263         TransactionController tc = activation.getTransactionController();
264
265         /*
266         ** Grab the last row. Note that if there are deletes
267         ** left lying around and no real row to return, then
268         ** the row array gets set even though the scan doesn't
269         ** return a row, so be careful to handle this correctly.
270         */

271         if (tc.fetchMaxOnBtree(
272                     conglomId, // conglomerate to open
273
0, // open mode
274
lockMode,
275                     isolationLevel,
276                     accessedCols,
277                     candidateCopy.getRowArray()))
278         {
279             currentRow =
280               getCompactRow(candidateCopy, accessedCols, (FormatableBitSet) null, true);
281             setCurrentRow(currentRow);
282         }
283         else
284         {
285             clearCurrentRow();
286         }
287             
288         numOpens++;
289         openTime += getElapsedMillis(beginTime);
290     }
291
292     /**
293      * Return the next row (if any) from the scan (if open).
294      *
295      * @exception StandardException thrown on failure to get next row
296      */

297     public ExecRow getNextRowCore() throws StandardException
298     {
299         if (returnedRow || !isOpen)
300         {
301             clearCurrentRow();
302         }
303         else
304         {
305             returnedRow = true;
306         }
307         return currentRow;
308     }
309
310     /**
311      * If the result set has been opened,
312      * close the open scan.
313      * @exception StandardException thrown on failure to close
314      */

315     public void close() throws StandardException
316     {
317         beginTime = getCurrentTimeMillis();
318         if (isOpen)
319         {
320             isOpen = false;
321             clearCurrentRow();
322
323             super.close();
324         }
325         else
326         {
327             if (SanityManager.DEBUG)
328             {
329                 SanityManager.DEBUG("CloseRepeatInfo","Close of LastIndexKeyResultSet repeated");
330             }
331         }
332
333         closeTime += getElapsedMillis(beginTime);
334     }
335
336     /**
337      * Return the total amount of time spent in this ResultSet
338      *
339      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
340      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
341      *
342      * @return long The total amount of time spent (in milliseconds).
343      */

344     public long getTimeSpent(int type)
345     {
346         long totTime = constructorTime + openTime + nextTime + closeTime;
347
348         /* RESOLVE - subtract out store time later, when available */
349         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
350         {
351             return totTime;
352         }
353         else
354         {
355             return totTime;
356         }
357     }
358
359
360     /**
361      * This result set has its row from the last fetch done.
362      * If the cursor is closed, a null is returned.
363      *
364      * @see CursorResultSet
365      *
366      * @return the last row returned;
367      * @exception StandardException thrown on failure.
368      */

369     public ExecRow getCurrentRow() throws StandardException
370     {
371         return currentRow;
372     }
373
374     /**
375      * Print the parameters that constructed this result set to the
376      * trace stream.
377      */

378 /*
379     private final void traceScanParameters()
380     {
381         if (SanityManager.DEBUG)
382         {
383             HeaderPrintWriter traceStream = SanityManager.GET_DEBUG_STREAM();
384
385             traceStream.println("");
386             traceStream.println("LastIndexKeyResultSet number " +
387                                 resultSetNumber +
388                                 " parameters:");
389
390             traceStream.println("");
391             traceStream.println("\tTable name: " + tableName);
392             if (indexName != null)
393             {
394                 traceStream.println("\tIndex name: " + indexName);
395             }
396             traceStream.println("");
397         }
398     }
399 */

400
401 }
402
Popular Tags