KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.ProjectRestrictResultSet
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.conn.LanguageConnectionContext;
32 import org.apache.derby.iapi.sql.conn.StatementContext;
33
34 import org.apache.derby.iapi.sql.execute.CursorResultSet;
35 import org.apache.derby.iapi.sql.execute.ExecRow;
36 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
37
38 import org.apache.derby.iapi.types.DataValueDescriptor;
39 import org.apache.derby.iapi.sql.Activation;
40 import org.apache.derby.iapi.sql.ResultSet;
41
42 import org.apache.derby.iapi.services.loader.GeneratedMethod;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.iapi.types.RowLocation;
47
48 import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;
49
50
51 /**
52  * Takes a table and a table filter and returns
53  * the table's rows satisfying the filter as a result set.
54  *
55  * @author ames
56  */

57 class ProjectRestrictResultSet extends NoPutResultSetImpl
58     implements CursorResultSet
59 {
60     /* Run time statistics variables */
61     public long restrictionTime;
62     public long projectionTime;
63
64     // set in constructor and not altered during
65
// life of object.
66
public NoPutResultSet source;
67     public GeneratedMethod constantRestriction;
68     public GeneratedMethod restriction;
69     public boolean doesProjection;
70     private GeneratedMethod projection;
71     private int[] projectMapping;
72     private boolean runTimeStatsOn;
73     private ExecRow mappedResultRow;
74     public boolean reuseResult;
75
76     private boolean shortCircuitOpen;
77
78     private ExecRow projRow;
79
80     //
81
// class interface
82
//
83
ProjectRestrictResultSet(NoPutResultSet s,
84                     Activation a,
85                     GeneratedMethod r,
86                     GeneratedMethod p,
87                     int resultSetNumber,
88                     GeneratedMethod cr,
89                     int mapRefItem,
90                     boolean reuseResult,
91                     boolean doesProjection,
92                     double optimizerEstimatedRowCount,
93                     double optimizerEstimatedCost)
94         throws StandardException
95     {
96         super(a, resultSetNumber, optimizerEstimatedRowCount, optimizerEstimatedCost);
97         source = s;
98         // source expected to be non-null, mystery stress test bug
99
// - sometimes get NullPointerException in openCore().
100
if (SanityManager.DEBUG)
101         {
102             SanityManager.ASSERT(source != null,
103                 "PRRS(), source expected to be non-null");
104         }
105         restriction = r;
106         projection = p;
107         constantRestriction = cr;
108         projectMapping = ((ReferencedColumnsDescriptorImpl) a.getPreparedStatement().getSavedObject(mapRefItem)).getReferencedColumnPositions();
109         this.reuseResult = reuseResult;
110         this.doesProjection = doesProjection;
111
112         // Allocate a result row if all of the columns are mapped from the source
113
if (projection == null)
114         {
115             mappedResultRow = activation.getExecutionFactory().getValueRow(projectMapping.length);
116         }
117
118         /* Remember whether or not RunTimeStatistics is on */
119         runTimeStatsOn = getLanguageConnectionContext().getRunTimeStatisticsMode();
120         constructorTime += getElapsedMillis(beginTime);
121     }
122
123     //
124
// NoPutResultSet interface
125
//
126

127     /**
128      * open a scan on the table. scan parameters are evaluated
129      * at each open, so there is probably some way of altering
130      * their values...
131      *
132      * @exception StandardException thrown if cursor finished.
133      */

134     public void openCore() throws StandardException
135     {
136         boolean constantEval = true;
137
138         beginTime = getCurrentTimeMillis();
139
140         // source expected to be non-null, mystery stress test bug
141
// - sometimes get NullPointerException in openCore().
142
if (SanityManager.DEBUG)
143         {
144             SanityManager.ASSERT(source != null,
145                 "PRRS().openCore(), source expected to be non-null");
146         }
147
148         // REVISIT: through the direct DB API, this needs to be an
149
// error, not an ASSERT; users can open twice. Only through JDBC
150
// is access to open controlled and ensured valid.
151
if (SanityManager.DEBUG)
152             SanityManager.ASSERT( ! isOpen, "ProjectRestrictResultSet already open");
153
154         if (constantRestriction != null)
155         {
156             DataValueDescriptor restrictBoolean;
157             restrictBoolean = (DataValueDescriptor)
158                     constantRestriction.invoke(activation);
159
160                 // if the result is null, we make it false --
161
// so the row won't be returned.
162
constantEval = (restrictBoolean == null) ||
163                         ((! restrictBoolean.isNull()) &&
164                             restrictBoolean.getBoolean());
165         }
166
167         if (constantEval)
168         {
169             source.openCore();
170         }
171         else
172         {
173             shortCircuitOpen = true;
174         }
175         isOpen = true;
176
177         numOpens++;
178
179         openTime += getElapsedMillis(beginTime);
180     }
181
182     /**
183      * reopen a scan on the table. scan parameters are evaluated
184      * at each open, so there is probably some way of altering
185      * their values...
186      *
187      * @exception StandardException thrown if cursor finished.
188      */

189     public void reopenCore() throws StandardException
190     {
191         boolean constantEval = true;
192
193         beginTime = getCurrentTimeMillis();
194
195         if (SanityManager.DEBUG)
196             SanityManager.ASSERT(isOpen, "ProjectRestrictResultSet not open, cannot reopen");
197
198         if (constantRestriction != null)
199         {
200             DataValueDescriptor restrictBoolean;
201             restrictBoolean = (DataValueDescriptor)
202                     constantRestriction.invoke(activation);
203
204                 // if the result is null, we make it false --
205
// so the row won't be returned.
206
constantEval = (restrictBoolean == null) ||
207                         ((! restrictBoolean.isNull()) &&
208                             restrictBoolean.getBoolean());
209         }
210
211         if (constantEval)
212         {
213             source.reopenCore();
214         }
215         else
216         {
217             shortCircuitOpen = true;
218         }
219         isOpen = true;
220
221         numOpens++;
222
223         openTime += getElapsedMillis(beginTime);
224     }
225
226     /**
227      * Return the requested values computed
228      * from the next row (if any) for which
229      * the restriction evaluates to true.
230      * <p>
231      * restriction and projection parameters
232      * are evaluated for each row.
233      *
234      * @exception StandardException thrown on failure.
235      * @exception StandardException ResultSetNotOpen thrown if not yet open.
236      *
237      * @return the next row in the result
238      */

239     public ExecRow getNextRowCore() throws StandardException {
240
241         ExecRow candidateRow = null;
242         ExecRow result = null;
243         boolean restrict = false;
244         DataValueDescriptor restrictBoolean;
245         long beginRT = 0;
246
247         /* Return null if open was short circuited by false constant expression */
248         if (shortCircuitOpen)
249         {
250             return result;
251         }
252
253         beginTime = getCurrentTimeMillis();
254         do
255         {
256             candidateRow = source.getNextRowCore();
257             if (candidateRow != null)
258             {
259                 beginRT = getCurrentTimeMillis();
260                 /* If restriction is null, then all rows qualify */
261                 if (restriction == null)
262                 {
263                     restrict = true;
264                 }
265                 else
266                 {
267                     setCurrentRow(candidateRow);
268                     restrictBoolean = (DataValueDescriptor)
269                                             restriction.invoke(activation);
270                     restrictionTime += getElapsedMillis(beginRT);
271
272                     // if the result is null, we make it false --
273
// so the row won't be returned.
274
restrict = ((! restrictBoolean.isNull()) &&
275                                  restrictBoolean.getBoolean());
276                     if (! restrict)
277                     {
278                         rowsFiltered++;
279                     }
280                 }
281
282                 /* Update the run time statistics */
283                 rowsSeen++;
284             }
285         } while ( (candidateRow != null) &&
286                   (! restrict ) );
287
288         if (candidateRow != null)
289         {
290             beginRT = getCurrentTimeMillis();
291
292             result = doProjection(candidateRow);
293
294             projectionTime += getElapsedMillis(beginRT);
295         }
296         /* Clear the current row, if null */
297         else
298         {
299             clearCurrentRow();
300         }
301
302
303         currentRow = result;
304
305         if (runTimeStatsOn)
306         {
307             if (! isTopResultSet)
308             {
309                 /* This is simply for RunTimeStats */
310                 /* We first need to get the subquery tracking array via the StatementContext */
311                 StatementContext sc = activation.getLanguageConnectionContext().getStatementContext();
312                 subqueryTrackingArray = sc.getSubqueryTrackingArray();
313             }
314             nextTime += getElapsedMillis(beginTime);
315         }
316         return result;
317     }
318
319     /**
320      * Return the total amount of time spent in this ResultSet
321      *
322      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
323      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
324      *
325      * @return long The total amount of time spent (in milliseconds).
326      */

327     public long getTimeSpent(int type)
328     {
329         long totTime = constructorTime + openTime + nextTime + closeTime;
330
331         if (type == CURRENT_RESULTSET_ONLY)
332         {
333             return totTime - source.getTimeSpent(ENTIRE_RESULTSET_TREE);
334         }
335         else
336         {
337             return totTime;
338         }
339     }
340
341     // ResultSet interface
342

343     /**
344      * If the result set has been opened,
345      * close the open scan.
346      *
347      * @exception StandardException thrown on error
348      */

349     public void close() throws StandardException
350     {
351         /* Nothing to do if open was short circuited by false constant expression */
352         if (shortCircuitOpen)
353         {
354             isOpen = false;
355             shortCircuitOpen = false;
356             return;
357         }
358
359         beginTime = getCurrentTimeMillis();
360         if ( isOpen ) {
361
362             // we don't want to keep around a pointer to the
363
// row ... so it can be thrown away.
364
// REVISIT: does this need to be in a finally
365
// block, to ensure that it is executed?
366
clearCurrentRow();
367
368             source.close();
369
370             super.close();
371         }
372         else
373             if (SanityManager.DEBUG)
374                 SanityManager.DEBUG("CloseRepeatInfo","Close of ProjectRestrictResultSet repeated");
375
376         closeTime += getElapsedMillis(beginTime);
377     }
378
379     public void finish() throws StandardException
380     {
381         source.finish();
382         finishAndRTS();
383     }
384
385     //
386
// CursorResultSet interface
387
//
388

389     /**
390      * Gets information from its source. We might want
391      * to have this take a CursorResultSet in its constructor some day,
392      * instead of doing a cast here?
393      *
394      * @see CursorResultSet
395      *
396      * @return the row location of the current cursor row.
397      * @exception StandardException thrown on failure.
398      */

399     public RowLocation getRowLocation() throws StandardException {
400         if (SanityManager.DEBUG)
401             SanityManager.ASSERT(source instanceof CursorResultSet, "source is not CursorResultSet");
402         return ( (CursorResultSet)source ).getRowLocation();
403     }
404
405     /**
406      * Gets last row returned.
407      *
408      * @see CursorResultSet
409      *
410      * @return the last row returned.
411      * @exception StandardException thrown on failure.
412      */

413     /* RESOLVE - this should return activation.getCurrentRow(resultSetNumber),
414      * once there is such a method. (currentRow is redundant)
415      */

416     public ExecRow getCurrentRow() throws StandardException {
417         ExecRow candidateRow = null;
418         ExecRow result = null;
419         boolean restrict = false;
420         DataValueDescriptor restrictBoolean;
421
422         if (SanityManager.DEBUG)
423             SanityManager.ASSERT(isOpen, "PRRS is expected to be open");
424
425         /* Nothing to do if we're not currently on a row */
426         if (currentRow == null)
427         {
428             return null;
429         }
430
431         /* Call the child result set to get it's current row.
432          * If no row exists, then return null, else requalify it
433          * before returning.
434          */

435         candidateRow = ((CursorResultSet) source).getCurrentRow();
436         if (candidateRow != null) {
437             setCurrentRow(candidateRow);
438                 /* If restriction is null, then all rows qualify */
439             restrictBoolean = (DataValueDescriptor)
440                     ((restriction == null) ? null : restriction.invoke(activation));
441
442             // if the result is null, we make it false --
443
// so the row won't be returned.
444
restrict = (restrictBoolean == null) ||
445                         ((! restrictBoolean.isNull()) &&
446                             restrictBoolean.getBoolean());
447         }
448
449         if (candidateRow != null && restrict)
450         {
451             result = doProjection(candidateRow);
452         }
453
454         currentRow = result;
455         /* Clear the current row, if null */
456         if (result == null) {
457             clearCurrentRow();
458         }
459
460         return currentRow;
461     }
462
463     /**
464      * Do the projection against the source row. Use reflection
465      * where necessary, otherwise get the source column into our
466      * result row.
467      *
468      * @param sourceRow The source row.
469      *
470      * @return The result of the projection
471      *
472      * @exception StandardException thrown on failure.
473      */

474     private ExecRow doProjection(ExecRow sourceRow)
475         throws StandardException
476     {
477         // No need to use reflection if reusing the result
478
if (reuseResult && projRow != null)
479         {
480             return projRow;
481         }
482
483         ExecRow result;
484
485         // Use reflection to do as much of projection as required
486
if (projection != null)
487         {
488             result = (ExecRow) projection.invoke(activation);
489         }
490         else
491         {
492             result = mappedResultRow;
493         }
494
495         // Copy any mapped columns from the source
496
for (int index = 0; index < projectMapping.length; index++)
497         {
498             if (projectMapping[index] != -1)
499             {
500                 result.setColumn(index + 1, sourceRow.getColumn(projectMapping[index]));
501             }
502         }
503
504         /* We need to reSet the current row after doing the projection */
505         setCurrentRow(result);
506
507         /* Remember the result if reusing it */
508         if (reuseResult)
509         {
510             projRow = result;
511         }
512         return result;
513     }
514
515     /**
516      * Do the projection against the sourceRow. If the source of the result set
517      * is of type ProjectRestrictResultSet, the projection by that result set
518      * will also be performed.
519      *
520      * @param sourceRow row to be projected
521      *
522      * @return The result of the projection
523      *
524      * @exception StandardException thrown on failure.
525      */

526     public ExecRow doBaseRowProjection(ExecRow sourceRow)
527         throws StandardException
528     {
529         final ExecRow result;
530         if (source instanceof ProjectRestrictResultSet) {
531             ProjectRestrictResultSet prs = (ProjectRestrictResultSet) source;
532             result = prs.doBaseRowProjection(sourceRow);
533         } else {
534             result = sourceRow.getNewNullRow();
535             result.setRowArray(sourceRow.getRowArray());
536         }
537         return doProjection(result);
538     }
539
540     /**
541      * Get projection mapping array. The array consist of indexes which
542      * maps the column in a row array to another position in the row array.
543      * If the value is projected out of the row, the value is negative.
544      * @return projection mapping array.
545      */

546     public int[] getBaseProjectMapping()
547     {
548         final int[] result;
549         if (source instanceof ProjectRestrictResultSet) {
550             result = new int[projectMapping.length];
551             final ProjectRestrictResultSet prs = (ProjectRestrictResultSet) source;
552             final int[] sourceMap = prs.getBaseProjectMapping();
553             for (int i=0; i<projectMapping.length; i++) {
554                 if (projectMapping[i] > 0) {
555                     result[i] = sourceMap[projectMapping[i] - 1];
556                 }
557             }
558         } else {
559             result = projectMapping;
560         }
561         return result;
562     }
563     
564     /**
565      * Is this ResultSet or it's source result set for update
566      *
567      * @return Whether or not the result set is for update.
568      */

569     public boolean isForUpdate()
570     {
571         return source.isForUpdate();
572     }
573
574     /**
575      * @see NoPutResultSet#updateRow
576      */

577     public void updateRow (ExecRow row) throws StandardException {
578         source.updateRow(row);
579     }
580
581     /**
582      * @see NoPutResultSet#markRowAsDeleted
583      */

584     public void markRowAsDeleted() throws StandardException {
585         source.markRowAsDeleted();
586     }
587
588 }
589
590
591
592
593
Popular Tags