KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.BasicNoPutResultSetImpl
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.context.ContextService;
25 import org.apache.derby.iapi.services.monitor.Monitor;
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
28 import org.apache.derby.iapi.services.stream.InfoStreams;
29 import org.apache.derby.iapi.error.StandardException;
30 import org.apache.derby.iapi.services.i18n.MessageService;
31
32 import org.apache.derby.iapi.store.access.TransactionController;
33
34 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
35 import org.apache.derby.iapi.sql.conn.StatementContext;
36
37 import org.apache.derby.iapi.reference.SQLState;
38
39 import org.apache.derby.iapi.sql.execute.ExecRow;
40 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
41 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
42 import org.apache.derby.iapi.sql.Activation;
43
44
45 import org.apache.derby.iapi.sql.ResultDescription;
46 import org.apache.derby.iapi.sql.ResultSet;
47 import org.apache.derby.iapi.sql.Row;
48
49 import org.apache.derby.iapi.types.DataValueDescriptor;
50
51 import org.apache.derby.iapi.services.io.FormatableBitSet;
52
53 import java.sql.Timestamp JavaDoc;
54 import java.sql.SQLWarning JavaDoc;
55
56 /**
57  * Abstract ResultSet for for operations that return rows but
58  * do not allow the caller to put data on output pipes. This
59  * basic implementation does not include support for an Activiation.
60  * See NoPutResultSetImpl.java for an implementaion with support for
61  * an activiation.
62  * <p>
63  * This abstract class does not define the entire ResultSet
64  * interface, but leaves the 'get' half of the interface
65  * for subtypes to implement. It is package-visible only,
66  * with its methods being public for exposure by its subtypes.
67  * <p>
68  */

