KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.HashScanResultSet
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.GeneratedMethod;
25
26 import org.apache.derby.iapi.services.monitor.Monitor;
27
28 import org.apache.derby.iapi.services.sanity.SanityManager;
29
30 import org.apache.derby.iapi.services.io.Storable;
31
32 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
33 import org.apache.derby.iapi.services.stream.InfoStreams;
34
35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
36
37 import org.apache.derby.iapi.error.StandardException;
38 import org.apache.derby.iapi.services.i18n.MessageService;
39
40 import org.apache.derby.iapi.reference.SQLState;
41
42 import org.apache.derby.iapi.sql.execute.CursorResultSet;
43 import org.apache.derby.iapi.sql.execute.ExecIndexRow;
44 import org.apache.derby.iapi.sql.execute.ExecRow;
45 import org.apache.derby.iapi.sql.execute.ExecutionContext;
46 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
47
48 import org.apache.derby.iapi.sql.Activation;
49 import org.apache.derby.iapi.sql.ResultSet;
50
51 import org.apache.derby.iapi.store.access.ConglomerateController;
52 import org.apache.derby.iapi.store.access.Qualifier;
53 import org.apache.derby.iapi.store.access.RowUtil;
54 import org.apache.derby.iapi.store.access.ScanController;
55 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
56 import org.apache.derby.iapi.store.access.TransactionController;
57
58 import org.apache.derby.iapi.types.DataValueDescriptor;
59
60 import org.apache.derby.iapi.types.Orderable;
61 import org.apache.derby.iapi.types.RowLocation;
62
63 import org.apache.derby.iapi.store.access.BackingStoreHashtable;
64 import org.apache.derby.iapi.services.io.FormatableBitSet;
65 import org.apache.derby.iapi.services.io.FormatableArrayHolder;
66 import org.apache.derby.iapi.services.io.FormatableIntHolder;
67 import org.apache.derby.iapi.store.access.KeyHasher;
68
69 import java.util.Enumeration JavaDoc;
70 import java.util.Properties JavaDoc;
71 import java.util.Vector JavaDoc;
72
73 /**
74  * Takes a conglomerate and a table filter builds a hash table on the
75  * specified column of the conglomerate on the 1st open. Look up into the
76  * hash table is done on the hash key column. The hash table consists of
77  * either DataValueDescriptor[]s or Vectors of DataValueDescriptor[]. The store builds
78  * the hash table. When a collision occurs, the store builds a Vector with
79  * the colliding DataValueDescriptor[]s.
80  *
81  * @author jerry
82  */

