KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.VTIResultSet
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.loader.ClassFactory;
25 import org.apache.derby.iapi.services.loader.ClassInspector;
26
27 import org.apache.derby.iapi.services.monitor.Monitor;
28
29 import org.apache.derby.iapi.services.sanity.SanityManager;
30
31 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
32 import org.apache.derby.iapi.services.stream.InfoStreams;
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.sql.Activation;
39 import org.apache.derby.iapi.sql.ResultDescription;
40 import org.apache.derby.iapi.types.DataValueDescriptor;
41 import org.apache.derby.iapi.sql.execute.ExecutionContext;
42
43 import org.apache.derby.iapi.store.access.Qualifier;
44
45 import org.apache.derby.iapi.error.StandardException;
46
47 import org.apache.derby.iapi.services.loader.GeneratedMethod;
48
49 import org.apache.derby.iapi.types.RowLocation;
50 import org.apache.derby.iapi.reference.SQLState;
51
52 import org.apache.derby.iapi.services.io.FormatableBitSet;
53 import org.apache.derby.iapi.services.io.FormatableHashtable;
54
55 import org.apache.derby.vti.DeferModification;
56 import org.apache.derby.vti.IFastPath;
57 import org.apache.derby.vti.VTIEnvironment;
58
59 import java.sql.PreparedStatement JavaDoc;
60 import java.sql.ResultSet JavaDoc;
61 import java.sql.SQLException JavaDoc;
62 import java.sql.ResultSetMetaData JavaDoc;
63
64
65 /**
66  */