69 abstract class BasicNoPutResultSetImpl
70 implements NoPutResultSet
71 {
72     /* Modified during the life of this object */
73     protected boolean isOpen;
74     protected boolean finished;
75     protected ExecRow currentRow;
76     protected boolean isTopResultSet;
77     protected LanguageConnectionContext lcc;
78     private SQLWarning JavaDoc warnings;
79
80     /* Run time statistics variables */
81     public int numOpens;
82     public int rowsSeen;
83     public int rowsFiltered;
84     protected long startExecutionTime;
85     protected long endExecutionTime;
86     public long beginTime;
87     public long constructorTime;
88     public long openTime;
89     public long nextTime;
90     public long closeTime;
91
92     public double optimizerEstimatedRowCount;
93     public double optimizerEstimatedCost;
94
95     // set on demand during execution
96
private StatementContext statementContext;
97     public NoPutResultSet[] subqueryTrackingArray;
98     ExecRow compactRow;
99
100     // Set in the constructor and not modified
101
protected Activation activation;
102     private boolean statisticsTimingOn;
103
104     ResultDescription resultDescription;
105
106     private transient ExecutionFactory exFactory;
107     private transient TransactionController tc;
108
109     private int[] baseColumnMap;
110
111     /**
112      * Constructor.
113         <BR>
114         Sets beginTime for all children to use to measue constructor time.
115      *
116      * @param resultDescription the result description. May be null.
117      * @param activation The activation
118      * @param optimizerEstimatedRowCount The optimizer's estimate of the
119      * total number of rows for this
120      * result set
121      * @param optimizerEstimatedCost The optimizer's estimated cost for
122      * this result set
123      */

124     BasicNoPutResultSetImpl(ResultDescription resultDescription,
125                             Activation activation,
126                             double optimizerEstimatedRowCount,
127                             double optimizerEstimatedCost)
128     {
129         this.activation = activation;
130         statisticsTimingOn = (activation != null && getLanguageConnectionContext().getStatisticsTiming());
131         beginTime = startExecutionTime = getCurrentTimeMillis();
132         this.resultDescription = resultDescription;
133         this.optimizerEstimatedRowCount = optimizerEstimatedRowCount;
134         this.optimizerEstimatedCost = optimizerEstimatedCost;
135     }
136     
137     public final Activation getActivation()
138     {
139         return activation;
140     }
141
142     // NoPutResultSet interface
143

144     /**
145      * @see NoPutResultSet#openCore
146      * @exception StandardException thrown if cursor finished.
147      */

148     public abstract void openCore() throws StandardException;
149
150     /**
151      * This is the default implementation of reopenCore().
152      * It simply does a close() followed by an open(). If
153      * there are optimizations to be made (caching, etc), this
154      * is a good place to do it -- this will be overridden
155      * by a number of resultSet imlementations. and SHOULD
156      * be overridden by any node that can get between a base
157      * table and a join.
158      *
159      * @see NoPutResultSet#openCore
160      * @exception StandardException thrown if cursor finished.
161      */

162     public void reopenCore() throws StandardException
163     {
164         close();
165         openCore();
166     }
167
168     /**
169      * @see NoPutResultSet#getNextRowCore
170      * @exception StandardException thrown if cursor finished.
171      */

172     public abstract ExecRow getNextRowCore() throws StandardException;
173
174     /**
175      * @see NoPutResultSet#getPointOfAttachment
176      */

177     public int getPointOfAttachment()
178     {
179         if (SanityManager.DEBUG)
180         {
181             SanityManager.THROWASSERT(
182                 "getPointOfAttachment() not expected to be called for " +
183                 getClass().getName());
184         }
185         return -1;
186     }
187
188     /**
189      * Mark the ResultSet as the topmost one in the ResultSet tree.
190      * Useful for closing down the ResultSet on an error.
191      */

192     public void markAsTopResultSet()
193     {
194         isTopResultSet = true;
195     }
196
197     /**
198      * @see NoPutResultSet#getScanIsolationLevel
199      */

200     public int getScanIsolationLevel()
201     {
202         if (SanityManager.DEBUG)
203         {
204             SanityManager.THROWASSERT(
205                 "getScanIsolationLevel() not expected to be called for " +
206                 getClass().getName());
207         }
208         return 0;
209     }
210
211     /** @see NoPutResultSet#getEstimatedRowCount */
212     public double getEstimatedRowCount()
213     {
214         return optimizerEstimatedRowCount;
215     }
216
217     /**
218      * @see NoPutResultSet#requiresRelocking
219      */

220     public boolean requiresRelocking()
221     {
222         if (SanityManager.DEBUG)
223         {
224             SanityManager.THROWASSERT(
225                 "requiresRelocking() not expected to be called for " +
226                 getClass().getName());
227         }
228         return false;
229     }
230
231     // ResultSet interface
232

233     /**
234      * open a scan on the table. scan parameters are evaluated
235      * at each open, so there is probably some way of altering
236      * their values...
237      *
238      * NOTE: This method should only be called on the top ResultSet
239      * of a ResultSet tree to ensure that the entire ResultSet
240      * tree gets closed down on an error. the openCore() method
241      * will be called for all other ResultSets in the tree.
242      *
243      * @exception StandardException thrown if cursor finished.
244      */

245     public final void open() throws StandardException
246     {
247         if (SanityManager.DEBUG)
248         {
249             if (!isTopResultSet)
250                 SanityManager.THROWASSERT(
251                 this + "expected to be the top ResultSet");
252         }
253
254         finished = false;
255
256         attachStatementContext();
257
258         try {
259
260             openCore();
261
262         } catch (StandardException se) {
263             activation.checkStatementValidity();
264             throw se;
265         }
266
267         activation.checkStatementValidity();
268     }
269
270     /**
271      * Returns the row at the absolute position from the query,
272      * and returns NULL when there is no such position.
273      * (Negative position means from the end of the result set.)
274      * Moving the cursor to an invalid position leaves the cursor
275      * positioned either before the first row (negative position)
276      * or after the last row (positive position).
277      * NOTE: An exception will be thrown on 0.
278      *
279      * @param row The position.
280      * @return The row at the absolute position, or NULL if no such position.
281      *
282      * @exception StandardException Thrown on failure
283      * @see Row
284      */

285     public ExecRow getAbsoluteRow(int row) throws StandardException
286     {
287         if ( ! isOpen )
288         {
289             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, ABSOLUTE);
290         }
291
292         attachStatementContext();
293
294         if (SanityManager.DEBUG)
295         {
296             if (!isTopResultSet)
297             {
298                 SanityManager.THROWASSERT(
299                     this + "expected to be the top ResultSet");
300             }
301
302             SanityManager.THROWASSERT(
303                 "getAbsoluteRow() not expected to be called for " + getClass().getName());
304         }
305
306         return null;
307     }
308
309     /**
310      * Returns the row at the relative position from the current
311      * cursor position, and returns NULL when there is no such position.
312      * (Negative position means toward the beginning of the result set.)
313      * Moving the cursor to an invalid position leaves the cursor
314      * positioned either before the first row (negative position)
315      * or after the last row (positive position).
316      * NOTE: 0 is valid.
317      * NOTE: An exception is thrown if the cursor is not currently
318      * positioned on a row.
319      *
320      * @param row The position.
321      * @return The row at the relative position, or NULL if no such position.
322      *
323      * @exception StandardException Thrown on failure
324      * @see Row
325      */