83 public class HashScanResultSet extends NoPutResultSetImpl
84     implements CursorResultSet
85 {
86     private boolean hashtableBuilt;
87     private ExecIndexRow startPosition;
88     private ExecIndexRow stopPosition;
89     protected ExecRow candidate; // candidate row is sparse
90
protected ExecRow compactRow;
91
92     // Variable for managing next() logic on hash entry
93
protected boolean firstNext = true;
94     private int numFetchedOnNext;
95     private int entryVectorSize;
96     private Vector JavaDoc entryVector;
97
98     // set in constructor and not altered during
99
// life of object.
100
private long conglomId;
101     protected StaticCompiledOpenConglomInfo scoci;
102     private GeneratedMethod resultRowAllocator;
103     private GeneratedMethod startKeyGetter;
104     private int startSearchOperator;
105     private GeneratedMethod stopKeyGetter;
106     private int stopSearchOperator;
107     public Qualifier[][] scanQualifiers;
108     public Qualifier[][] nextQualifiers;
109     private int initialCapacity;
110     private float loadFactor;
111     private int maxCapacity;
112     public String JavaDoc tableName;
113     public String JavaDoc userSuppliedOptimizerOverrides;
114     public String JavaDoc indexName;
115     public boolean forUpdate;
116     private boolean runTimeStatisticsOn;
117     private FormatableBitSet accessedCols;
118     public int isolationLevel;
119     public int lockMode;
120     public int[] keyColumns;
121     private boolean sameStartStopPosition;
122     private boolean skipNullKeyColumns;
123
124     protected BackingStoreHashtable hashtable;
125     protected boolean eliminateDuplicates; // set to true in DistinctScanResultSet
126

127     // Run time statistics
128
public Properties JavaDoc scanProperties;
129     public String JavaDoc startPositionString;
130     public String JavaDoc stopPositionString;
131     public int hashtableSize;
132     public boolean isConstraint;
133
134     public static final int DEFAULT_INITIAL_CAPACITY = -1;
135     public static final float DEFAULT_LOADFACTOR = (float) -1.0;
136     public static final int DEFAULT_MAX_CAPACITY = -1;
137
138
139     //
140
// class interface
141
//
142
HashScanResultSet(long conglomId,
143         StaticCompiledOpenConglomInfo scoci, Activation activation,
144         GeneratedMethod resultRowAllocator,
145         int resultSetNumber,
146         GeneratedMethod startKeyGetter, int startSearchOperator,
147         GeneratedMethod stopKeyGetter, int stopSearchOperator,
148         boolean sameStartStopPosition,
149         Qualifier[][] scanQualifiers,
150         Qualifier[][] nextQualifiers,
151         int initialCapacity,
152         float loadFactor,
153         int maxCapacity,
154         int hashKeyItem,
155         String JavaDoc tableName,
156         String JavaDoc userSuppliedOptimizerOverrides,
157         String JavaDoc indexName,
158         boolean isConstraint,
159         boolean forUpdate,
160         int colRefItem,
161         int lockMode,
162         boolean tableLocked,
163         int isolationLevel,
164         boolean skipNullKeyColumns,
165         double optimizerEstimatedRowCount,
166         double optimizerEstimatedCost)
167             throws StandardException
168     {
169         super(activation,
170                 resultSetNumber,
171                 optimizerEstimatedRowCount,
172                 optimizerEstimatedCost);
173         this.scoci = scoci;
174         this.conglomId = conglomId;
175
176         if (SanityManager.DEBUG) {
177             SanityManager.ASSERT( activation!=null, "hash scan must get activation context");
178             SanityManager.ASSERT( resultRowAllocator!= null, "hash scan must get row allocator");
179             if (sameStartStopPosition)
180             {
181                 SanityManager.ASSERT(stopKeyGetter == null,
182                     "stopKeyGetter expected to be null when sameStartStopPosition is true");
183             }
184         }
185
186         this.resultRowAllocator = resultRowAllocator;
187
188         this.startKeyGetter = startKeyGetter;
189         this.startSearchOperator = startSearchOperator;
190         this.stopKeyGetter = stopKeyGetter;
191         this.stopSearchOperator = stopSearchOperator;
192         this.sameStartStopPosition = sameStartStopPosition;
193         this.scanQualifiers = scanQualifiers;
194         this.nextQualifiers = nextQualifiers;
195         this.initialCapacity = initialCapacity;
196         this.loadFactor = loadFactor;
197         this.maxCapacity = maxCapacity;
198         this.tableName = tableName;
199         this.userSuppliedOptimizerOverrides = userSuppliedOptimizerOverrides;
200         this.indexName = indexName;
201         this.isConstraint = isConstraint;
202         this.forUpdate = forUpdate;
203         this.skipNullKeyColumns = skipNullKeyColumns;
204
205         /* Retrieve the hash key columns */
206         FormatableArrayHolder fah = (FormatableArrayHolder)
207                                         (activation.getPreparedStatement().
208                                             getSavedObject(hashKeyItem));
209         FormatableIntHolder[] fihArray = (FormatableIntHolder[]) fah.getArray(FormatableIntHolder.class);
210         keyColumns = new int[fihArray.length];
211         for (int index = 0; index < fihArray.length; index++)
212         {
213             keyColumns[index] = fihArray[index].getInt();
214         }
215
216         // retrieve the valid column list from
217
// the saved objects, if it exists
218
this.accessedCols = null;
219         if (colRefItem != -1)
220         {
221             this.accessedCols = (FormatableBitSet)(activation.getPreparedStatement().
222                                           getSavedObject(colRefItem));
223         }
224         this.lockMode = lockMode;
225
226         /* Isolation level - translate from language to store */
227         // If not specified, get current isolation level
228
if (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL)
229         {
230             isolationLevel = lcc.getCurrentIsolationLevel();
231         }
232
233         if (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)
234         {
235             this.isolationLevel = TransactionController.ISOLATION_SERIALIZABLE;
236         }
237         else
238         {
239             /* NOTE: always do row locking on READ COMMITTED/UNCOMMITTED
240              * and repeatable read scans unless the table is marked as
241              * table locked (in sys.systables).
242              *
243              * We always get instantaneous locks as we will complete
244              * the scan before returning any rows and we will fully
245              * requalify the row if we need to go to the heap on a next().
246              */

247
248             if (! tableLocked)
249             {
250                 this.lockMode = TransactionController.MODE_RECORD;
251             }
252
253             if (isolationLevel ==
254                     ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL)
255             {
256                 this.isolationLevel =
257                     TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK;
258             }
259             else if (isolationLevel ==
260                         ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL)
261             {
262                 this.isolationLevel =
263                     TransactionController.ISOLATION_READ_UNCOMMITTED;
264             }
265             else if (isolationLevel ==
266                         ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL)
267             {
268                 this.isolationLevel =
269                     TransactionController.ISOLATION_REPEATABLE_READ;
270             }
271         }
272
273         if (SanityManager.DEBUG)
274         {
275             SanityManager.ASSERT(
276                 ((isolationLevel ==
277                       ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) ||
278                  (isolationLevel ==
279                       ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) ||
280                  (isolationLevel ==
281                       ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) ||
282                  (isolationLevel ==
283                       ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)),
284
285                 "Invalid isolation level - " + isolationLevel);
286         }
287
288         runTimeStatisticsOn =
289             getLanguageConnectionContext().getRunTimeStatisticsMode();
290
291         /* Only call row allocators once */
292         candidate = (ExecRow) resultRowAllocator.invoke(activation);
293         compactRow =
294                 getCompactRow(candidate, accessedCols, (FormatableBitSet) null, false);
295         constructorTime += getElapsedMillis(beginTime);
296     }
297
298     //
299
// ResultSet interface (leftover from NoPutResultSet)
300
//
301

302     /**
303      * open a scan on the table. scan parameters are evaluated
304      * at each open, so there is probably some way of altering
305      * their values...
306      *
307      * @exception StandardException thrown on failure to open
308      */

309     public void openCore() throws StandardException
310     {
311         TransactionController tc;
312
313         beginTime = getCurrentTimeMillis();
314         if (SanityManager.DEBUG)
315             SanityManager.ASSERT( ! isOpen, "HashScanResultSet already open");
316
317         // Get the current transaction controller
318
tc = activation.getTransactionController();
319
320         if (startKeyGetter != null)
321         {
322             startPosition = (ExecIndexRow) startKeyGetter.invoke(activation);
323             if (sameStartStopPosition)
324             {
325                 stopPosition = startPosition;
326             }
327         }
328         if (stopKeyGetter != null)
329         {
330             stopPosition = (ExecIndexRow) stopKeyGetter.invoke(activation);
331         }
332
333         // Check whether there are any comparisons with unordered nulls
334
// on either the start or stop position. If there are, we can
335
// (and must) skip the scan, because no rows can qualify
336
if (skipScan(startPosition, stopPosition))
337         {
338             // Do nothing
339
;
340         }
341         else if (! hashtableBuilt)
342         {
343             DataValueDescriptor[] startPositionRow =
344                 startPosition == null ? null : startPosition.getRowArray();
345             DataValueDescriptor[] stopPositionRow =
346                 stopPosition == null ? null : stopPosition.getRowArray();
347
348             hashtable =
349                 tc.createBackingStoreHashtableFromScan(
350                     conglomId, // conglomerate to open
351
(forUpdate ? TransactionController.OPENMODE_FORUPDATE : 0),
352                     lockMode,
353                     isolationLevel,
354                     accessedCols,
355                     startPositionRow,
356                     startSearchOperator,
357                     scanQualifiers,
358                     stopPositionRow,
359                     stopSearchOperator,
360                     -1, // no limit on total rows.
361
keyColumns,
362                     eliminateDuplicates,// remove duplicates?
363
-1, // RESOLVE - is there a row estimate?
364
maxCapacity,
365                     initialCapacity, // in memory Hashtable initial capacity
366
loadFactor, // in memory Hashtable load factor
367
runTimeStatisticsOn,
368                     skipNullKeyColumns);
369
370
371             if (runTimeStatisticsOn)
372             {
373                 hashtableSize = hashtable.size();
374
375                 if (scanProperties == null)
376                 {
377                     scanProperties = new Properties JavaDoc();
378                 }
379
380                 try
381                 {
382                     if (hashtable != null)
383                     {
384                         hashtable.getAllRuntimeStats(scanProperties);
385                     }
386                 }
387                 catch(StandardException se)
388                 {
389                     // ignore
390
}
391             }
392
393
394             /* Remember that we created the hash table */
395             hashtableBuilt = true;
396
397             /*
398             ** Tell the activation about the number of qualifying rows.
399             ** Do this only here, not in reopen, because we don't want
400             ** to do this costly operation too often.
401             */

402             activation.informOfRowCount(this, (long) hashtableSize);
403         }
404
405         isOpen = true;
406
407         resetProbeVariables();
408
409         numOpens++;
410         openTime += getElapsedMillis(beginTime);
411     }
412
413     /**
414      * reopen this ResultSet.
415      *
416      * @exception StandardException thrown if cursor finished.
417      */

418     public void reopenCore() throws StandardException {
419         TransactionController tc;
420
421         if (SanityManager.DEBUG)
422         {
423             SanityManager.ASSERT(isOpen,
424                     "HashScanResultSet already open");
425         }
426
427         beginTime = getCurrentTimeMillis();
428
429         resetProbeVariables();
430
431         numOpens++;
432         openTime += getElapsedMillis(beginTime);
433     }
434
435     private void resetProbeVariables() throws StandardException
436     {
437         firstNext = true;
438         numFetchedOnNext = 0;
439         entryVector = null;
440         entryVectorSize = 0;
441
442         if (nextQualifiers != null)
443         {
444             clearOrderableCache(nextQualifiers);
445         }
446     }
447
448
449     /**
450      * Return the next row (if any) from the scan (if open).
451      *
452      * @exception StandardException thrown on failure to get next row
453      */

454     public ExecRow getNextRowCore() throws StandardException
455     {
456         ExecRow result = null;
457         DataValueDescriptor[] columns = null;
458
459         beginTime = getCurrentTimeMillis();
460         if ( isOpen && hashtableBuilt)
461         {
462             /* We use a do/while loop to ensure that we continue down
463              * the duplicate chain, if one exists, until we find a
464              * row that matches on all probe predicates (or the
465              * duplicate chain is exhausted.)
466              */

467             do
468             {
469                 if (firstNext)
470                 {
471                     firstNext = false;
472
473                     /* Hash key could be either a single column or multiple columns.
474                      * If a single column, then it is the datavalue wrapper, otherwise
475                      * it is a KeyHasher.
476                      */

477                     Object JavaDoc hashEntry;
478                     if (keyColumns.length == 1)
479                     {
480                         hashEntry = hashtable.get(nextQualifiers[0][0].getOrderable());
481                     }
482                     else
483                     {
484                         KeyHasher mh = new KeyHasher(keyColumns.length);
485
486                         if (SanityManager.DEBUG)
487                         {
488                             SanityManager.ASSERT(nextQualifiers.length == 1);
489                         }
490
491                         for (int index = 0; index < keyColumns.length; index++)
492                         {
493                             // For hashing only use the AND qualifiers
494
// located in nextQualifiers[0][0...N], OR
495
// qualifiers are checked down a bit by calling
496
// qualifyRow on rows returned from hash.
497

498                             DataValueDescriptor dvd =
499                                 nextQualifiers[0][index].getOrderable();
500
501                             if (dvd == null)
502                             {
503                                 mh = null;
504                                 break;
505                             }
506                             mh.setObject(
507                                 index, nextQualifiers[0][index].getOrderable());
508                         }
509                         hashEntry = (mh == null) ? null : hashtable.get(mh);
510                     }
511
512                     if (hashEntry instanceof Vector JavaDoc)
513                     {
514                         entryVector = (Vector JavaDoc) hashEntry;
515                         entryVectorSize = entryVector.size();
516                         columns =
517                             (DataValueDescriptor[]) entryVector.firstElement();
518                     }
519                     else
520                     {
521                         entryVector = null;
522                         entryVectorSize = 0;
523                         columns = (DataValueDescriptor[]) hashEntry;
524                     }
525                 }
526                 else if (numFetchedOnNext < entryVectorSize)
527                 {
528                     /* We walking a Vector and there's
529                      * more rows left in the vector.
530                      */

531                     columns = (DataValueDescriptor[])
532                         entryVector.elementAt(numFetchedOnNext);
533                 }
534
535                 if (columns != null)
536                 {
537                     if (SanityManager.DEBUG)
538                     {
539                         // There used to be an assertion here that the columns
540
// array was the same size as the number of columns
541
// in the compact row. This assertion no longer holds
542
// now that we're doing sparse rows, so I deleted it.
543

544                         // Columns is really a Storable[]
545
for (int i = 0; i < columns.length; i++)
546                         {
547                             if (columns[i] != null &&
548                                 ! (columns[i] instanceof Storable))
549                             {
550                                 SanityManager.THROWASSERT(
551                                 "columns[" + i + "] expected to be Storable, not " +
552                                 columns[i].getClass().getName());
553                             }
554                         }
555                     }
556
557                     // See if the entry satisfies all of the other qualifiers
558

559                     /* We've already "evaluated" the 1st keyColumns qualifiers
560                      * when we probed into the hash table, but we need to
561                      * evaluate them again here because of the behavior of
562                      * NULLs. NULLs are treated as equal when building and
563                      * probing the hash table so that we only get a single
564                      * entry. However, NULL does not equal NULL, so the
565                      * compare() method below will eliminate any row that
566                      * has a key column containing a NULL.
567                      *
568                      * The following code will also evaluate any OR clauses
569                      * that may exist, while the above hashing does not
570                      * include them.
571                      */

572
573                     if (RowUtil.qualifyRow(columns, nextQualifiers))
574                     {
575                         setCompatRow(compactRow, columns);
576
577                         rowsSeen++;
578
579                         result = compactRow;
580                     }
581                     else
582                     {
583                         result = null;
584                     }
585
586                     numFetchedOnNext++;
587                 }
588                 else
589                 {
590                     result = null;
591                 }
592             }
593             while (result == null && numFetchedOnNext < entryVectorSize);
594
595         }
596
597         currentRow = result;
598         setCurrentRow(result);
599
600         nextTime += getElapsedMillis(beginTime);
601         return result;
602     }
603
604     /**
605      * If the result set has been opened,
606      * close the open scan.
607      *
608      * @exception StandardException thrown on error
609      */

610     public void close() throws StandardException
611     {
612         beginTime = getCurrentTimeMillis();
613         if ( isOpen )
614         {
615             // we don't want to keep around a pointer to the
616
// row ... so it can be thrown away.
617
// REVISIT: does this need to be in a finally
618
// block, to ensure that it is executed?
619
clearCurrentRow();
620
621             if (hashtableBuilt)
622             {
623                 // This is where we get the scan properties for a subquery
624
scanProperties = getScanProperties();
625                 // This is where we get the positioner info for inner tables
626
if (runTimeStatisticsOn)
627                 {
628                     startPositionString = printStartPosition();
629                     stopPositionString = printStopPosition();
630                 }
631
632                 // close the hash table, eating any exception
633
hashtable.close();
634                 hashtable = null;
635                 hashtableBuilt = false;
636             }
637             startPosition = null;
638             stopPosition = null;
639
640             super.close();
641         }
642         else
643             if (SanityManager.DEBUG)
644                 SanityManager.DEBUG("CloseRepeatInfo","Close of HashScanResultSet repeated");
645
646         closeTime += getElapsedMillis(beginTime);
647     }
648
649     /**
650      * Return the total amount of time spent in this ResultSet
651      *
652      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
653      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
654      *
655      * @return long The total amount of time spent (in milliseconds).
656      */

657     public long getTimeSpent(int type)
658     {
659         long totTime = constructorTime + openTime + nextTime + closeTime;
660
661         /* RESOLVE - subtract out store time later, when available */
662         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
663         {
664             return totTime;
665         }
666         else
667         {
668             return totTime;
669         }
670     }
671
672     /**
673      * @see NoPutResultSet#getScanIsolationLevel
674      */

675     public int getScanIsolationLevel()
676     {
677         return isolationLevel;
678     }
679
680     /**
681      * @see NoPutResultSet#requiresRelocking
682      */

683     public boolean requiresRelocking()
684     {
685         // IndexRowToBaseRow needs to relock if we didn't keep the lock
686
return(
687             ((isolationLevel ==
688                  TransactionController.ISOLATION_READ_COMMITTED) ||
689              (isolationLevel ==
690                  TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK) ||
691              (isolationLevel ==
692                  TransactionController.ISOLATION_READ_UNCOMMITTED)));
693
694     }
695
696     //
697
// CursorResultSet interface
698
//
699

700     /**
701      * This result set has its row location from
702      * the last fetch done. If the cursor is closed,
703      * a null is returned.
704      *
705      * @see CursorResultSet
706      *
707      * @return the row location of the current cursor row.
708      * @exception StandardException thrown on failure to get row location
709      */

710     public RowLocation getRowLocation() throws StandardException
711     {
712         if (! isOpen) return null;
713
714         if ( ! hashtableBuilt)
715             return null;
716
717         /* This method should only be called if the last column
718          * in the current row is a RowLocation.
719          */

720         if (SanityManager.DEBUG)
721         {
722             SanityManager.ASSERT(currentRow != null,
723               "There must be a current row when fetching the row location");
724             Object JavaDoc rlCandidate = currentRow.getColumn(
725                                                     currentRow.nColumns());
726             if (! (rlCandidate instanceof RowLocation))
727             {
728                 SanityManager.THROWASSERT(
729                     "rlCandidate expected to be instanceof RowLocation, not " +
730                     rlCandidate.getClass().getName());
731             }
732         }
733
734         return (RowLocation) currentRow.getColumn(
735                                             currentRow.nColumns());
736     }
737
738     /**
739      * This result set has its row from the last fetch done.
740      * If the cursor is closed, a null is returned.
741      *
742      * @see CursorResultSet
743      *
744      * @return the last row returned;
745      * @exception StandardException thrown on failure.
746      */

747     /* RESOLVE - this should return activation.getCurrentRow(resultSetNumber),
748      * once there is such a method. (currentRow is redundant)
749      */

750     public ExecRow getCurrentRow() throws StandardException
751     {
752         /* Doesn't make sense to call this method for this node since
753          * joins are not updatable.
754          */

755         if (SanityManager.DEBUG)
756         {
757             SanityManager.THROWASSERT(
758              "getCurrentRow() not expected to be called for HSRS");
759         }
760
761         return null;
762     }
763
764     public String JavaDoc printStartPosition()
765     {
766         return printPosition(startSearchOperator, startKeyGetter, startPosition);
767     }
768
769     public String JavaDoc printStopPosition()
770     {
771         if (sameStartStopPosition)
772         {
773             return printPosition(stopSearchOperator, startKeyGetter, startPosition);
774         }
775         else
776         {
777             return printPosition(stopSearchOperator, stopKeyGetter, stopPosition);
778         }
779     }
780
781     /**
782      * Return a start or stop positioner as a String.
783      */

784     private String JavaDoc printPosition(int searchOperator,
785                                  GeneratedMethod positionGetter,
786                                  ExecIndexRow eiRow)
787     {
788         String JavaDoc idt = "";
789
790         String JavaDoc output = "";
791         if (positionGetter == null)
792         {
793             return "\t" +
794                     MessageService.getTextMessage(SQLState.LANG_NONE) +
795                     "\n";
796         }
797
798         ExecIndexRow positioner = null;
799
800         try
801         {
802             positioner = (ExecIndexRow) positionGetter.invoke(activation);
803         }
804         catch (StandardException e)
805         {
806
807             if (eiRow == null)
808             {
809                 return "\t" + MessageService.getTextMessage(
810                                             SQLState.LANG_POSITION_NOT_AVAIL);
811             }
812             return "\t" + MessageService.getTextMessage(
813                             SQLState.LANG_UNEXPECTED_EXC_GETTING_POSITIONER) +
814                             "\n";
815         }
816
817         if (positioner == null)
818         {
819             return "\t" +
820                     MessageService.getTextMessage(SQLState.LANG_NONE) +
821                     "\n";
822         }
823
824         String JavaDoc searchOp = null;
825
826         switch (searchOperator)
827         {
828             case ScanController.GE:
829                 searchOp = ">=";
830                 break;
831
832             case ScanController.GT:
833                 searchOp = ">";
834                 break;
835
836             default:
837                 if (SanityManager.DEBUG)
838                 {
839                     SanityManager.THROWASSERT("Unknown search operator " +
840                                                 searchOperator);
841                 }
842
843                 // This is not internationalized because we should never
844
// reach here.
845
searchOp = "unknown value (" + searchOperator + ")";
846                 break;
847         }
848
849         output += "\t" + MessageService.getTextMessage(
850                                         SQLState.LANG_POSITIONER,
851                                         searchOp,
852                                         String.valueOf(positioner.nColumns()))
853                                         + "\n";
854             
855         output += "\t" + MessageService.getTextMessage(
856                                         SQLState.LANG_ORDERED_NULL_SEMANTICS) +
857                                         "\n";
858         for (int position = 0; position < positioner.nColumns(); position++)
859         {
860             if (positioner.areNullsOrdered(position))
861             {
862                 output = output + position + " ";
863             }
864         }
865         
866         return output + "\n";
867     }
868
869     public Properties JavaDoc getScanProperties()
870     {
871         return scanProperties;
872     }
873
874     /**
875      * Is this ResultSet or it's source result set for update
876      *
877      * @return Whether or not the result set is for update.
878      */

879     public boolean isForUpdate()
880     {
881         return forUpdate;
882     }
883 }
884
Popular Tags