67 class VTIResultSet extends NoPutResultSetImpl
68     implements CursorResultSet, VTIEnvironment {
69
70     /* Run time statistics variables */
71     public int rowsReturned;
72     public String JavaDoc javaClassName;
73
74     private boolean next;
75     private ClassInspector classInspector;
76     private GeneratedMethod row;
77     private GeneratedMethod constructor;
78     private PreparedStatement JavaDoc userPS;
79     private ResultSet userVTI;
80     private ExecRow allocatedRow;
81     private FormatableBitSet referencedColumns;
82     private boolean version2;
83     private boolean reuseablePs;
84     private boolean isTarget;
85     private FormatableHashtable compileTimeConstants;
86     private int ctcNumber;
87
88     private boolean pushedProjection;
89     private IFastPath fastPath;
90
91     private Qualifier[][] pushedQualifiers;
92
93     private boolean[] runtimeNullableColumn;
94
95     /**
96         Specified isolation level of SELECT (scan). If not set or
97         not application, it will be set to ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL
98     */

99     private int scanIsolationLevel = ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL;
100
101     //
102
// class interface
103
//
104
VTIResultSet(Activation activation, GeneratedMethod row, int resultSetNumber,
105                  GeneratedMethod constructor,
106                  String JavaDoc javaClassName,
107                  Qualifier[][] pushedQualifiers,
108                  int erdNumber,
109                  boolean version2, boolean reuseablePs,
110                  int ctcNumber,
111                  boolean isTarget,
112                  int scanIsolationLevel,
113                  double optimizerEstimatedRowCount,
114                  double optimizerEstimatedCost)
115         throws StandardException
116     {
117         super(activation, resultSetNumber,
118               optimizerEstimatedRowCount, optimizerEstimatedCost);
119         this.row = row;
120         this.constructor = constructor;
121         this.javaClassName = javaClassName;
122         this.version2 = version2;
123         this.reuseablePs = reuseablePs;
124         this.isTarget = isTarget;
125         this.pushedQualifiers = pushedQualifiers;
126         this.scanIsolationLevel = scanIsolationLevel;
127
128         if (erdNumber != -1)
129         {
130             this.referencedColumns = (FormatableBitSet)(activation.getPreparedStatement().
131                                 getSavedObject(erdNumber));
132         }
133
134         this.ctcNumber = ctcNumber;
135         compileTimeConstants = (FormatableHashtable) (activation.getPreparedStatement().
136                                 getSavedObject(ctcNumber));
137
138         constructorTime += getElapsedMillis(beginTime);
139     }
140
141     //
142
// ResultSet interface (leftover from NoPutResultSet)
143
//
144

145
146     /**
147      * Sets state to 'open'.
148      *
149      * @exception StandardException thrown if activation closed.
150      */

151     public void openCore() throws StandardException
152     {
153         beginTime = getCurrentTimeMillis();
154         if (SanityManager.DEBUG)
155             SanityManager.ASSERT( ! isOpen, "VTIResultSet already open");
156
157         isOpen = true;
158         numOpens++;
159
160         /* We need to Instantiate the user's ResultSet on the each open since
161          * there is no way to close and then reopen a java.sql.ResultSet.
162          * For Version 2 VTIs, we may be able to skip instantiated their
163          * PreparedStatement here.
164          */

165         try {
166             if (version2)
167             {
168                 userPS = (PreparedStatement JavaDoc) constructor.invoke(activation);
169
170                 if (userPS instanceof org.apache.derby.vti.Pushable) {
171                     org.apache.derby.vti.Pushable p = (org.apache.derby.vti.Pushable) userPS;
172                     if (referencedColumns != null) {
173                         pushedProjection = p.pushProjection(this, getProjectedColList());
174                     }
175                 }
176
177                 if (userPS instanceof org.apache.derby.vti.IQualifyable) {
178                     org.apache.derby.vti.IQualifyable q = (org.apache.derby.vti.IQualifyable) userPS;
179
180                     q.setQualifiers(this, pushedQualifiers);
181                 }
182                 fastPath = userPS instanceof IFastPath ? (IFastPath) userPS : null;
183
184                 if( isTarget
185                     && userPS instanceof DeferModification
186                     && activation.getConstantAction() instanceof UpdatableVTIConstantAction)
187                 {
188                     UpdatableVTIConstantAction constants = (UpdatableVTIConstantAction) activation.getConstantAction();
189                     ((DeferModification) userPS).modificationNotify( constants.statementType, constants.deferred);
190                 }
191                 
192                 if ((fastPath != null) && fastPath.executeAsFastPath())
193                     ;
194                 else
195                     userVTI = userPS.executeQuery();
196
197                 /* Save off the target VTI */
198                 if (isTarget)
199                 {
200                     activation.setTargetVTI(userVTI);
201                 }
202
203             }
204             else
205             {
206                 userVTI = (ResultSet) constructor.invoke(activation);
207             }
208
209             // Set up the nullablity of the runtime columns, may be delayed
210
setNullableColumnList();
211         }
212         catch (Throwable JavaDoc t)
213         {
214             throw StandardException.unexpectedUserException(t);
215         }
216
217
218         openTime += getElapsedMillis(beginTime);
219     }
220
221     private boolean[] setNullableColumnList() throws SQLException JavaDoc {
222
223         if (runtimeNullableColumn != null)
224             return runtimeNullableColumn;
225
226         if (userVTI == null)
227             return null;
228
229         ResultSetMetaData JavaDoc rsmd = userVTI.getMetaData();
230         boolean[] nullableColumn = new boolean[rsmd.getColumnCount() + 1];
231         for (int i = 1; i < nullableColumn.length; i++) {
232             nullableColumn[i] = rsmd.isNullable(i) != ResultSetMetaData.columnNoNulls;
233         }
234
235         return runtimeNullableColumn = nullableColumn;
236     }
237
238     /**
239      * If the VTI is a version2 vti that does not
240      * need to be instantiated multiple times then
241      * we simply close the current ResultSet and
242      * create a new one via a call to
243      * PreparedStatement.executeQuery().
244      *
245      * @see NoPutResultSet#openCore
246      * @exception StandardException thrown if cursor finished.
247      */

248     public void reopenCore() throws StandardException
249     {
250         if (reuseablePs)
251         {
252             /* close the user ResultSet.
253              */

254             if (userVTI != null)
255             {
256                 try
257                 {
258                     userVTI.close();
259                     userVTI = userPS.executeQuery();
260
261                     /* Save off the target VTI */
262                     if (isTarget)
263                     {
264                         activation.setTargetVTI(userVTI);
265                     }
266                 } catch (SQLException JavaDoc se)
267                 {
268                     throw StandardException.unexpectedUserException(se);
269                 }
270             }
271         }
272         else
273         {
274             close();
275             openCore();
276         }
277     }
278
279     /**
280      * If open and not returned yet, returns the row
281      * after plugging the parameters into the expressions.
282      *
283      * @exception StandardException thrown on failure.
284      */

285     public ExecRow getNextRowCore() throws StandardException
286     {
287         ExecRow result = null;
288
289         beginTime = getCurrentTimeMillis();
290         
291         if ( isOpen )
292         {
293             try
294             {
295                 if ((userVTI == null) && (fastPath != null)) {
296                     result = getAllocatedRow();
297                     int action = fastPath.nextRow(result.getRowArray());
298                     if (action == IFastPath.GOT_ROW)
299                         ;
300                     else if (action == IFastPath.SCAN_COMPLETED)
301                         result = null;
302                     else if (action == IFastPath.NEED_RS) {
303                         userVTI = userPS.executeQuery();
304                     }
305                 }
306                 if ((userVTI != null))
307                 {
308                     if( ! userVTI.next())
309                     {
310                         if( null != fastPath)
311                             fastPath.rowsDone();
312                         result = null;
313                     }
314                     else
315                     {
316                         // Get the cached row and fill it up
317
result = getAllocatedRow();
318                         populateFromResultSet(result);
319                         if (fastPath != null)
320                             fastPath.currentRow(userVTI, result.getRowArray());
321                     }
322                 }
323             }
324             catch (Throwable JavaDoc t)
325             {
326                 throw StandardException.unexpectedUserException(t);
327             }
328
329         }
330
331         setCurrentRow(result);
332         if (result != null)
333         {
334             rowsReturned++;
335             rowsSeen++;
336         }
337
338         nextTime += getElapsedMillis(beginTime);
339         return result;
340     }
341
342     
343
344     /**
345      * @see org.apache.derby.iapi.sql.ResultSet#close
346      *
347      * @exception StandardException thrown on error
348      */

349     public void close() throws StandardException
350     {
351         beginTime = getCurrentTimeMillis();
352         if (isOpen) {
353
354             // we don't want to keep around a pointer to the
355
// row ... so it can be thrown away.
356
// REVISIT: does this need to be in a finally
357
// block, to ensure that it is executed?
358
clearCurrentRow();
359             next = false;
360
361             /* close the user ResultSet. We have to eat any exception here
362              * since our close() method cannot throw an exception.
363              */

364             if (userVTI != null)
365             {
366                 try
367                 {
368                     userVTI.close();
369                 } catch (SQLException JavaDoc se)
370                 {
371                     throw StandardException.unexpectedUserException(se);
372                 }
373                 finally {
374                     userVTI = null;
375                 }
376             }
377             if ((userPS != null) && !reuseablePs)
378             {
379                 try
380                 {
381                     userPS.close();
382                 } catch (SQLException JavaDoc se)
383                 {
384                     throw StandardException.unexpectedUserException(se);
385                 }
386                 finally {
387                     userPS = null;
388                 }
389             }
390             super.close();
391         }
392         else
393             if (SanityManager.DEBUG)
394                 SanityManager.DEBUG("CloseRepeatInfo","Close of VTIResultSet repeated");
395
396         closeTime += getElapsedMillis(beginTime);
397     }
398
399     public void finish() throws StandardException {
400
401         // for a reusablePS it will be closed by the activation
402
// when it is closed.
403
if ((userPS != null) && !reuseablePs)
404         {
405             try
406             {
407                 userPS.close();
408                 userPS = null;
409             } catch (SQLException JavaDoc se)
410             {
411                 throw StandardException.unexpectedUserException(se);
412             }
413         }
414
415         finishAndRTS();
416
417     }
418
419     /**
420      * Return the total amount of time spent in this ResultSet
421      *
422      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
423      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
424      *
425      * @return long The total amount of time spent (in milliseconds).
426      */

427     public long getTimeSpent(int type)
428     {
429         long totTime = constructorTime + openTime + nextTime + closeTime;
430         return totTime;
431     }
432
433     //
434
// CursorResultSet interface
435
//
436

437     /**
438      * This is not operating against a stored table,
439      * so it has no row location to report.
440      *
441      * @see CursorResultSet
442      *
443      * @return a null.
444      */

445     public RowLocation getRowLocation() {
446         if (SanityManager.DEBUG)
447             SanityManager.THROWASSERT("RowResultSet used in positioned update/delete");
448         return null;
449     }
450
451     /**
452      * This is not used in positioned update and delete,
453      * so just return a null.
454      *
455      * @see CursorResultSet
456      *
457      * @return a null.
458      */

459     public ExecRow getCurrentRow() {
460         if (SanityManager.DEBUG)
461             SanityManager.THROWASSERT("RowResultSet used in positioned update/delete");
462         return null;
463     }
464
465     // Class implementation
466

467     /**
468      * Return the GeneratedMethod for instantiating the VTI.
469      *
470      * @return The GeneratedMethod for instantiating the VTI.
471      */

472     GeneratedMethod getVTIConstructor()
473     {
474         return constructor;
475     }
476
477     boolean isReuseablePs() {
478         return reuseablePs;
479     }
480
481
482     /**
483      * Cache the ExecRow for this result set.
484      *
485      * @return The cached ExecRow for this ResultSet
486      *
487      * @exception StandardException thrown on failure.
488      */

489     private ExecRow getAllocatedRow()
490         throws StandardException
491     {
492         if (allocatedRow == null)
493         {
494             allocatedRow = (ExecRow) row.invoke(activation);
495         }
496
497         return allocatedRow;
498     }
499
500     private int[] getProjectedColList() {
501
502         FormatableBitSet refs = referencedColumns;
503         int size = refs.size();
504         int arrayLen = 0;
505         for (int i = 0; i < size; i++) {
506             if (refs.isSet(i))
507                 arrayLen++;
508         }
509
510         int[] colList = new int[arrayLen];
511         int offset = 0;
512         for (int i = 0; i < size; i++) {
513             if (refs.isSet(i))
514                 colList[offset++] = i + 1;
515         }
516
517         return colList;
518     }
519     /**
520      * @exception StandardException thrown on failure to open
521      */

522     public void populateFromResultSet(ExecRow row)
523         throws StandardException
524     {
525         try
526         {
527             boolean[] nullableColumn = setNullableColumnList();
528             DataValueDescriptor[] columns = row.getRowArray();
529             // ExecRows are 0-based, ResultSets are 1-based
530
int rsColNumber = 1;
531             for (int index = 0; index < columns.length; index++)
532             {
533                 // Skip over unreferenced columns
534
if (referencedColumns != null && (! referencedColumns.get(index)))
535                 {
536                     if (!pushedProjection)
537                         rsColNumber++;
538
539                     continue;
540                 }
541
542                 columns[index].setValueFromResultSet(
543                                     userVTI, rsColNumber,
544                                     /* last parameter is whether or
545                                      * not the column is nullable
546                                      */

547                                     nullableColumn[rsColNumber]);
548                 rsColNumber++;
549             }
550
551         } catch (StandardException se) {
552             throw se;
553         }
554         catch (Throwable JavaDoc t)
555         {
556             throw StandardException.unexpectedUserException(t);
557         }
558     }
559
560     public final int getScanIsolationLevel() {
561         return scanIsolationLevel;
562     }
563
564     /*
565     ** VTIEnvironment
566     */

567     public final boolean isCompileTime() {
568         return false;
569     }
570
571     public final String JavaDoc getOriginalSQL() {
572         return activation.getPreparedStatement().getSource();
573     }
574
575     public final int getStatementIsolationLevel() {
576         return ExecutionContext.CS_TO_JDBC_ISOLATION_LEVEL_MAP[getScanIsolationLevel()];
577     }
578
579
580     public final void setSharedState(String JavaDoc key, java.io.Serializable JavaDoc value) {
581         if (key == null)
582             return;
583
584         if (compileTimeConstants == null) {
585
586             Object JavaDoc[] savedObjects = activation.getPreparedStatement().getSavedObjects();
587
588             synchronized (savedObjects) {
589
590                 compileTimeConstants = (FormatableHashtable) savedObjects[ctcNumber];
591                 if (compileTimeConstants == null) {
592                     compileTimeConstants = new FormatableHashtable();
593                     savedObjects[ctcNumber] = compileTimeConstants;
594                 }
595             }
596         }
597
598         if (value == null)
599             compileTimeConstants.remove(key);
600         else
601             compileTimeConstants.put(key, value);
602
603
604     }
605
606     public Object JavaDoc getSharedState(String JavaDoc key) {
607         if ((key == null) || (compileTimeConstants == null))
608             return null;
609
610         return compileTimeConstants.get(key);
611     }
612 }
613
Popular Tags