326     public ExecRow getRelativeRow(int row) throws StandardException
327     {
328         if ( ! isOpen )
329         {
330             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, RELATIVE);
331         }
332
333         attachStatementContext();
334
335         if (SanityManager.DEBUG)
336         {
337             if (!isTopResultSet)
338             {
339                 SanityManager.THROWASSERT(
340                     this + "expected to be the top ResultSet");
341             }
342
343             SanityManager.THROWASSERT(
344                 "getRelativeRow() not expected to be called for " + getClass().getName());
345         }
346
347         return null;
348     }
349
350     /**
351      * Sets the current position to before the first row and returns NULL
352      * because there is no current row.
353      *
354      * @return NULL.
355      *
356      * @exception StandardException Thrown on failure
357      * @see Row
358      */

359     public ExecRow setBeforeFirstRow()
360         throws StandardException
361     {
362         if ( ! isOpen )
363         {
364             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, FIRST);
365         }
366
367         if (SanityManager.DEBUG)
368         {
369             if (!isTopResultSet)
370             {
371                 SanityManager.THROWASSERT(
372                     this + "expected to be the top ResultSet");
373             }
374
375             SanityManager.THROWASSERT(
376                 "setBeforeFirstRow() not expected to be called for " + getClass().getName());
377         }
378
379         return null;
380     }
381
382     /**
383      * Determine if the cursor is before the first row in the result
384      * set.
385      *
386      * @return true if before the first row, false otherwise. Returns
387      * false when the result set contains no rows.
388      */

389     public boolean checkRowPosition(int isType) throws StandardException
390     {
391         return false;
392     }
393
394     /**
395      * Returns the row number of the current row. Row
396      * numbers start from 1 and go to 'n'. Corresponds
397      * to row numbering used to position current row
398      * in the result set (as per JDBC).
399      *
400      * @return the row number, or 0 if not on a row
401      *
402      */

403     public int getRowNumber()
404     {
405         return 0;
406     }
407
408     /**
409      * Returns the first row from the query, and returns NULL when there
410      * are no rows.
411      *
412      * @return The first row, or NULL if no rows.
413      *
414      * @exception StandardException Thrown on failure
415      * @see Row
416      */

417     public ExecRow getFirstRow()
418         throws StandardException
419     {
420         if ( ! isOpen )
421         {
422             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, FIRST);
423         }
424
425         attachStatementContext();
426
427         if (SanityManager.DEBUG)
428         {
429             if (!isTopResultSet)
430             {
431                 SanityManager.THROWASSERT(
432                     this + "expected to be the top ResultSet");
433             }
434
435             SanityManager.THROWASSERT(
436                 "getFirstRow() not expected to be called for " + getClass().getName());
437         }
438
439         return null;
440     }
441
442     /**
443      * Return the requested values computed
444      * from the next row (if any) for which
445      * the restriction evaluates to true.
446      * <p>
447      * restriction and projection parameters
448      * are evaluated for each row.
449      *
450      * NOTE: This method should only be called on the top ResultSet
451      * of a ResultSet tree to ensure that the entire ResultSet
452      * tree gets closed down on an error. the getNextRowCore() method
453      * will be called for all other ResultSets in the tree.
454      *
455      * @exception StandardException thrown on failure.
456      * @exception StandardException ResultSetNotOpen thrown if not yet open.
457      *
458      * @return the next row in the result
459      */

460     public final ExecRow getNextRow() throws StandardException
461     {
462         if ( ! isOpen ) {
463             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, NEXT);
464         }
465
466         if (SanityManager.DEBUG)
467         {
468             if (!isTopResultSet)
469                 SanityManager.THROWASSERT(
470                 this + "expected to be the top ResultSet");
471         }
472
473         attachStatementContext();
474
475         return getNextRowCore();
476     }
477
478     /**
479      * Returns the previous row from the query, and returns NULL when there
480      * are no more previous rows.
481      *
482      * @return The previous row, or NULL if no more previous rows.
483      *
484      * @exception StandardException Thrown on failure
485      * @see Row
486      */

