Source Code Cross Referenced for TableScanResultSet.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » sql » execute » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.sql.execute 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.sql.execute.TableScanResultSet
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.sql.execute;
0023:
0024:        import org.apache.derby.iapi.sql.execute.CursorResultSet;
0025:        import org.apache.derby.iapi.error.StandardException;
0026:        import org.apache.derby.iapi.services.i18n.MessageService;
0027:
0028:        import org.apache.derby.iapi.sql.Activation;
0029:        import org.apache.derby.iapi.sql.ResultSet;
0030:        import org.apache.derby.iapi.sql.execute.ExecRow;
0031:        import org.apache.derby.iapi.sql.execute.ExecIndexRow;
0032:        import org.apache.derby.iapi.sql.execute.ExecutionContext;
0033:        import org.apache.derby.iapi.sql.execute.NoPutResultSet;
0034:        import org.apache.derby.iapi.sql.execute.TemporaryRowHolder;
0035:
0036:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
0037:
0038:        import org.apache.derby.iapi.store.access.ConglomerateController;
0039:        import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
0040:        import org.apache.derby.iapi.store.access.Qualifier;
0041:        import org.apache.derby.iapi.store.access.ScanController;
0042:        import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
0043:        import org.apache.derby.iapi.store.access.TransactionController;
0044:
0045:        import org.apache.derby.iapi.types.DataValueDescriptor;
0046:
0047:        import org.apache.derby.iapi.types.Orderable;
0048:        import org.apache.derby.iapi.types.RowLocation;
0049:
0050:        import org.apache.derby.iapi.services.sanity.SanityManager;
0051:
0052:        import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
0053:        import org.apache.derby.iapi.services.stream.InfoStreams;
0054:
0055:        import org.apache.derby.iapi.services.monitor.Monitor;
0056:
0057:        import org.apache.derby.iapi.services.loader.GeneratedMethod;
0058:        import org.apache.derby.iapi.services.io.FormatableBitSet;
0059:
0060:        import org.apache.derby.iapi.reference.SQLState;
0061:
0062:        import java.util.Properties;
0063:        import java.util.Hashtable;
0064:
0065:        /**
0066:         * Takes a table and a table filter and returns
0067:         * the table's rows satisfying the filter as a result set.
0068:         *
0069:         * There are several things we could do during object
0070:         * construction that are done in the open & next calls, to
0071:         * improve performance.
0072:         *
0073:         * @author ames
0074:         */
0075:        class TableScanResultSet extends NoPutResultSetImpl implements 
0076:                CursorResultSet, Cloneable {
0077:            protected ScanController scanController;
0078:            protected boolean scanControllerOpened;
0079:            protected boolean isKeyed;
0080:            protected boolean firstScan = true;
0081:            protected ExecIndexRow startPosition;
0082:            protected ExecIndexRow stopPosition;
0083:            protected ExecRow candidate;
0084:
0085:            // set in constructor and not altered during
0086:            // life of object.
0087:            protected long conglomId;
0088:            protected DynamicCompiledOpenConglomInfo dcoci;
0089:            protected StaticCompiledOpenConglomInfo scoci;
0090:            protected GeneratedMethod resultRowAllocator;
0091:            protected GeneratedMethod startKeyGetter;
0092:            protected int startSearchOperator;
0093:            protected GeneratedMethod stopKeyGetter;
0094:            protected int stopSearchOperator;
0095:            public Qualifier[][] qualifiers;
0096:            public String tableName;
0097:            public String userSuppliedOptimizerOverrides;
0098:            public String indexName;
0099:            protected boolean runTimeStatisticsOn;
0100:            protected FormatableBitSet accessedCols;
0101:            protected int[] indexCols; //index keys base column position array
0102:            public int rowsPerRead;
0103:            public boolean forUpdate;
0104:            private boolean sameStartStopPosition;
0105:            private boolean nextDone;
0106:            private RowLocation rlTemplate;
0107:
0108:            public int isolationLevel;
0109:            public int lockMode;
0110:
0111:            // Run time statistics
0112:            private Properties scanProperties;
0113:            public String startPositionString;
0114:            public String stopPositionString;
0115:            public boolean isConstraint;
0116:            public boolean coarserLock;
0117:            public boolean oneRowScan;
0118:
0119:            protected long rowsThisScan;
0120:
0121:            private long estimatedRowCount;
0122:
0123:            /* Following fields are used by beetle 3865, updateable cursor using index. "past2FutureTbl"
0124:             * is a hash table containing updated rows that are thrown into future direction of the
0125:             * index scan and as a result we'll hit it again but should skip it.  If this hash table
0126:             * is full, we scan forward and have a virtual memory style temp heap holding future row
0127:             * id's.
0128:             */
0129:            protected Hashtable past2FutureTbl;
0130:            protected TemporaryRowHolder futureForUpdateRows; //tmp table for materialized rids
0131:            protected TemporaryRowHolderResultSet futureRowResultSet; //result set for reading from above
0132:            protected boolean skipFutureRowHolder; //skip reading rows from above
0133:            protected boolean sourceDrained; //all row ids materialized
0134:            protected boolean currentRowPrescanned; //got a row from above tmp table
0135:            protected boolean compareToLastKey; //see comments in UpdateResultSet
0136:            protected ExecRow lastCursorKey;
0137:            private ExecRow sparseRow; //sparse row in heap column order
0138:            private FormatableBitSet sparseRowMap; //which columns to read
0139:
0140:            // For Scrollable insensitive updatable result sets, only qualify a row the 
0141:            // first time it's been read, since an update can change a row so that it 
0142:            // no longer qualifies
0143:            private boolean qualify;
0144:
0145:            // currentRowIsValid is set to the result of positioning at a rowLocation.
0146:            // It will be true if the positioning was successful and false if the row 
0147:            // was deleted under our feet. Whenenver currentRowIsValid is false it means 
0148:            // that the row has been deleted.
0149:            private boolean currentRowIsValid;
0150:
0151:            // Indicates whether the scan has been positioned back to a previously read
0152:            // row, or it is accessing a row for the first time.
0153:            private boolean scanRepositioned;
0154:
0155:            //
0156:            // class interface
0157:            //
0158:            TableScanResultSet(long conglomId,
0159:                    StaticCompiledOpenConglomInfo scoci, Activation activation,
0160:                    GeneratedMethod resultRowAllocator, int resultSetNumber,
0161:                    GeneratedMethod startKeyGetter, int startSearchOperator,
0162:                    GeneratedMethod stopKeyGetter, int stopSearchOperator,
0163:                    boolean sameStartStopPosition, Qualifier[][] qualifiers,
0164:                    String tableName, String userSuppliedOptimizerOverrides,
0165:                    String indexName, boolean isConstraint, boolean forUpdate,
0166:                    int colRefItem, int indexColItem, int lockMode,
0167:                    boolean tableLocked, int isolationLevel, int rowsPerRead,
0168:                    boolean oneRowScan, double optimizerEstimatedRowCount,
0169:                    double optimizerEstimatedCost) throws StandardException {
0170:                super (activation, resultSetNumber, optimizerEstimatedRowCount,
0171:                        optimizerEstimatedCost);
0172:
0173:                this .conglomId = conglomId;
0174:
0175:                /* Static info created at compile time and can be shared across
0176:                 * instances of the plan.
0177:                 * Dynamic info created on 1st opening of this ResultSet as
0178:                 * it cannot be shared.
0179:                 */
0180:                this .scoci = scoci;
0181:
0182:                if (SanityManager.DEBUG) {
0183:                    SanityManager.ASSERT(activation != null,
0184:                            "table scan must get activation context");
0185:                    SanityManager.ASSERT(resultRowAllocator != null,
0186:                            "table scan must get row allocator");
0187:                    if (sameStartStopPosition) {
0188:                        SanityManager
0189:                                .ASSERT(stopKeyGetter == null,
0190:                                        "stopKeyGetter expected to be null when sameStartStopPosition is true");
0191:                    }
0192:                }
0193:
0194:                this .resultRowAllocator = resultRowAllocator;
0195:
0196:                this .startKeyGetter = startKeyGetter;
0197:                this .startSearchOperator = startSearchOperator;
0198:                this .stopKeyGetter = stopKeyGetter;
0199:                this .stopSearchOperator = stopSearchOperator;
0200:                this .sameStartStopPosition = sameStartStopPosition;
0201:                this .qualifiers = qualifiers;
0202:                this .tableName = tableName;
0203:                this .userSuppliedOptimizerOverrides = userSuppliedOptimizerOverrides;
0204:                this .indexName = indexName;
0205:                this .isConstraint = isConstraint;
0206:                this .forUpdate = forUpdate;
0207:                this .rowsPerRead = rowsPerRead;
0208:                this .oneRowScan = oneRowScan;
0209:
0210:                // retrieve the valid column list from
0211:                // the saved objects, if it exists
0212:                this .accessedCols = null;
0213:                if (colRefItem != -1) {
0214:                    this .accessedCols = (FormatableBitSet) (activation
0215:                            .getPreparedStatement().getSavedObject(colRefItem));
0216:                }
0217:                if (indexColItem != -1) {
0218:                    this .indexCols = (int[]) (activation.getPreparedStatement()
0219:                            .getSavedObject(indexColItem));
0220:                }
0221:                if (indexCols != null)
0222:                    activation.setForUpdateIndexScan(this );
0223:
0224:                this .lockMode = lockMode;
0225:
0226:                /* Isolation level - translate from language to store */
0227:                // If not specified, get current isolation level
0228:                if (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL) {
0229:                    isolationLevel = lcc.getCurrentIsolationLevel();
0230:                }
0231:
0232:                if (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL) {
0233:                    this .isolationLevel = TransactionController.ISOLATION_SERIALIZABLE;
0234:                } else {
0235:                    /* NOTE: always do row locking on READ COMMITTED/UNCOMITTED scans,
0236:                     * unless the table is marked as table locked (in sys.systables)
0237:                     * This is to improve concurrency.  Also see FromBaseTable's
0238:                     * updateTargetLockMode (KEEP THESE TWO PLACES CONSISTENT!
0239:                     * bug 4318).
0240:                     */
0241:
0242:                    /* NOTE: always do row locking on READ COMMITTED/UNCOMMITTED 
0243:                     *       and repeatable read scans unless the table is marked as 
0244:                     *       table locked (in sys.systables).
0245:                     *
0246:                     *		 We always get instantaneous locks as we will complete
0247:                     *		 the scan before returning any rows and we will fully
0248:                     *		 requalify the row if we need to go to the heap on a next().
0249:                     */
0250:
0251:                    if (!tableLocked) {
0252:                        this .lockMode = TransactionController.MODE_RECORD;
0253:                    }
0254:
0255:                    if (isolationLevel == ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) {
0256:                        /* 
0257:                         * Now we see if we can get instantaneous locks
0258:                         * if we are getting share locks.
0259:                         * (For example, we can get instantaneous locks
0260:                         * when doing a bulk fetch.)
0261:                         */
0262:                        if ((!forUpdate) && canGetInstantaneousLocks()) {
0263:                            this .isolationLevel = TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK;
0264:                        } else {
0265:                            this .isolationLevel = TransactionController.ISOLATION_READ_COMMITTED;
0266:                        }
0267:                    } else if (isolationLevel == ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) {
0268:                        this .isolationLevel = TransactionController.ISOLATION_READ_UNCOMMITTED;
0269:                    } else if (isolationLevel == ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) {
0270:                        this .isolationLevel = TransactionController.ISOLATION_REPEATABLE_READ;
0271:                    }
0272:                }
0273:
0274:                if (SanityManager.DEBUG) {
0275:                    SanityManager
0276:                            .ASSERT(
0277:                                    ((isolationLevel == ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL)
0278:                                            || (isolationLevel == ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL)
0279:                                            || (isolationLevel == ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) || (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)),
0280:
0281:                                    "Invalid isolation level - "
0282:                                            + isolationLevel);
0283:                }
0284:
0285:                runTimeStatisticsOn = (activation != null && activation
0286:                        .getLanguageConnectionContext()
0287:                        .getRunTimeStatisticsMode());
0288:
0289:                /* Only call row allocators once */
0290:                candidate = (ExecRow) resultRowAllocator.invoke(activation);
0291:                constructorTime += getElapsedMillis(beginTime);
0292:
0293:                /* Always qualify the first time a row is being read */
0294:                qualify = true;
0295:                currentRowIsValid = false;
0296:                scanRepositioned = false;
0297:            }
0298:
0299:            //
0300:            // ResultSet interface (leftover from NoPutResultSet)
0301:            //
0302:
0303:            /**
0304:             * open a scan on the table. scan parameters are evaluated
0305:             * at each open, so there is probably some way of altering
0306:             * their values...
0307:             *
0308:             * @exception StandardException thrown on failure to open
0309:             */
0310:            public void openCore() throws StandardException {
0311:                if (SanityManager.DEBUG)
0312:                    SanityManager.ASSERT(!isOpen,
0313:                            "TableScanResultSet already open");
0314:
0315:                // Get the current transaction controller
0316:                TransactionController tc = activation
0317:                        .getTransactionController();
0318:
0319:                if (dcoci == null)
0320:                    dcoci = tc.getDynamicCompiledConglomInfo(conglomId);
0321:
0322:                if (startKeyGetter != null) {
0323:                    startPosition = (ExecIndexRow) startKeyGetter
0324:                            .invoke(activation);
0325:                    if (sameStartStopPosition) {
0326:                        stopPosition = startPosition;
0327:                    }
0328:                }
0329:                if (stopKeyGetter != null) {
0330:                    stopPosition = (ExecIndexRow) stopKeyGetter
0331:                            .invoke(activation);
0332:                }
0333:
0334:                /* NOTE: We always open the ScanController on the 1st open
0335:                 * to do the keyed conglomerate check.
0336:                 */
0337:
0338:                // Determine whether the conglomerate is keyed.  This determines
0339:                // how we find the RowLocation for the base heap.  For non-keyed
0340:                // conglomerates, we ask the scan.  For keyed conglomerates, it
0341:                // is the last column in the row.
0342:                //
0343:                // Do this here, rather than in the constructor, so we can avoid
0344:                // throwing exceptions from the constructor
0345:                if (firstScan) {
0346:                    openScanController(tc);
0347:
0348:                    isKeyed = scanController.isKeyed();
0349:
0350:                    /*
0351:                     ** If scan tracing is turned on, print information about this
0352:                     ** TableScanResultSet when it is first opened.  We would like
0353:                     ** to do this when it is constructed, but it is not always
0354:                     ** possible to get the start and stop positioners at the time
0355:                     ** this object is constructed (because they may depend on outer
0356:                     ** rows).
0357:                     */
0358:                    if (SanityManager.DEBUG) {
0359:                        if (SanityManager.DEBUG_ON("ScanTrace")) {
0360:                            //traceScanParameters();
0361:                        }
0362:                    }
0363:                }
0364:
0365:                // Check whether there are any comparisons with unordered nulls
0366:                // on either the start or stop position.  If there are, we can
0367:                // (and must) skip the scan, because no rows can qualify
0368:                if (skipScan(startPosition, stopPosition)) {
0369:                    scanControllerOpened = false;
0370:                }
0371:                /* NOTE: We always open the ScanController on the 1st open
0372:                 * to do the keyed conglomerate check, so we only need to
0373:                 * do it here if not the 1st scan.
0374:                 */
0375:                else if (!firstScan) {
0376:                    openScanController(tc);
0377:                }
0378:
0379:                /* If the scan is on an index and opened for update,
0380:                 * then we cache the scan controller and conglomerate
0381:                 * number in the activation so that the scan controller
0382:                 * can be re-used by the update/delete if the index
0383:                 * that we are scanning also needs to be updated.
0384:                 */
0385:                if (forUpdate && isKeyed) {
0386:                    activation.setIndexScanController(scanController);
0387:                    activation.setIndexConglomerateNumber(conglomId);
0388:                }
0389:
0390:                firstScan = false;
0391:                isOpen = true;
0392:                numOpens++;
0393:                nextDone = false;
0394:                openTime += getElapsedMillis(beginTime);
0395:            }
0396:
0397:            /*
0398:             ** Open the scan controller
0399:             **
0400:             ** @param transaction controller will open one if null
0401:             */
0402:            protected void openScanController(TransactionController tc)
0403:                    throws StandardException {
0404:                DataValueDescriptor[] startPositionRow = startPosition == null ? null
0405:                        : startPosition.getRowArray();
0406:                DataValueDescriptor[] stopPositionRow = stopPosition == null ? null
0407:                        : stopPosition.getRowArray();
0408:
0409:                // Clear the Qualifiers's Orderable cache 
0410:                if (qualifiers != null) {
0411:                    clearOrderableCache(qualifiers);
0412:                }
0413:
0414:                // Get the current transaction controller
0415:                if (tc == null)
0416:                    tc = activation.getTransactionController();
0417:
0418:                int openMode = 0;
0419:                if (forUpdate) {
0420:                    openMode = TransactionController.OPENMODE_FORUPDATE;
0421:
0422:                    if (activation.isCursorActivation())
0423:                        openMode |= TransactionController.OPENMODE_USE_UPDATE_LOCKS;
0424:                }
0425:
0426:                scanController = tc.openCompiledScan(activation
0427:                        .getResultSetHoldability(), openMode, lockMode,
0428:                        isolationLevel, accessedCols, startPositionRow,
0429:                        // not used when giving null start position
0430:                        startSearchOperator, qualifiers, stopPositionRow,
0431:                        // not used when giving null stop position
0432:                        stopSearchOperator, scoci, dcoci);
0433:
0434:                /* Remember that we opened the scan */
0435:                scanControllerOpened = true;
0436:
0437:                rowsThisScan = 0;
0438:
0439:                /*
0440:                 ** Inform the activation of the estimated number of rows.  Only
0441:                 ** do it here, not in reopen, so that we don't do this costly
0442:                 ** check too often.
0443:                 */
0444:                estimatedRowCount = scanController.getEstimatedRowCount();
0445:                activation.informOfRowCount(this , scanController
0446:                        .getEstimatedRowCount());
0447:            }
0448:
0449:            /*
0450:             ** reopen the scan controller
0451:             */
0452:            private void reopenScanController() throws StandardException {
0453:                DataValueDescriptor[] startPositionRow = startPosition == null ? null
0454:                        : startPosition.getRowArray();
0455:                DataValueDescriptor[] stopPositionRow = stopPosition == null ? null
0456:                        : stopPosition.getRowArray();
0457:
0458:                // Clear the Qualifiers's Orderable cache 
0459:                if (qualifiers != null) {
0460:                    clearOrderableCache(qualifiers);
0461:                }
0462:
0463:                scanController.reopenScan(startPositionRow,
0464:                        startSearchOperator, qualifiers, stopPositionRow,
0465:                        stopSearchOperator);
0466:
0467:                /* Remember that we opened the scan */
0468:                scanControllerOpened = true;
0469:
0470:                rowsThisScan = 0;
0471:            }
0472:
0473:            /**
0474:             * Reopen a table scan.  Here we take advantage
0475:             * of the reopenScan() interface on scanController
0476:             * for optimimal performance on joins where we are
0477:             * an inner table.
0478:             *
0479:             * @exception StandardException thrown on failure to open
0480:             */
0481:            public void reopenCore() throws StandardException {
0482:                beginTime = getCurrentTimeMillis();
0483:                if (SanityManager.DEBUG)
0484:                    SanityManager.ASSERT(isOpen,
0485:                            "TableScanResultSet not open, cannot reopen");
0486:
0487:                if (startKeyGetter != null) {
0488:                    startPosition = (ExecIndexRow) startKeyGetter
0489:                            .invoke(activation);
0490:                    if (sameStartStopPosition) {
0491:                        stopPosition = startPosition;
0492:                    }
0493:                }
0494:                if (stopKeyGetter != null) {
0495:                    stopPosition = (ExecIndexRow) stopKeyGetter
0496:                            .invoke(activation);
0497:                }
0498:
0499:                // Check whether there are any comparisons with unordered nulls
0500:                // on either the start or stop position.  If there are, we can
0501:                // (and must) skip the scan, because no rows can qualify
0502:                if (skipScan(startPosition, stopPosition)) {
0503:                    scanControllerOpened = false;
0504:                } else {
0505:                    if (scanController == null)
0506:                        openScanController((TransactionController) null);
0507:                    else
0508:                        reopenScanController();
0509:
0510:                }
0511:
0512:                numOpens++;
0513:                nextDone = false;
0514:                openTime += getElapsedMillis(beginTime);
0515:            }
0516:
0517:            /**
0518:             * Check and make sure sparse heap row and accessed bit map are created.
0519:             * beetle 3865, update cursor using index.
0520:             *
0521:             * @exception StandardException thrown on failure
0522:             */
0523:            private void getSparseRowAndMap() throws StandardException {
0524:                int numCols = 1, colPos;
0525:                for (int i = 0; i < indexCols.length; i++) {
0526:                    colPos = (indexCols[i] > 0) ? indexCols[i] : -indexCols[i];
0527:                    if (colPos > numCols)
0528:                        numCols = colPos;
0529:                }
0530:                sparseRow = new ValueRow(numCols);
0531:                sparseRowMap = new FormatableBitSet(numCols);
0532:                for (int i = 0; i < indexCols.length; i++) {
0533:                    if (accessedCols.get(i)) {
0534:                        colPos = (indexCols[i] > 0) ? indexCols[i]
0535:                                : -indexCols[i];
0536:                        sparseRow.setColumn(colPos, candidate.getColumn(i + 1));
0537:                        sparseRowMap.set(colPos - 1);
0538:                    }
0539:                }
0540:            }
0541:
0542:            /**
0543:             * Return the next row (if any) from the scan (if open).
0544:             *
0545:             * @exception StandardException thrown on failure to get next row
0546:             */
0547:            public ExecRow getNextRowCore() throws StandardException {
0548:                checkCancellationFlag();
0549:
0550:                if (currentRow == null || scanRepositioned) {
0551:                    currentRow = getCompactRow(candidate, accessedCols,
0552:                            (FormatableBitSet) null, isKeyed);
0553:                }
0554:
0555:                beginTime = getCurrentTimeMillis();
0556:
0557:                ExecRow result = null;
0558:
0559:                /* beetle 3865, updateable cursor using index. We first saved updated rows with new value
0560:                 * falling into future direction of index scan in hash table, if it's full, we scanned
0561:                 * forward and saved future row ids in a virtual mem heap.
0562:                 */
0563:                if (futureForUpdateRows != null) {
0564:                    currentRowPrescanned = false;
0565:                    if (!skipFutureRowHolder) {
0566:                        if (futureRowResultSet == null) {
0567:                            futureRowResultSet = (TemporaryRowHolderResultSet) futureForUpdateRows
0568:                                    .getResultSet();
0569:                            futureRowResultSet.openCore();
0570:                        }
0571:
0572:                        ExecRow ridRow = futureRowResultSet.getNextRowCore();
0573:
0574:                        if (ridRow != null) {
0575:                            /* to boost performance, we used virtual mem heap, and we can insert after
0576:                             * we start retrieving results.  The assumption is to
0577:                             * delete current row right after we retrieve it.
0578:                             */
0579:                            futureRowResultSet.deleteCurrentRow();
0580:                            RowLocation rl = (RowLocation) ridRow.getColumn(1);
0581:                            ConglomerateController baseCC = activation
0582:                                    .getHeapConglomerateController();
0583:                            if (sparseRow == null)
0584:                                getSparseRowAndMap();
0585:                            baseCC.fetch(rl, sparseRow.getRowArray(),
0586:                                    sparseRowMap);
0587:                            RowLocation rl2 = (RowLocation) rl.getClone();
0588:                            currentRow.setColumn(currentRow.nColumns(), rl2);
0589:                            candidate.setColumn(candidate.nColumns(), rl2); // have to be consistent!
0590:
0591:                            result = currentRow;
0592:                            currentRowPrescanned = true;
0593:                        } else if (sourceDrained) {
0594:                            currentRowPrescanned = true;
0595:                            currentRow = null;
0596:                        }
0597:
0598:                        if (currentRowPrescanned) {
0599:                            setCurrentRow(result);
0600:
0601:                            nextTime += getElapsedMillis(beginTime);
0602:                            return result;
0603:                        }
0604:                    }
0605:                }
0606:
0607:                if (isOpen && !nextDone) {
0608:                    /* Only need to do 1 next per scan
0609:                     * for 1 row scans.
0610:                     */
0611:                    nextDone = oneRowScan;
0612:
0613:                    if (scanControllerOpened) {
0614:                        boolean moreRows;
0615:
0616:                        while (moreRows = scanController.fetchNext(candidate
0617:                                .getRowArray())) {
0618:                            rowsSeen++;
0619:                            rowsThisScan++;
0620:
0621:                            /*
0622:                             ** Skip rows where there are start or stop positioners
0623:                             ** that do not implement ordered null semantics and
0624:                             ** there are columns in those positions that contain
0625:                             ** null.
0626:                             ** No need to check if start and stop positions are the
0627:                             ** same, since all predicates in both will be ='s,
0628:                             ** and hence evaluated in the store.
0629:                             */
0630:                            if ((!sameStartStopPosition) && skipRow(candidate)) {
0631:                                rowsFiltered++;
0632:                                continue;
0633:                            }
0634:
0635:                            /* beetle 3865, updateable cursor use index. If we have a hash table that
0636:                             * holds updated records, and we hit it again, skip it, and remove it from
0637:                             * hash since we can't hit it again, and we have a space in hash, so can
0638:                             * stop scanning forward.
0639:                             */
0640:                            if (past2FutureTbl != null) {
0641:                                RowLocation rowLoc = (RowLocation) currentRow
0642:                                        .getColumn(currentRow.nColumns());
0643:                                if (past2FutureTbl.get(rowLoc) != null) {
0644:                                    past2FutureTbl.remove(rowLoc);
0645:                                    continue;
0646:                                }
0647:                            }
0648:
0649:                            result = currentRow;
0650:
0651:                            break;
0652:                        }
0653:
0654:                        /*
0655:                         ** If we just finished a full scan of the heap, update
0656:                         ** the number of rows in the scan controller.
0657:                         **
0658:                         ** NOTE: It would be more efficient to only update the
0659:                         ** scan controller if the optimizer's estimated number of
0660:                         ** rows were wrong by more than some threshold (like 10%).
0661:                         ** This would require a little more work than I have the
0662:                         ** time for now, however, as the row estimate that is given
0663:                         ** to this result set is the total number of rows for all
0664:                         ** scans, not the number of rows per scan.
0665:                         */
0666:                        if (!moreRows) {
0667:                            setRowCountIfPossible(rowsThisScan);
0668:                            currentRow = null;
0669:                        }
0670:                    }
0671:                }
0672:
0673:                setCurrentRow(result);
0674:                currentRowIsValid = true;
0675:                scanRepositioned = false;
0676:                qualify = true;
0677:
0678:                nextTime += getElapsedMillis(beginTime);
0679:                return result;
0680:            }
0681:
0682:            /**
0683:             * If the result set has been opened,
0684:             * close the open scan.
0685:             * @exception StandardException on error
0686:             */
0687:            public void close() throws StandardException {
0688:                beginTime = getCurrentTimeMillis();
0689:                if (isOpen) {
0690:                    /*
0691:                     ** If scan tracing is turned on, print information about this
0692:                     ** TableScanResultSet when it is closed.
0693:                     */
0694:                    if (SanityManager.DEBUG) {
0695:                        if (SanityManager.DEBUG_ON("ScanTrace")) {
0696:                            //traceClose();
0697:                        }
0698:                    }
0699:
0700:                    // we don't want to keep around a pointer to the
0701:                    // row ... so it can be thrown away.
0702:                    // REVISIT: does this need to be in a finally
0703:                    // block, to ensure that it is executed?
0704:                    clearCurrentRow();
0705:                    ;
0706:                    if (scanController != null) {
0707:                        // This is where we get the positioner info for inner tables
0708:                        if (runTimeStatisticsOn) {
0709:                            // This is where we get the scan properties for a subquery
0710:                            scanProperties = getScanProperties();
0711:                            startPositionString = printStartPosition();
0712:                            stopPositionString = printStopPosition();
0713:                        }
0714:                        scanController.close();
0715:                        scanController = null; // should not access after close
0716:                        activation.clearIndexScanInfo();
0717:                    }
0718:                    scanControllerOpened = false;
0719:                    startPosition = null;
0720:                    stopPosition = null;
0721:
0722:                    super .close();
0723:
0724:                    if (indexCols != null) {
0725:                        ConglomerateController borrowedBaseCC = activation
0726:                                .getHeapConglomerateController();
0727:                        if (borrowedBaseCC != null) {
0728:                            borrowedBaseCC.close();
0729:                            activation.clearHeapConglomerateController();
0730:                        }
0731:                    }
0732:                    if (futureRowResultSet != null)
0733:                        futureRowResultSet.close();
0734:                } else if (SanityManager.DEBUG)
0735:                    SanityManager.DEBUG("CloseRepeatInfo",
0736:                            "Close of TableScanResultSet repeated");
0737:
0738:                closeTime += getElapsedMillis(beginTime);
0739:            }
0740:
0741:            /**
0742:             * Return the total amount of time spent in this ResultSet
0743:             *
0744:             * @param type	CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
0745:             *				ENTIRE_RESULTSET_TREE  - time spent in this ResultSet and below.
0746:             *
0747:             * @return long		The total amount of time spent (in milliseconds).
0748:             */
0749:            public long getTimeSpent(int type) {
0750:                long totTime = constructorTime + openTime + nextTime
0751:                        + closeTime;
0752:
0753:                /* RESOLVE - subtract out store time later, when available */
0754:                if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY) {
0755:                    return totTime;
0756:                } else {
0757:                    return totTime;
0758:                }
0759:            }
0760:
0761:            //
0762:            // CursorResultSet interface
0763:            //
0764:
0765:            /**
0766:             * This result set has its row location from
0767:             * the last fetch done. If the cursor is closed, 
0768:             * or the row has been deleted a null is returned.
0769:             *
0770:             * @see CursorResultSet
0771:             *
0772:             * @return the row location of the current cursor row.
0773:             * @exception StandardException thrown on failure to get row location
0774:             */
0775:            public RowLocation getRowLocation() throws StandardException {
0776:                RowLocation rl;
0777:
0778:                if (!isOpen)
0779:                    return null;
0780:
0781:                if (!scanControllerOpened)
0782:                    return null;
0783:
0784:                /*
0785:                 ** If the conglomerate is keyed, the row location of the base row
0786:                 ** is in the last column of the current row.  If it's not keyed,
0787:                 ** we get the row location from the scan of the heap.
0788:                 */
0789:                if (isKeyed) {
0790:                    if (SanityManager.DEBUG) {
0791:                        SanityManager
0792:                                .ASSERT(currentRow != null,
0793:                                        "There must be a current row when fetching the row location");
0794:                    }
0795:
0796:                    rl = (RowLocation) currentRow.getColumn(currentRow
0797:                            .nColumns());
0798:                } else {
0799:                    if (currentRowIsValid) {
0800:                        // we reuse the same rowlocation object across several calls.
0801:                        if (rlTemplate == null)
0802:                            rlTemplate = scanController
0803:                                    .newRowLocationTemplate();
0804:                        rl = rlTemplate;
0805:                        try {
0806:                            scanController.fetchLocation(rl);
0807:                        } catch (StandardException se) {
0808:                            if (se.getMessageId().equals(
0809:                                    SQLState.HEAP_SCAN_NOT_POSITIONED)) {
0810:                                //Have a easier to understand error message than what 
0811:                                //we get from store 
0812:                                throw StandardException
0813:                                        .newException(SQLState.NO_CURRENT_ROW);
0814:                            }
0815:                            throw se;
0816:                        }
0817:                    } else {
0818:                        rl = null;
0819:                    }
0820:                }
0821:
0822:                return rl;
0823:            }
0824:
0825:            /**
0826:             * This result set has its row from the last fetch done. 
0827:             * If the cursor is closed, the row has been deleted, or
0828:             * no longer qualifies (for forward only result sets) a 
0829:             * null is returned.
0830:             *
0831:             * @see CursorResultSet
0832:             *
0833:             * @return the last row returned;
0834:             * @exception StandardException thrown on failure.
0835:             */
0836:            /* RESOLVE - this should return activation.getCurrentRow(resultSetNumber),
0837:             * once there is such a method.  (currentRow is redundant)
0838:             */
0839:            public ExecRow getCurrentRow() throws StandardException {
0840:                ExecRow result = null;
0841:
0842:                if (SanityManager.DEBUG)
0843:                    SanityManager.ASSERT(isOpen, "TSRS expected to be open");
0844:
0845:                if (currentRowPrescanned)
0846:                    return currentRow;
0847:
0848:                /* Nothing to do if we're not currently on a row or
0849:                 * if the current row get deleted out from under us
0850:                 * or if there is no current scan (can happen if the
0851:                 * scan is being skipped) or if the current position
0852:                 * no longer qualifies.
0853:                 */
0854:                try {
0855:                    if ((currentRow == null)
0856:                            || (!currentRowIsValid)
0857:                            || (!scanControllerOpened)
0858:                            || (qualify && scanController
0859:                                    .isCurrentPositionDeleted())
0860:                            || (qualify && (!scanController
0861:                                    .doesCurrentPositionQualify()))) {
0862:                        return null;
0863:                    }
0864:                } catch (StandardException se) {
0865:                    if (se.getMessageId().equals(
0866:                            SQLState.AM_SCAN_NOT_POSITIONED)) {
0867:                        //bug 4515 - Have a easier to understand error message than what we get from store 
0868:                        se = StandardException
0869:                                .newException(SQLState.NO_CURRENT_ROW);
0870:                        throw se;
0871:                    }
0872:                }
0873:
0874:                result = (ExecRow) resultRowAllocator.invoke(activation);
0875:                currentRow = getCompactRow(result, accessedCols,
0876:                        (FormatableBitSet) null, isKeyed);
0877:
0878:                try {
0879:                    scanController.fetchWithoutQualify(result.getRowArray());
0880:                } catch (StandardException se) {
0881:                    if (se.getMessageId().equals(SQLState.AM_RECORD_NOT_FOUND)) {
0882:                        // Somehow the row got deleted between the above 
0883:                        // doesCurrentPositionQualify() call and here (one way is if
0884:                        // this scan is read uncommitted isolation level).
0885:                        return null;
0886:                    } else {
0887:                        throw se;
0888:                    }
0889:                }
0890:
0891:                setCurrentRow(result);
0892:                return currentRow;
0893:            }
0894:
0895:            /**
0896:             * @see NoPutResultSet#positionScanAtRowLocation
0897:             * 
0898:             * Also sets qualify to false so that later calls to getCurrentRow
0899:             * will not attempt to re-qualify the current row. 
0900:             */
0901:            public void positionScanAtRowLocation(RowLocation rl)
0902:                    throws StandardException {
0903:                // Check if the scanController is a B-tree scan controller. Do not
0904:                // attempt to re-position a b-tree controller.
0905:                if (!isKeyed) {
0906:                    currentRowIsValid = scanController
0907:                            .positionAtRowLocation(rl);
0908:                }
0909:                qualify = false;
0910:                scanRepositioned = true;
0911:            }
0912:
0913:            /**
0914:             * Print the parameters that constructed this result set to the
0915:             * trace stream.
0916:             */
0917:            /*
0918:             private final void traceScanParameters()
0919:             {
0920:             if (SanityManager.DEBUG)
0921:             {
0922:             HeaderPrintWriter traceStream = SanityManager.GET_DEBUG_STREAM();
0923:
0924:             traceStream.println("");
0925:             traceStream.println("TableScanResultSet number " +
0926:             resultSetNumber +
0927:             " parameters:");
0928:
0929:             traceStream.println("");
0930:             traceStream.println("\tTable name: " + tableName);
0931:             if (indexName != null)
0932:             {
0933:             traceStream.println("\tIndex name: " + indexName);
0934:             }
0935:             traceStream.println("");
0936:             traceStream.println("\tStart position is: ");
0937:             tracePrintPosition(traceStream,
0938:             startSearchOperator,
0939:             startKeyGetter);
0940:             traceStream.println("");
0941:             traceStream.println("\tStop position is: " );
0942:             tracePrintPosition(traceStream,
0943:             stopSearchOperator,
0944:             stopKeyGetter);
0945:             traceStream.println("");
0946:             traceStream.println("\tQualifiers are: ");
0947:             tracePrintQualifiers(traceStream, qualifiers, 2);
0948:             traceStream.println("");
0949:             }
0950:             }
0951:             */
0952:
0953:            /**
0954:             * Print I/O statistics about a scan when it closes.
0955:             */
0956:            /*
0957:             private final void traceClose()
0958:             {
0959:             if (SanityManager.DEBUG)
0960:             {
0961:             InfoStreams			infoStreams;
0962:             HeaderPrintWriter	traceStream;
0963:
0964:             traceStream = SanityManager.GET_DEBUG_STREAM();
0965:
0966:             traceStream.println("TableScanResultSet number " +
0967:             resultSetNumber +
0968:             " closed.");
0969:             if (isKeyed)
0970:             {
0971:             traceStream.println("\t" +
0972:             rowCount() +
0973:             " row(s) qualified from " +
0974:             "keyed" +
0975:             " table " +
0976:             tableName +
0977:             " using index " +
0978:             indexName);
0979:             }
0980:             else
0981:             {
0982:             traceStream.println("\t" +
0983:             rowCount() +
0984:             " row(s) qualified from " +
0985:             "non-keyed" +
0986:             " table " +
0987:             tableName);
0988:             }
0989:             traceStream.println("");
0990:             }
0991:             }
0992:             */
0993:
0994:            /**
0995:             * Print a start or stop positioner to the trace stream.
0996:             */
0997:            /*
0998:             private final void tracePrintPosition(HeaderPrintWriter traceStream,
0999:             int searchOperator,
1000:             GeneratedMethod positionGetter)
1001:             {
1002:             if (SanityManager.DEBUG)
1003:             {
1004:             if (positionGetter == null)
1005:             {
1006:             traceStream.println("\t\tNone");
1007:             return;
1008:             }
1009:
1010:             ExecIndexRow	positioner = null;
1011:
1012:             try
1013:             {
1014:             positioner = (ExecIndexRow) positionGetter.invoke(activation);
1015:             }
1016:             catch (StandardException e)
1017:             {
1018:             traceStream.println("\t\tUnexpected exception " +
1019:             e +
1020:             " getting positioner.");
1021:             e.printStackTrace(traceStream.getPrintWriter());
1022:             return;
1023:             }
1024:
1025:             if (positioner == null)
1026:             {
1027:             traceStream.println("\t\tNone");
1028:             return;
1029:             }
1030:
1031:             String searchOp = null;
1032:
1033:             switch (searchOperator)
1034:             {
1035:             case ScanController.GE:
1036:             searchOp = "GE";
1037:             break;
1038:
1039:             case ScanController.GT:
1040:             searchOp = "GT";
1041:             break;
1042:
1043:             default:
1044:             searchOp = "unknown value (" + searchOperator + ")";
1045:             break;
1046:             }
1047:
1048:             traceStream.println("\t\t" +
1049:             searchOp +
1050:             " on first " +
1051:             positioner.nColumns() +
1052:             " column(s).");
1053:
1054:             traceStream.print(
1055:             "\t\tOrdered null semantics on the following columns: ");
1056:             for (int position = 0; position < positioner.nColumns(); position++)
1057:             {
1058:             if (positioner.areNullsOrdered(position))
1059:             {
1060:             traceStream.print(position + " ");
1061:             }
1062:             }
1063:             traceStream.println("");
1064:             }
1065:             }
1066:             */
1067:
1068:            /**
1069:             * Print an array of Qualifiers to the trace stream.
1070:             */
1071:            /*
1072:             private final void tracePrintQualifiers(HeaderPrintWriter traceStream,
1073:             Qualifier[][] qualifiers,
1074:             int depth)
1075:             {
1076:             if (SanityManager.DEBUG)
1077:             {
1078:             char[] indentchars = new char[depth];
1079:
1080:             /*
1081:             ** Form an array of tab characters for indentation.
1082:             *
1083:             while (depth > 0)
1084:             {
1085:             indentchars[depth - 1] = '\t';
1086:             depth--;
1087:             }
1088:             String indent = new String(indentchars);
1089:
1090:             if (qualifiers == null)
1091:             {
1092:             traceStream.println(indent +
1093:             MessageService.getTextMessage(
1094:             SQLState.LANG_NONE)
1095:             );
1096:             return;
1097:             }
1098:
1099:             // RESOLVE (mikem) We don't support 2-d qualifiers yet.
1100:             if (SanityManager.DEBUG)
1101:             {
1102:             SanityManager.ASSERT(qualifiers.length == 1);
1103:             }
1104:
1105:             for (int i = 0; i < qualifiers[0].length; i++)
1106:             {
1107:             Qualifier qual = qualifiers[0][i];
1108:
1109:             traceStream.println("");
1110:             traceStream.println(indent + "Column Id: " + qual.getColumnId());
1111:            
1112:             int operator = qual.getOperator();
1113:             String opString = null;
1114:             switch (operator)
1115:             {
1116:             case Orderable.ORDER_OP_EQUALS:
1117:             opString = "=";
1118:             break;
1119:
1120:             case Orderable.ORDER_OP_LESSOREQUALS:
1121:             opString = "<=";
1122:             break;
1123:
1124:             case Orderable.ORDER_OP_LESSTHAN:
1125:             opString = "<";
1126:             break;
1127:
1128:             default:
1129:             opString = "unknown value (" + operator + ")";
1130:             break;
1131:             }
1132:             traceStream.println(indent + "Operator: " + opString);
1133:             traceStream.println(indent + "Ordered nulls: " +
1134:             qual.getOrderedNulls());
1135:             traceStream.println(indent + "Unknown return value: " +
1136:             qual.getUnknownRV());
1137:             traceStream.println(indent + "Negate comparison result: " +
1138:             qual.negateCompareResult());
1139:             traceStream.println("");
1140:             }
1141:             }
1142:             }
1143:             */
1144:
1145:            public String printStartPosition() {
1146:                return printPosition(startSearchOperator, startKeyGetter,
1147:                        startPosition);
1148:            }
1149:
1150:            public String printStopPosition() {
1151:                if (sameStartStopPosition) {
1152:                    return printPosition(stopSearchOperator, startKeyGetter,
1153:                            startPosition);
1154:                } else {
1155:                    return printPosition(stopSearchOperator, stopKeyGetter,
1156:                            stopPosition);
1157:                }
1158:            }
1159:
1160:            /**
1161:             * Return a start or stop positioner as a String.
1162:             *
1163:             * If we already generated the information, then use
1164:             * that.  Otherwise, invoke the activation to get it.
1165:             */
1166:            private String printPosition(int searchOperator,
1167:                    GeneratedMethod positionGetter, ExecIndexRow positioner) {
1168:                String idt = "";
1169:                String output = "";
1170:                if (positionGetter == null) {
1171:                    return "\t"
1172:                            + MessageService.getTextMessage(SQLState.LANG_NONE)
1173:                            + "\n";
1174:                }
1175:
1176:                if (positioner == null) {
1177:                    try {
1178:                        positioner = (ExecIndexRow) positionGetter
1179:                                .invoke(activation);
1180:                    } catch (StandardException e) {
1181:                        // the positionGetter will fail with a NullPointerException
1182:                        // if the outer table is empty
1183:                        // (this isn't a problem since we won't call it on the inner
1184:                        // table if there are no rows on the outer table)
1185:                        if (e.getSQLState() == SQLState.LANG_UNEXPECTED_USER_EXCEPTION)
1186:                            return "\t"
1187:                                    + MessageService
1188:                                            .getTextMessage(SQLState.LANG_POSITION_NOT_AVAIL);
1189:                        return "\t"
1190:                                + MessageService
1191:                                        .getTextMessage(
1192:                                                SQLState.LANG_UNEXPECTED_EXC_GETTING_POSITIONER,
1193:                                                e.toString());
1194:                    }
1195:                }
1196:                if (positioner == null) {
1197:                    return "\t"
1198:                            + MessageService.getTextMessage(SQLState.LANG_NONE)
1199:                            + "\n";
1200:                }
1201:                String searchOp = null;
1202:
1203:                switch (searchOperator) {
1204:                case ScanController.GE:
1205:                    searchOp = ">=";
1206:                    break;
1207:
1208:                case ScanController.GT:
1209:                    searchOp = ">";
1210:                    break;
1211:
1212:                default:
1213:                    if (SanityManager.DEBUG) {
1214:                        SanityManager.THROWASSERT("Unknown search operator "
1215:                                + searchOperator);
1216:                    }
1217:
1218:                    // NOTE: This does not have to be internationalized because
1219:                    // this code should never be reached.
1220:                    searchOp = "unknown value (" + searchOperator + ")";
1221:                    break;
1222:                }
1223:
1224:                output = output
1225:                        + "\t"
1226:                        + MessageService.getTextMessage(
1227:                                SQLState.LANG_POSITIONER, searchOp, String
1228:                                        .valueOf(positioner.nColumns())) + "\n";
1229:
1230:                output = output
1231:                        + "\t"
1232:                        + MessageService
1233:                                .getTextMessage(SQLState.LANG_ORDERED_NULL_SEMANTICS)
1234:                        + "\n";
1235:                for (int position = 0; position < positioner.nColumns(); position++) {
1236:                    if (positioner.areNullsOrdered(position)) {
1237:                        output = output + position + " ";
1238:                    }
1239:                }
1240:
1241:                return output + "\n";
1242:            }
1243:
1244:            public Properties getScanProperties() {
1245:                if (scanProperties == null) {
1246:                    scanProperties = new Properties();
1247:                }
1248:                try {
1249:                    if (scanController != null) {
1250:                        scanController.getScanInfo().getAllScanInfo(
1251:                                scanProperties);
1252:                        /* Did we get a coarser lock due to
1253:                         * a covering lock, lock escalation
1254:                         * or configuration?
1255:                         */
1256:                        coarserLock = scanController.isTableLocked()
1257:                                && (lockMode == TransactionController.MODE_RECORD);
1258:                    }
1259:                } catch (StandardException se) {
1260:                    // ignore
1261:                }
1262:
1263:                return scanProperties;
1264:            }
1265:
1266:            /**
1267:             * @see NoPutResultSet#getScanIsolationLevel
1268:             */
1269:            public int getScanIsolationLevel() {
1270:                return isolationLevel;
1271:            }
1272:
1273:            /**
1274:             * @see NoPutResultSet#requiresRelocking
1275:             */
1276:            public boolean requiresRelocking() {
1277:                return (isolationLevel == TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK);
1278:            }
1279:
1280:            /**
1281:             * Update the number of rows in the scan controller.
1282:             *
1283:             * NOTE: It would be more efficient to only update the
1284:             * scan controller if the optimizer's estimated number of
1285:             * rows were wrong by more than some threshold (like 10%).
1286:             * This would require a little more work than I have the
1287:             * time for now, however, as the row estimate that is given
1288:             * to this result set is the total number of rows for all
1289:             * scans, not the number of rows per scan.
1290:             *
1291:             *
1292:             * @param rowsThisScan	The number of rows to update the scanController to
1293:             *
1294:             * @exception StandardException		Thrown on error
1295:             */
1296:            protected final void setRowCountIfPossible(long rowsThisScan)
1297:                    throws StandardException {
1298:                /*
1299:                 ** Is it a heap scan with no qualifiers (full table scan?)
1300:                 ** and is it not for update (we don't want to count rows we're
1301:                 ** about to delete.
1302:                 */
1303:                if ((!scanController.isKeyed())
1304:                        && (qualifiers == null || qualifiers.length == 0)
1305:                        && (!forUpdate)) {
1306:
1307:                    // Only update rows if different by more than 10%
1308:                    long diff = rowsThisScan - estimatedRowCount;
1309:
1310:                    long tenPerCent = estimatedRowCount / 10;
1311:
1312:                    if (diff < 0)
1313:                        diff = -diff;
1314:
1315:                    if (diff > tenPerCent)
1316:                        scanController.setEstimatedRowCount(rowsThisScan);
1317:                }
1318:            }
1319:
1320:            /**
1321:             * Can we get instantaneous locks when getting share row
1322:             * locks at READ COMMITTED.
1323:             */
1324:            protected boolean canGetInstantaneousLocks() {
1325:                return false;
1326:            }
1327:
1328:            /**
1329:             * Is this ResultSet or it's source result set for update
1330:             * 
1331:             * @return Whether or not the result set is for update.
1332:             */
1333:            public boolean isForUpdate() {
1334:                return forUpdate;
1335:            }
1336:
1337:            /**
1338:             * Shallow clone this result set.  Used in trigger reference.
1339:             * beetle 4373.
1340:             */
1341:            public Object clone() {
1342:                Object clo = null;
1343:                try {
1344:                    clo = super .clone();
1345:                } catch (CloneNotSupportedException e) {
1346:                }
1347:                return clo;
1348:            }
1349:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.