487     public ExecRow getPreviousRow()
488         throws StandardException
489     {
490         if ( ! isOpen )
491         {
492             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, PREVIOUS);
493         }
494
495         attachStatementContext();
496
497         if (SanityManager.DEBUG)
498         {
499             if (!isTopResultSet)
500             {
501                 SanityManager.THROWASSERT(
502                     this + "expected to be the top ResultSet");
503             }
504
505             SanityManager.THROWASSERT(
506                 "getPreviousRow() not expected to be called.");
507         }
508
509         return null;
510     }
511
512     /**
513      * Returns the last row from the query, and returns NULL when there
514      * are no rows.
515      *
516      * @return The last row, or NULL if no rows.
517      *
518      * @exception StandardException Thrown on failure
519      * @see Row
520      */

521     public ExecRow getLastRow()
522         throws StandardException
523     {
524         if ( ! isOpen )
525         {
526             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, LAST);
527         }
528
529         attachStatementContext();
530
531         if (SanityManager.DEBUG)
532         {
533             if (!isTopResultSet)
534             {
535                 SanityManager.THROWASSERT(
536                     this + "expected to be the top ResultSet");
537             }
538
539             SanityManager.THROWASSERT(
540                 "getLastRow() not expected to be called.");
541         }
542
543         return null;
544     }
545
546     /**
547      * Sets the current position to after the last row and returns NULL
548      * because there is no current row.
549      *
550      * @return NULL.
551      *
552      * @exception StandardException Thrown on failure
553      * @see Row
554      */

555     public ExecRow setAfterLastRow()
556         throws StandardException
557     {
558         if ( ! isOpen )
559         {
560             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, LAST);
561         }
562
563         if (SanityManager.DEBUG)
564         {
565             if (!isTopResultSet)
566             {
567                 SanityManager.THROWASSERT(
568                     this + "expected to be the top ResultSet");
569             }
570
571             SanityManager.THROWASSERT(
572                 "setAfterLastRow() not expected to be called.");
573         }
574
575         return null;
576     }
577
578
579     /**
580      * Returns true.
581      */

582      public boolean returnsRows() { return true; }
583
584     public final int modifiedRowCount() { return 0; }
585
586     /**
587      * Clean up on error
588      * @exception StandardException Thrown on failure
589      *
590      */

591     public void cleanUp() throws StandardException
592     {
593         if (isOpen) {
594             close();
595         }
596     }
597
598     /**
599         Report if closed.
600      */

601     public boolean isClosed() {
602         return ( ! isOpen );
603     }
604
605     public void finish() throws StandardException
606     {
607         finishAndRTS();
608     }
609
610     /**
611      * @exception StandardException on error
612      */

613     protected final void finishAndRTS() throws StandardException
614     {
615
616         if (!finished) {
617             /*
618             ** If run time statistics tracing is turned on, then now is the
619             ** time to dump out the information.
620             */

621             if (isTopResultSet) {
622
623                 LanguageConnectionContext lcc = getLanguageConnectionContext();
624                 if (lcc.getRunTimeStatisticsMode())
625                 {
626                     endExecutionTime = getCurrentTimeMillis();
627
628                     lcc.setRunTimeStatisticsObject(
629                         lcc.getExecutionContext().getResultSetStatisticsFactory().getRunTimeStatistics(activation, this, subqueryTrackingArray));
630
631                     HeaderPrintWriter istream = lcc.getLogQueryPlan() ? Monitor.getStream() : null;
632                     if (istream != null)
633                     {
634                         istream.printlnWithHeader(LanguageConnectionContext.xidStr +
635                                                   lcc.getTransactionExecute().getTransactionIdString() +
636                                                   "), " +
637                                                   LanguageConnectionContext.lccStr +
638                                                   lcc.getInstanceNumber() +
639                                                   "), " +
640                                                   lcc.getRunTimeStatisticsObject().getStatementText() + " ******* " +
641                                                   lcc.getRunTimeStatisticsObject().getStatementExecutionPlanText());
642                     }
643                 }
644
645             }
646
647             if (!isClosed())
648                 close();
649
650             finished = true;
651
652             if (isTopResultSet && activation.isSingleExecution())
653                 activation.close();
654         }
655     }
656
657     /* The following methods are common to almost all sub-classes.
658      * They are overriden in selected cases.
659      */

660
661     /**
662      * Returns the description of the table's rows
663      */

664     public ResultDescription getResultDescription() {
665         return resultDescription;
666     }
667
668     /**
669      * Get the execution time in milliseconds.
670      *
671      * @return long The execution time in milliseconds.
672      */

673     public long getExecuteTime()
674     {
675         return getTimeSpent(ResultSet.ENTIRE_RESULTSET_TREE);
676     }
677
678     /**
679      * Get the Timestamp for the beginning of execution.
680      *
681      * @return Timestamp The Timestamp for the beginning of execution.
682      */

683     public Timestamp JavaDoc getBeginExecutionTimestamp()
684     {
685         if (startExecutionTime == 0)
686         {
687             return null;
688         }
689         else
690         {
691             return new Timestamp JavaDoc(startExecutionTime);
692         }
693     }
694
695     /**
696      * Get the Timestamp for the end of execution.
697      *
698      * @return Timestamp The Timestamp for the end of execution.
699      */

700     public Timestamp JavaDoc getEndExecutionTimestamp()
701     {
702         if (endExecutionTime == 0)
703         {
704             return null;
705         }
706         else
707         {
708             return new Timestamp JavaDoc(endExecutionTime);
709         }
710     }
711
712     /**
713      * @see ResultSet#getSubqueryTrackingArray
714      */

715     public final NoPutResultSet[] getSubqueryTrackingArray(int numSubqueries)
716     {
717         if (subqueryTrackingArray == null)
718         {
719             subqueryTrackingArray = new NoPutResultSet[numSubqueries];
720         }
721
722         return subqueryTrackingArray;
723     }
724
725     /**
726      * Return the current time in milliseconds, if DEBUG and RunTimeStats is
727      * on, else return 0. (Only pay price of system call if need to.)
728      *
729      * @return long Current time in milliseconds.
730      */

731     protected final long getCurrentTimeMillis()
732     {
733         if (statisticsTimingOn)
734         {
735             return System.currentTimeMillis();
736         }
737         else
738         {
739             return 0;
740         }
741     }
742
743     /**
744      * @see ResultSet#getAutoGeneratedKeysResultset
745      */

746     public ResultSet getAutoGeneratedKeysResultset()
747     {
748         //A non-null resultset would be returned only for an insert statement
749
return (ResultSet)null;
750     }
751
752     /**
753      * Return the elapsed time in milliseconds, between now and the beginTime, if
754      * DEBUG and RunTimeStats is on, else return 0.
755      * (Only pay price of system call if need to.)
756      *
757      * @return long Elapsed time in milliseconds.
758      */

759
760     protected final long getElapsedMillis(long beginTime)
761     {
762         if (statisticsTimingOn)
763         {
764             return (System.currentTimeMillis() - beginTime);
765         }
766         else
767         {
768             return 0;
769         }
770     }
771
772     /**
773      * Dump out the time information for run time stats.
774      *
775      * @return Nothing.
776      */

777     protected final String JavaDoc dumpTimeStats(String JavaDoc indent, String JavaDoc subIndent)
778     {
779         return
780             indent +
781               MessageService.getTextMessage(SQLState.LANG_TIME_SPENT_THIS) +
782               " " + getTimeSpent(ResultSet.CURRENT_RESULTSET_ONLY) + "\n" +
783             indent +
784               MessageService.getTextMessage(
785                 SQLState.LANG_TIME_SPENT_THIS_AND_BELOW) +
786               " " + getTimeSpent(NoPutResultSet.ENTIRE_RESULTSET_TREE) + "\n" +
787             indent +
788               MessageService.getTextMessage(
789                 SQLState.LANG_TOTAL_TIME_BREAKDOWN) + "\n" +
790             subIndent +
791               MessageService.getTextMessage(SQLState.LANG_CONSTRUCTOR_TIME) +
792               " " + constructorTime + "\n" +
793             subIndent +
794               MessageService.getTextMessage(SQLState.LANG_OPEN_TIME) +
795               " " + openTime + "\n" +
796             subIndent +
797               MessageService.getTextMessage(SQLState.LANG_NEXT_TIME) +
798               " " + nextTime + "\n" +
799             subIndent +
800               MessageService.getTextMessage(SQLState.LANG_CLOSE_TIME) +
801               " " + closeTime;
802     }
803
804
805     /**
806       * Attach this result set to the top statement context on the stack.
807       * Result sets can be directly read from the JDBC layer. The JDBC layer
808       * will push and pop a statement context around each ResultSet.getNext().
809       * There's no guarantee that the statement context used for the last
810       * getNext() will be the context used for the current getNext(). The
811       * last statement context may have been popped off the stack and so
812       * will not be available for cleanup if an error occurs. To make sure
813       * that we will be cleaned up, we always attach ourselves to the top
814       * context.
815       *
816       * The fun and games occur in nested contexts: using JDBC result sets inside
817       * user code that is itself invoked from queries or CALL statements.
818       *
819       *
820       * @exception StandardException thrown if cursor finished.
821       */

822     protected void attachStatementContext() throws StandardException
823     {
824         if (isTopResultSet)
825         {
826             if (statementContext == null || !statementContext.onStack() )
827             {
828                 statementContext = getLanguageConnectionContext().getStatementContext();
829             }
830             statementContext.setTopResultSet(this, subqueryTrackingArray);
831             // Pick up any materialized subqueries
832
if (subqueryTrackingArray == null)
833             {
834                 subqueryTrackingArray = statementContext.getSubqueryTrackingArray();
835             }
836         }
837
838     }
839
840     /**
841       * Cache the language connection context. Return it.
842       *
843       * @return the language connection context
844       */

845     protected final LanguageConnectionContext getLanguageConnectionContext()
846     {
847         if ( lcc == null )
848         {
849             /* We don't always have an activation. Get the LCC
850              * from the activation when we have one.
851              */

852             if (activation != null)
853             {
854                 lcc = activation.getLanguageConnectionContext();
855             }
856             else
857             {
858                 lcc = (LanguageConnectionContext) ContextService.getContext(LanguageConnectionContext.CONTEXT_ID);
859             }
860         }
861
862         return lcc;
863     }
864
865     /** @see NoPutResultSet#resultSetNumber() */
866     public int resultSetNumber() {
867         if (SanityManager.DEBUG) {
868             SanityManager.THROWASSERT(
869                 "resultSetNumber() should not be called on a " +
870                 this.getClass().getName()
871                 );
872         }
873
874         return 0;
875     }
876
877     //////////////////////////////////////////////////////
878
//
879
// UTILS
880
//
881
//////////////////////////////////////////////////////
882

883     /**
884      * Get a execution factory
885      *
886      * @return the execution factory
887      */

888     final ExecutionFactory getExecutionFactory()
889     {
890         if (exFactory == null) {
891             exFactory = activation.getExecutionFactory();
892         }
893         if (SanityManager.DEBUG)
894             SanityManager.ASSERT(exFactory!=null,"unable to get execution factory");
895         return exFactory;
896     }
897
898     /**
899      * Get the current transaction controller.
900      *
901      */

902     final TransactionController getTransactionController()
903     {
904         if (tc == null)
905         {
906             tc = getLanguageConnectionContext().getTransactionExecute();
907         }
908         return tc;
909     }
910
911     /**
912      * Get a compacted version of the candidate row according to the
913      * columns specified in the bit map. Share the holders between rows.
914      * If there is no bit map, use the candidate row as the compact row.
915      *
916      * Also, create an array of ints mapping base column positions to
917      * compact column positions, to make it cheaper to copy columns to
918      * the compact row, if we ever have to do it again.
919      *
920      * @param candidate The row to get the columns from
921      * @param accessedCols A bit map of the columns that are accessed in
922      * the candidate row
923      * @param otherCols An bit map of other column ids - this is used
924      * in case columns from an index row will be
925      * copied into a heap row - in this case, we
926      * need to be sure there are enough columns in
927      * the compact row. This parameter is null if
928      * columns will not be copied from an index row
929      * to a compact heap row. The column numbers in
930      * the bit map are zero-based.
931      * @param isKeyed Tells whether to return a ValueRow or an IndexRow
932      *
933      * @return A compact row.
934      */

935     protected ExecRow getCompactRow(ExecRow candidate,
936                                     FormatableBitSet accessedCols,
937                                     FormatableBitSet otherCols,
938                                     boolean isKeyed)
939                                     throws StandardException
940     {
941         int numCandidateCols = candidate.nColumns();
942
943         if (accessedCols == null)
944         {
945             compactRow = candidate;
946             baseColumnMap = new int[numCandidateCols];
947             for (int i = 0; i < baseColumnMap.length; i++)
948                 baseColumnMap[i] = i;
949         }
950         else
951         {
952             FormatableBitSet allCols;
953
954             if (otherCols == null)
955             {
956                 allCols = accessedCols;
957             }
958             else
959             {
960                 allCols = new FormatableBitSet(accessedCols);
961                 allCols.or(otherCols);
962             }
963
964             int numCols = allCols.getNumBitsSet();
965             baseColumnMap = new int[numCols];
966
967             if (compactRow == null)
968             {
969                 ExecutionFactory ex = lcc.getExecutionContext().getExecutionFactory();
970
971                 if (isKeyed)
972                 {
973                     compactRow = ex.getIndexableRow(numCols);
974                 }
975                 else
976                 {
977                     compactRow = ex.getValueRow(numCols);
978                 }
979             }
980
981             int position = 0;
982             for (int i = allCols.anySetBit();
983                     i != -1;
984                     i = allCols.anySetBit(i))
985             {
986                 // Stop looking if there are columns beyond the columns
987
// in the candidate row. This can happen due to the
988
// otherCols bit map.
989
if (i >= numCandidateCols)
990                     break;
991
992                 DataValueDescriptor sc = candidate.getColumn(i+1);
993                 if (sc != null)
994                 {
995                     compactRow.setColumn(
996                                     position + 1,
997                                     sc
998                                     );
999                 }
1000                baseColumnMap[position] = i;
1001                position++;
1002            }
1003        }
1004
1005        return compactRow;
1006    }
1007
1008    /**
1009     * Copy columns from the candidate row from the store to the given
1010     * compact row. If there is no column map, just use the candidate row.
1011     *
1012     * This method assumes the above method (getCompactRow()) was called
1013     * first. getCompactRow() sets up the baseColumnMap.
1014     *
1015     * @param candidateRow The candidate row from the store
1016     * @param compactRow The compact row to fill in
1017     *
1018     * @return The compact row to use
1019     */

1020    protected ExecRow setCompactRow(ExecRow candidateRow, ExecRow compactRow)
1021    {
1022        ExecRow retval;
1023
1024        //System.out.println("base col map " + baseColumnMap);
1025
if (baseColumnMap == null)
1026        {
1027            retval = candidateRow;
1028        }
1029        else
1030        {
1031            retval = compactRow;
1032
1033            setCompatRow(compactRow, candidateRow.getRowArray());
1034        }
1035
1036        return retval;
1037    }
1038
1039
1040    protected final void setCompatRow(ExecRow compactRow, Object JavaDoc[] sourceRow) {
1041
1042        Object JavaDoc[] destRow = compactRow.getRowArray();
1043        int[] lbcm = baseColumnMap;
1044
1045        for (int i = 0; i < lbcm.length; i++)
1046        {
1047
1048            destRow[i] = sourceRow[lbcm[i]];
1049
1050        }
1051    }
1052
1053    /**
1054     * Is this ResultSet or it's source result set for update
1055     * This method will be overriden in the inherited Classes
1056     * if it is true
1057     * @return Whether or not the result set is for update.
1058     */

1059    public boolean isForUpdate()
1060    {
1061        return false;
1062    }
1063
1064    /**
1065     * Checks whether the currently executing statement has been cancelled.
1066     * This is done by checking the statement's allocated StatementContext
1067     * object.
1068     *
1069     * @see StatementContext
1070     */

1071    public void checkCancellationFlag()
1072        throws
1073            StandardException
1074    {
1075        StatementContext localStatementContext = getLanguageConnectionContext().getStatementContext();
1076        if (localStatementContext == null) {
1077            return;
1078        }
1079
1080        if (localStatementContext.isCancelled()) {
1081            throw StandardException.newException(SQLState.LANG_STATEMENT_CANCELLED_OR_TIMED_OUT);
1082        }
1083    }
1084
1085    protected final void addWarning(SQLWarning JavaDoc w) {
1086
1087        if (isTopResultSet) {
1088            if (warnings == null)
1089                warnings = w;
1090            else
1091                warnings.setNextWarning(w);
1092            return;
1093        }
1094
1095        if (activation != null) {
1096
1097            ResultSet rs = activation.getResultSet();
1098            if (rs instanceof BasicNoPutResultSetImpl) {
1099                ((BasicNoPutResultSetImpl) rs).addWarning(w);
1100            }
1101
1102        }
1103    }
1104
1105    public final SQLWarning JavaDoc getWarnings() {
1106        SQLWarning JavaDoc w = warnings;
1107        warnings = null;
1108        return w;
1109    }
1110}
1111
Popular Tags