Source Code Cross Referenced for GenericScanController.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » store » access » conglomerate » 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.store.access.conglomerate 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.store.access.conglomerate.GenericScanController
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.store.access.conglomerate;
0023:
0024:        import org.apache.derby.iapi.reference.SQLState;
0025:
0026:        import org.apache.derby.iapi.services.sanity.SanityManager;
0027:
0028:        import org.apache.derby.iapi.error.StandardException;
0029:
0030:        import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
0031:        import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
0032:        import org.apache.derby.iapi.store.access.conglomerate.ScanManager;
0033:        import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
0034:
0035:        import org.apache.derby.iapi.store.access.ConglomerateController;
0036:        import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
0037:        import org.apache.derby.iapi.store.access.Qualifier;
0038:        import org.apache.derby.iapi.store.access.RowUtil;
0039:        import org.apache.derby.iapi.store.access.ScanController;
0040:        import org.apache.derby.iapi.store.access.ScanInfo;
0041:        import org.apache.derby.iapi.store.access.SpaceInfo;
0042:
0043:        import org.apache.derby.iapi.store.raw.ContainerHandle;
0044:        import org.apache.derby.iapi.store.raw.FetchDescriptor;
0045:        import org.apache.derby.iapi.store.raw.Page;
0046:        import org.apache.derby.iapi.store.raw.RecordHandle;
0047:        import org.apache.derby.iapi.store.raw.Transaction;
0048:
0049:        import org.apache.derby.iapi.store.access.Qualifier;
0050:
0051:        import org.apache.derby.iapi.types.DataValueDescriptor;
0052:
0053:        import org.apache.derby.iapi.types.Orderable;
0054:        import org.apache.derby.iapi.types.RowLocation;
0055:
0056:        import org.apache.derby.iapi.store.access.BackingStoreHashtable;
0057:        import org.apache.derby.iapi.services.io.FormatableBitSet;
0058:
0059:        import java.util.Properties;
0060:
0061:        /**
0062:         Generic class implementing shared ScanController methods.
0063:
0064:         Logically a scancontroller is used to scan a set of rows that meet some 
0065:         specified qualification.  Rows that meet the qualification may be operated
0066:         upon by the scan to fetch, delete, or replace.  The ScanController also
0067:         supports the notion or "repositioning" the scan, which simply resets the
0068:         beginning of the scan to a new place, and allows the user to continue from
0069:         there.
0070:
0071:         This class attempts to abstract out some of the parts of the scan such that
0072:         maybe multiple access methods can share code, even if they perform parts of
0073:         the scan wildly differently.  Here is how the scan has been broken apart:
0074:
0075:         scan_position - this variable holds the current scan position, it may be 
0076:         extended
0077:         to provide more information if necessary.
0078:
0079:         scan_state    - a scan has 3 possible states: 
0080:         SCAN_INIT, SCAN_INPROGRESS, SCAN_DONE
0081:
0082:         positionAtInitScan()
0083:         - This routine is called to move the scan to the SCAN_INIT state.
0084:         It is used both for initialization of the ScanController and
0085:         by reopenScan().
0086:
0087:         positionAtStartForForwardScan()
0088:         - This routine is called to move the scan from SCAN_INIT to 
0089:         SCAN_INPROGRESS.  Upon return from this routine it is expected
0090:         that scan_position is set such that calling the generic 
0091:         scan loop will reach the first row of the scan.  Note that this
0092:         usually means setting the scan_postion to one before the 1st 
0093:         row to be returned.
0094:
0095:         fetchRows()   - This routine is the meat of the scan, it moves the scan to the
0096:         next row, applies necessary qualifiers, and handles group or
0097:         non-group operations.  It moves through rows on a page in
0098:         order and then moves to the "next" page.
0099:
0100:         positionAtNextPage()
0101:         - This routine handles moving the scan from the current 
0102:         scan_position to the next page.
0103:
0104:         positionAtDoneScan()
0105:         - Handle all cleanup associated with moving the scan state from
0106:         SCAN_INPROGRESS to SCAN_DONE.  This may include releasing locks,
0107:         and setting the state of the scan.  This does not close the 
0108:         scan, it allows for a reopenScan() to be called.
0109:         **/
0110:
0111:        public abstract class GenericScanController extends GenericController
0112:                implements  ScanManager {
0113:
0114:            /**************************************************************************
0115:             * Constants of the class
0116:             **************************************************************************
0117:             */
0118:
0119:            /*
0120:             * There are 5 states a scan can be in.
0121:             *     SCAN_INIT - A scan has started but no positioning has been done.
0122:             *                 The scan will be positioned when the first next() call
0123:             *                 has been made.  None of the positioning state variables
0124:             *                 are valid in this state.
0125:             *     SCAN_INPROGRESS -
0126:             *                 A scan is in this state after the first next() call.
0127:             *                 On exit from any GenericScanController method, while in 
0128:             *                 this state,
0129:             *                 the scan "points" at a row which qualifies for the 
0130:             *                 scan.  While not maintaining latches on a page the 
0131:             *                 current position of the scan is either kept by record
0132:             *                 handle or key.  To tell which use the following:
0133:             *                 if (record key == null)
0134:             *                    record handle has current position
0135:             *                 else
0136:             *                    record key has current position
0137:             *
0138:             *     SCAN_DONE - Once the end of the table or the stop condition is met
0139:             *                 then the scan is placed in this state.  Only valid 
0140:             *                 ScanController method at this point is close().
0141:             *
0142:             *     SCAN_HOLD_INIT -
0143:             *                 The scan has been opened and held open across a commit,
0144:             *                 at the last commit the state was SCAN_INIT.
0145:             *                 The scan has never progressed from the SCAN_INIT state
0146:             *                 during a transaction.  When a next is done the state
0147:             *                 will either progress to SCAN_INPROGRESS or SCAN_DONE.
0148:             *
0149:             *     SCAN_HOLD_INPROGRESS -
0150:             *                 The scan has been opened and held open across a commit,
0151:             *                 at the last commit the state was in SCAN_INPROGRESS.
0152:             *                 The transaction which opened the scan has committed,
0153:             *                 but the scan was opened with the "hold" option true.
0154:             *                 At commit the locks were released and the "current"
0155:             *                 position is remembered.  In this state only two calls
0156:             *                 are valid, either next() or close().  When next() is
0157:             *                 called the scan is reopened, the underlying container
0158:             *                 is opened thus associating all new locks with the current
0159:             *                 transaction, and the scan continues at the "next" row.
0160:             */
0161:            public static final int SCAN_INIT = 1;
0162:            public static final int SCAN_INPROGRESS = 2;
0163:            public static final int SCAN_DONE = 3;
0164:            public static final int SCAN_HOLD_INIT = 4;
0165:            public static final int SCAN_HOLD_INPROGRESS = 5;
0166:
0167:            /**************************************************************************
0168:             * Fields of the class
0169:             **************************************************************************
0170:             */
0171:
0172:            /**
0173:             * The following group of fields are all basic input parameters which are
0174:             * provided by the calling code when doing a scan.
0175:             * These are just saved values from what was initially input.
0176:             **/
0177:            private FormatableBitSet init_scanColumnList;
0178:            private DataValueDescriptor[] init_startKeyValue;
0179:            private int init_startSearchOperator;
0180:            private Qualifier[][] init_qualifier;
0181:            private DataValueDescriptor[] init_stopKeyValue;
0182:            private int init_stopSearchOperator;
0183:
0184:            private FetchDescriptor init_fetchDesc;
0185:
0186:            /**
0187:             * Delay positioning the table at the start position until the first
0188:             * next() call.
0189:             */
0190:            private int scan_state;
0191:
0192:            /**
0193:             * If this flag is set to true, a RowLocation returned from this controller
0194:             * may have been reused for another row.
0195:             */
0196:            protected boolean rowLocationsInvalidated = false;
0197:
0198:            /**
0199:             * This is the sequence number for when a record id can be
0200:             * reused. If it has been changed in the container, a RowLocation
0201:             * may be reused for another row.
0202:             */
0203:            private long reusableRecordIdSequenceNumber = 0;
0204:
0205:            /**
0206:             * The position for the current scan.  The can be maintained in any
0207:             * of the following ways:
0208:             *     record handle - scan_position.current_rh:
0209:             *         The scan maintains it's position using the record handle while
0210:             *         it does not have a latch on the page, which is the case anytime
0211:             *         control leaves access.  The access method must take appropriate
0212:             *         steps to make sure the record handle will still be valid when
0213:             *         the scan needs to reposition using the record handle.
0214:             *     slot number   - scan_position.current_slot:
0215:             *         While the scan has a latch on the page the scan is positioned
0216:             *         using the slot number as the order of the rows cannot change
0217:             *         while the latch is held (unless the holder of the latch causes
0218:             *         them to move).  
0219:             *     page number   - (RESOLVE - TODO)
0220:             *         Sometimes it would be interesting to position a scan "between"
0221:             *         pages, such that the next time the scan starts is starts at
0222:             *         the next page.  This would allow us to efficiently do group
0223:             *         scans returning page at atime results.  
0224:             *         NOT IMPLEMENTED CURRENTLY.
0225:             **/
0226:            protected RowPosition scan_position;
0227:
0228:            /**
0229:             * Performance counters ...
0230:             */
0231:            protected int stat_numpages_visited = 0;
0232:            protected int stat_numrows_visited = 0;
0233:            protected int stat_numrows_qualified = 0;
0234:
0235:            /**************************************************************************
0236:             * Constructors for This class:
0237:             **************************************************************************
0238:             */
0239:
0240:            /**************************************************************************
0241:             * Private methods of This class:
0242:             **************************************************************************
0243:             */
0244:
0245:            private final void repositionScanForUpateOper()
0246:                    throws StandardException {
0247:                if (scan_state != SCAN_INPROGRESS)
0248:                    throw StandardException
0249:                            .newException(SQLState.AM_SCAN_NOT_POSITIONED);
0250:
0251:                if (!open_conglom.latchPage(scan_position)) {
0252:                    throw StandardException.newException(
0253:                            SQLState.AM_RECORD_NOT_FOUND, open_conglom
0254:                                    .getContainer().getId(), new Long(
0255:                                    scan_position.current_rh.getId()));
0256:                }
0257:
0258:                if (open_conglom.isUseUpdateLocks()) {
0259:                    // we only have an U lock at this point which was acquired when the
0260:                    // scan positioned on the row, need to request an
0261:                    // X lock before we can actually perform the delete
0262:
0263:                    open_conglom.lockPositionForWrite(scan_position,
0264:                            false /* not insert */, true);
0265:                }
0266:            }
0267:
0268:            /**************************************************************************
0269:             * Protected methods implementing mechanics of scanning rows:
0270:             *
0271:             *     positionAtInitScan()             - move scan state to SCAN_INIT
0272:             *     positionAtStartForForwardScan()  - SCAN_INIT -> SCAN_INPROGRESS
0273:             *     positionAtResumeScan()           - reposition after losing scan latch
0274:             *     fetchRows()                      - move scan while in SCAN_INPROGRESS
0275:             *     positionAtNextPage()             - move page while in SCAN_INPROGRESS
0276:             *     positionAtDoneScan()             - SCAN_INPROGRESS -> SCAN_DONE
0277:             *
0278:             **************************************************************************
0279:             */
0280:
0281:            /**
0282:             * Move scan to the the SCAN_INIT state.
0283:             * <p>
0284:             * This routine is called to move the scan to the SCAN_INIT state.
0285:             * It is used both for initialization of the ScanController and
0286:             * by reopenScan().
0287:             **/
0288:            protected void positionAtInitScan(
0289:                    DataValueDescriptor[] startKeyValue,
0290:                    int startSearchOperator, Qualifier qualifier[][],
0291:                    DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
0292:                    RowPosition pos) throws StandardException {
0293:                // startKeyValue init.
0294:                this .init_startKeyValue = startKeyValue;
0295:                if (RowUtil.isRowEmpty(this .init_startKeyValue))
0296:                    this .init_startKeyValue = null;
0297:
0298:                // startSearchOperator init.
0299:                this .init_startSearchOperator = startSearchOperator;
0300:
0301:                // qualifier init.
0302:                if ((qualifier != null) && (qualifier.length == 0))
0303:                    qualifier = null;
0304:                this .init_qualifier = qualifier;
0305:
0306:                // TODO (mikem) - this could be more efficient, by writing
0307:                // code to figure out length of row, but scratch row is cached
0308:                // so allocating it here is probably not that bad.
0309:                init_fetchDesc = new FetchDescriptor((open_conglom
0310:                        .getRuntimeMem().get_scratch_row()).length,
0311:                        init_scanColumnList, init_qualifier);
0312:
0313:                // stopKeyValue init.
0314:                this .init_stopKeyValue = stopKeyValue;
0315:                if (RowUtil.isRowEmpty(this .init_stopKeyValue))
0316:                    this .init_stopKeyValue = null;
0317:
0318:                // stopSearchOperator init.
0319:                this .init_stopSearchOperator = stopSearchOperator;
0320:
0321:                // reset the "current" position to starting condition.
0322:                pos.init();
0323:
0324:                // Verify that all columns in start key value, stop key value, and
0325:                // qualifiers are present in the list of columns described by the
0326:                // scanColumnList.
0327:                if (SanityManager.DEBUG) {
0328:                    if (init_scanColumnList != null) {
0329:                        // verify that all columns specified in qualifiers, start
0330:                        // and stop positions are specified in the scanColumnList.  
0331:
0332:                        FormatableBitSet required_cols;
0333:
0334:                        if (qualifier != null)
0335:                            required_cols = RowUtil
0336:                                    .getQualifierBitSet(qualifier);
0337:                        else
0338:                            required_cols = new FormatableBitSet(0);
0339:
0340:                        // add in start columns
0341:                        if (this .init_startKeyValue != null) {
0342:                            required_cols.grow(this .init_startKeyValue.length);
0343:                            for (int i = 0; i < this .init_startKeyValue.length; i++)
0344:                                required_cols.set(i);
0345:                        }
0346:
0347:                        if (this .init_stopKeyValue != null) {
0348:                            required_cols.grow(this .init_stopKeyValue.length);
0349:                            for (int i = 0; i < this .init_stopKeyValue.length; i++)
0350:                                required_cols.set(i);
0351:                        }
0352:
0353:                        FormatableBitSet required_cols_and_scan_list = (FormatableBitSet) required_cols
0354:                                .clone();
0355:
0356:                        required_cols_and_scan_list.and(init_scanColumnList);
0357:
0358:                        // FormatableBitSet equals requires the two FormatableBitSets to be of same
0359:                        // length.
0360:                        required_cols.grow(init_scanColumnList.size());
0361:
0362:                        if (!required_cols_and_scan_list.equals(required_cols)) {
0363:                            SanityManager
0364:                                    .THROWASSERT("Some column specified in a Btree "
0365:                                            + " qualifier/start/stop list is "
0366:                                            + "not represented in the scanColumnList."
0367:                                            + "\n:required_cols_and_scan_list = "
0368:                                            + required_cols_and_scan_list
0369:                                            + "\n;required_cols = "
0370:                                            + required_cols
0371:                                            + "\n;init_scanColumnList = "
0372:                                            + init_scanColumnList);
0373:                        }
0374:                    }
0375:                }
0376:
0377:                // Scan is fully initialized and ready to go.
0378:                scan_state = SCAN_INIT;
0379:            }
0380:
0381:            /**
0382:             * Reposition the scan upon entering the fetchRows loop.
0383:             * <p>
0384:             * Called upon entering fetchRows() while in the SCAN_INPROGRESS state.
0385:             * Do work necessary to look at rows in the current page of the scan.
0386:             * <p>
0387:             * The default implementation uses a record handle to maintain a scan
0388:             * position.  It will get the latch again on the current
0389:             * scan position and set the slot to the current record handle.
0390:             *
0391:             * @exception  StandardException  Standard exception policy.
0392:             **/
0393:            protected void positionAtResumeScan(RowPosition pos)
0394:                    throws StandardException {
0395:                if (SanityManager.DEBUG) {
0396:                    SanityManager.ASSERT(scan_position.current_rh != null, this 
0397:                            .toString());
0398:                }
0399:
0400:                // reposition the scan at the row just before the next one to return.
0401:                // This routine handles the mess of repositioning if the row or the
0402:                // page has disappeared. This can happen if a lock was not held on the
0403:                // row while not holding the latch.
0404:                open_conglom.latchPageAndRepositionScan(scan_position);
0405:            }
0406:
0407:            /**
0408:             * Move the scan from SCAN_INIT to SCAN_INPROGRESS.
0409:             * <p>
0410:             * This routine is called to move the scan from SCAN_INIT to 
0411:             * SCAN_INPROGRESS.  Upon return from this routine it is expected
0412:             * that scan_position is set such that calling the generic 
0413:             * scan loop will reach the first row of the scan.  Note that this
0414:             * usually means setting the scan_postion to one before the 1st 
0415:             * row to be returned.
0416:             * <p>
0417:             *
0418:             * @exception  StandardException  Standard exception policy.
0419:             **/
0420:            protected void positionAtStartForForwardScan(RowPosition pos)
0421:                    throws StandardException {
0422:                if (pos.current_rh == null) {
0423:                    // 1st positioning of scan (delayed from openScan).
0424:                    pos.current_page = open_conglom.getContainer()
0425:                            .getFirstPage();
0426:
0427:                    if (SanityManager.DEBUG) {
0428:                        SanityManager
0429:                                .ASSERT(pos.current_page.getPageNumber() == ContainerHandle.FIRST_PAGE_NUMBER);
0430:
0431:                        if (pos.current_page.recordCount() < 1)
0432:                            SanityManager.THROWASSERT("record count = "
0433:                                    + pos.current_page.recordCount());
0434:                    }
0435:
0436:                    // set up for scan to continue at beginning of first page just
0437:                    // after first first control row on first page.
0438:                    pos.current_slot = Page.FIRST_SLOT_NUMBER;
0439:                } else {
0440:                    // 1st positioning of scan following a reopenScanByRowLocation
0441:
0442:                    // reposition the scan at the row just before the next one to 
0443:                    // return.  This routine handles the mess of repositioning if the 
0444:                    // row or the page has disappeared. This can happen if a lock was 
0445:                    // not held on the row while not holding the latch.
0446:                    open_conglom.latchPageAndRepositionScan(pos);
0447:
0448:                    // set up for scan to at the specified record handle (position one
0449:                    // before it so that the loop increment and find it).
0450:                    pos.current_slot -= 1;
0451:                }
0452:
0453:                pos.current_rh = null;
0454:                this .stat_numpages_visited = 1;
0455:                this .scan_state = SCAN_INPROGRESS;
0456:            }
0457:
0458:            /**
0459:             * Position scan to slot before first slot on next page.
0460:             * <p>
0461:             * @exception  StandardException  Standard exception policy.
0462:             **/
0463:            protected void positionAtNextPage(RowPosition pos)
0464:                    throws StandardException {
0465:                // The current_page can become null, in a rare multi-user case, where
0466:                // all pages in the heap are deallocated, in the middle of the scan
0467:                // loop, when no latches are held, and the scan is waiting on a lock.
0468:                // In this case the lockPositionForRead code, has nowhere good to 
0469:                // position the scan, so it just sets the page to null and returns.
0470:                if (pos.current_page != null) {
0471:                    // save current page number.
0472:                    long pageid = pos.current_page.getPageNumber();
0473:
0474:                    // unlatch old page.
0475:                    pos.unlatch();
0476:
0477:                    // latch page after current page number.
0478:                    pos.current_page = open_conglom.getContainer().getNextPage(
0479:                            pageid);
0480:
0481:                    // set up for scan to continue at beginning of this new page.
0482:                    pos.current_slot = Page.FIRST_SLOT_NUMBER - 1;
0483:                }
0484:            }
0485:
0486:            /**
0487:             * Do any necessary work to complete the scan.
0488:             *
0489:             * @exception  StandardException  Standard exception policy.
0490:             **/
0491:            protected void positionAtDoneScan(RowPosition pos)
0492:                    throws StandardException {
0493:                // Unlatch current page if any.
0494:                pos.unlatch();
0495:
0496:                // unlock the previous row.
0497:                if (scan_position.current_rh != null) {
0498:                    open_conglom.unlockPositionAfterRead(scan_position);
0499:                    scan_position.current_rh = null;
0500:                }
0501:
0502:                this .scan_state = SCAN_DONE;
0503:            }
0504:
0505:            public void reopenScanByRowLocation(RowLocation startRowLocation,
0506:                    Qualifier qualifier[][]) throws StandardException {
0507:                throw StandardException
0508:                        .newException(SQLState.BTREE_UNIMPLEMENTED_FEATURE);
0509:            }
0510:
0511:            /**************************************************************************
0512:             * Protected methods of This class:
0513:             **************************************************************************
0514:             */
0515:
0516:            /**
0517:             * Create object which represents the scan position.
0518:             * <p>
0519:             * Designed so that extending classes can override and allocate 
0520:             * implementation specific row position's.
0521:             *
0522:             * @exception  StandardException  Standard exception policy.
0523:             **/
0524:            protected RowPosition allocateScanPosition()
0525:                    throws StandardException {
0526:                return (new RowPosition());
0527:            }
0528:
0529:            /**
0530:             * Fetch the next N rows from the table.
0531:             * <p>
0532:             * Utility routine used by both fetchSet() and fetchNextGroup().
0533:             *
0534:             * @exception  StandardException  Standard exception policy.
0535:             **/
0536:            protected int fetchRows(DataValueDescriptor[][] row_array,
0537:                    RowLocation[] rowloc_array,
0538:                    BackingStoreHashtable hash_table, long max_rowcnt,
0539:                    int[] key_column_numbers) throws StandardException {
0540:                int ret_row_count = 0;
0541:                DataValueDescriptor[] fetch_row = null;
0542:
0543:                if (max_rowcnt == -1)
0544:                    max_rowcnt = Long.MAX_VALUE;
0545:
0546:                if (SanityManager.DEBUG) {
0547:                    if (row_array != null) {
0548:                        SanityManager
0549:                                .ASSERT(row_array[0] != null,
0550:                                        "first array slot in fetchNextGroup() must be non-null.");
0551:                        SanityManager.ASSERT(hash_table == null);
0552:                    } else {
0553:                        SanityManager.ASSERT(hash_table != null);
0554:                    }
0555:                }
0556:
0557:                if (this .scan_state == SCAN_INPROGRESS) {
0558:                    positionAtResumeScan(scan_position);
0559:                } else if (this .scan_state == SCAN_INIT) {
0560:                    positionAtStartForForwardScan(scan_position);
0561:
0562:                } else if (this .scan_state == SCAN_HOLD_INPROGRESS) {
0563:                    reopenAfterEndTransaction();
0564:
0565:                    if (SanityManager.DEBUG) {
0566:                        SanityManager.ASSERT(scan_position.current_rh != null,
0567:                                this .toString());
0568:                    }
0569:
0570:                    // reposition the scan at the row just before the next one to 
0571:                    // return.
0572:                    // This routine handles the mess of repositioning if the row or 
0573:                    // the page has disappeared. This can happen if a lock was not 
0574:                    // held on the row while not holding the latch.
0575:                    open_conglom.latchPageAndRepositionScan(scan_position);
0576:
0577:                    this .scan_state = SCAN_INPROGRESS;
0578:                } else if (this .scan_state == SCAN_HOLD_INIT) {
0579:                    reopenAfterEndTransaction();
0580:
0581:                    positionAtStartForForwardScan(scan_position);
0582:
0583:                } else {
0584:                    if (SanityManager.DEBUG)
0585:                        SanityManager.ASSERT(this .scan_state == SCAN_DONE);
0586:
0587:                    return (0);
0588:                }
0589:
0590:                // At this point:
0591:                // scan_position.current_page is latched.  
0592:                // scan_position.current_slot is the slot on scan_position.current_page
0593:                // just before the "next" record this routine should process.
0594:
0595:                // loop through successive pages and successive slots on those
0596:                // pages.  Stop when either the last page is reached 
0597:                // (scan_position.current_page will be null).  
0598:                // Along the way apply qualifiers to skip rows which don't qualify.
0599:
0600:                while (scan_position.current_page != null) {
0601:                    while ((scan_position.current_slot + 1) < scan_position.current_page
0602:                            .recordCount()) {
0603:                        // unlock the previous row.
0604:                        if (scan_position.current_rh != null) {
0605:                            open_conglom.unlockPositionAfterRead(scan_position);
0606:
0607:                        }
0608:                        // Allocate a new row to read the row into.
0609:                        if (fetch_row == null) {
0610:                            if (hash_table == null) {
0611:                                // point at allocated row in array if one exists.
0612:                                if (row_array[ret_row_count] == null) {
0613:                                    row_array[ret_row_count] = open_conglom
0614:                                            .getRuntimeMem()
0615:                                            .get_row_for_export();
0616:                                }
0617:
0618:                                fetch_row = row_array[ret_row_count];
0619:                            } else {
0620:                                fetch_row = open_conglom.getRuntimeMem()
0621:                                        .get_row_for_export();
0622:                            }
0623:                        }
0624:
0625:                        // move scan current position forward.
0626:                        scan_position.positionAtNextSlot();
0627:
0628:                        // Lock the row.
0629:                        boolean lock_granted_while_latch_held = open_conglom
0630:                                .lockPositionForRead(scan_position,
0631:                                        (RowPosition) null, true, true);
0632:
0633:                        if (!lock_granted_while_latch_held) {
0634:                            // if lock could not be granted while holding
0635:                            // latch, then the row may either be on the same page 
0636:                            // or it may no longer exist, this implementation does not
0637:                            // handle rows which move to different pages.  
0638:                            // 
0639:                            // If the row moved on the same page then 
0640:                            // lockPositionForRead() will have automatically updated
0641:                            // the scan_postion argument to point to it, and we 
0642:                            // wil now have a latch and a lock on that row.
0643:                            //
0644:                            // If the row no longer exists then the 
0645:                            // "moveForwardIfRowDisappears" argument makes this routine
0646:                            // find the "next" row in the heap and position on it.  If
0647:                            // a valid row exists in the current page to position on,
0648:                            // then lockPositionForRead() will position on it, get
0649:                            // a lock on it, and return with a latch on the page.  
0650:                            // Otherwise the routine will return with current_slot == -1
0651:                            // and it is up to this routine to continue the scan as
0652:                            // normal at the top of the loop.
0653:
0654:                            if (scan_position.current_page == null) {
0655:                                // page has been unlatched and the scan is done, there
0656:                                // are no more pages.  getNextPage() has been coded to
0657:                                // handle a null current_page.
0658:
0659:                                break;
0660:                            } else if (scan_position.current_slot == -1) {
0661:                                // This means that lockPositionForRead() had to 
0662:                                // reposition the scan forward to a new page, because 
0663:                                // the row the scan was locking was purged, when the 
0664:                                // latch was released to wait on the lock.  In this 
0665:                                // case just jump back to the top of loop and continue 
0666:                                // scan.
0667:
0668:                                if (SanityManager.DEBUG) {
0669:                                    SanityManager
0670:                                            .ASSERT(scan_position.current_rh == null);
0671:                                }
0672:
0673:                                continue;
0674:                            }
0675:                        }
0676:
0677:                        this .stat_numrows_visited++;
0678:
0679:                        // lockRowAtPosition set pos.current_rh as part of getting lock.
0680:                        if (SanityManager.DEBUG) {
0681:                            SanityManager
0682:                                    .ASSERT(scan_position.current_rh != null);
0683:
0684:                            // make sure current_rh and current_slot are in sync
0685:                            if (scan_position.current_slot != scan_position.current_page
0686:                                    .getSlotNumber(scan_position.current_rh)) {
0687:                                SanityManager
0688:                                        .THROWASSERT("current_slot = "
0689:                                                + scan_position.current_slot
0690:                                                + "current_rh = "
0691:                                                + scan_position.current_rh
0692:                                                + "current_rh.slot = "
0693:                                                + scan_position.current_page
0694:                                                        .getSlotNumber(scan_position.current_rh));
0695:                            }
0696:                        }
0697:
0698:                        // fetchFromSlot returns null if row does not qualify.
0699:
0700:                        scan_position.current_rh_qualified = (scan_position.current_page
0701:                                .fetchFromSlot(scan_position.current_rh,
0702:                                        scan_position.current_slot, fetch_row,
0703:                                        init_fetchDesc, false) != null);
0704:
0705:                        if (scan_position.current_rh_qualified) {
0706:                            // qualifying row.  
0707:
0708:                            // scan_position.current_rh is save position of scan while 
0709:                            // latch is not held.  It currently points at the 
0710:                            // scan_position.current_slot in search (while latch is 
0711:                            // held).
0712:                            if (SanityManager.DEBUG) {
0713:                                // make sure current_rh and current_slot are in sync
0714:                                SanityManager
0715:                                        .ASSERT(scan_position.current_slot == scan_position.current_page
0716:                                                .getSlotNumber(scan_position.current_rh));
0717:                            }
0718:
0719:                            // Found qualifying row.  Done fetching rows for the group?
0720:                            ret_row_count++;
0721:                            stat_numrows_qualified++;
0722:
0723:                            if (hash_table == null) {
0724:                                if (rowloc_array != null) {
0725:                                    // if requested return the associated row location.
0726:                                    setRowLocationArray(rowloc_array,
0727:                                            ret_row_count - 1, scan_position);
0728:                                }
0729:
0730:                                fetch_row = null;
0731:                            } else {
0732:                                if (hash_table.put(false, fetch_row)) {
0733:                                    // The row was inserted into the hash table so we
0734:                                    // need to create a new row next time through.
0735:                                    fetch_row = null;
0736:                                }
0737:                            }
0738:
0739:                            if (max_rowcnt <= ret_row_count) {
0740:                                // exit fetch row loop and return to the client.
0741:                                scan_position.unlatch();
0742:
0743:                                if (SanityManager.DEBUG) {
0744:                                    SanityManager
0745:                                            .ASSERT(scan_position.current_rh != null);
0746:                                }
0747:
0748:                                return (ret_row_count);
0749:                            }
0750:                        }
0751:                    }
0752:
0753:                    positionAtNextPage(scan_position);
0754:
0755:                    this .stat_numpages_visited++;
0756:                }
0757:
0758:                // Reached last page of scan.
0759:                positionAtDoneScan(scan_position);
0760:
0761:                // we need to decrement when we stop scan at the end of the table.
0762:                this .stat_numpages_visited--;
0763:
0764:                return (ret_row_count);
0765:            }
0766:
0767:            /**
0768:            Reposition the current scan.  This call is semantically the same as if
0769:            the current scan had been closed and a openScan() had been called instead.
0770:            The scan is reopened against the same conglomerate, and the scan
0771:            is reopened with the same "scan column list", "hold" and "forUpdate"
0772:            parameters passed in the original openScan.  
0773:            <p>
0774:            The statistics gathered by the scan are not reset to 0 by a reopenScan(),
0775:            rather they continue to accumulate.
0776:            <p>
0777:            Note that this operation is currently only supported on Heap conglomerates.
0778:            Also note that order of rows within are heap are not guaranteed, so for
0779:            instance positioning at a RowLocation in the "middle" of a heap, then
0780:            inserting more data, then continuing the scan is not guaranteed to see
0781:            the new rows - they may be put in the "beginning" of the heap.
0782:
0783:            @param startRecordHandle  An existing RecordHandle within the conglomerate,
0784:            at which to position the start of the scan.  The scan will begin at this
0785:            location and continue forward until the end of the conglomerate.  
0786:            Positioning at a non-existent RowLocation (ie. an invalid one or one that
0787:            had been deleted), will result in an exception being thrown when the 
0788:            first next operation is attempted.
0789:
0790:            @param qualifier An array of qualifiers which, applied
0791:            to each key, restrict the rows returned by the scan.  Rows
0792:            for which any one of the qualifiers returns false are not
0793:            returned by the scan. If null, all rows are returned.
0794:
0795:            @exception StandardException Standard exception policy.
0796:             **/
0797:            protected void reopenScanByRecordHandle(
0798:                    RecordHandle startRecordHandle, Qualifier qualifier[][])
0799:                    throws StandardException {
0800:                // initialize scan position parameters at beginning of scan
0801:                this .scan_state = (!open_conglom.getHold() ? SCAN_INIT
0802:                        : SCAN_HOLD_INIT);
0803:
0804:                // position the scan at the row before the given record id, so that
0805:                // the first "next" starts on the given row.
0806:                scan_position.current_rh = startRecordHandle;
0807:            }
0808:
0809:            protected abstract void setRowLocationArray(
0810:                    RowLocation[] rowloc_array, int index, RowPosition pos)
0811:                    throws StandardException;
0812:
0813:            /**************************************************************************
0814:             * abstract protected Methods of This class:
0815:             **************************************************************************
0816:             */
0817:
0818:            /**************************************************************************
0819:             * Public Methods of This class:
0820:             **************************************************************************
0821:             */
0822:            public void init(OpenConglomerate open_conglom,
0823:                    FormatableBitSet scanColumnList,
0824:                    DataValueDescriptor[] startKeyValue,
0825:                    int startSearchOperator, Qualifier qualifier[][],
0826:                    DataValueDescriptor[] stopKeyValue, int stopSearchOperator)
0827:                    throws StandardException {
0828:                super .init(open_conglom);
0829:
0830:                // RESOLVE (mikem) - move this into runtime_mem
0831:                scan_position = allocateScanPosition();
0832:
0833:                // remember inputs
0834:                init_scanColumnList = scanColumnList;
0835:
0836:                positionAtInitScan(startKeyValue, startSearchOperator,
0837:                        qualifier, stopKeyValue, stopSearchOperator,
0838:                        scan_position);
0839:
0840:                reusableRecordIdSequenceNumber = open_conglom.getContainer()
0841:                        .getReusableRecordIdSequenceNumber();
0842:            }
0843:
0844:            public final int getNumPagesVisited() {
0845:                return (stat_numpages_visited);
0846:            }
0847:
0848:            public final int getNumRowsVisited() {
0849:                return (stat_numrows_visited);
0850:            }
0851:
0852:            public final int getNumRowsQualified() {
0853:                return (stat_numrows_qualified);
0854:            }
0855:
0856:            public final FormatableBitSet getScanColumnList() {
0857:                return (init_scanColumnList);
0858:            }
0859:
0860:            public final DataValueDescriptor[] getStartKeyValue() {
0861:                return (init_startKeyValue);
0862:            }
0863:
0864:            public final int getStartSearchOperator() {
0865:                return (init_startSearchOperator);
0866:            }
0867:
0868:            public final DataValueDescriptor[] getStopKeyValue() {
0869:                return (init_stopKeyValue);
0870:            }
0871:
0872:            public final int getStopSearchOperator() {
0873:                return (init_stopSearchOperator);
0874:            }
0875:
0876:            public final Qualifier[][] getQualifier() {
0877:                return (init_qualifier);
0878:            }
0879:
0880:            public final int getScanState() {
0881:                return (scan_state);
0882:            }
0883:
0884:            public final void setScanState(int state) {
0885:                scan_state = state;
0886:            }
0887:
0888:            public final RowPosition getScanPosition() {
0889:                return (scan_position);
0890:            }
0891:
0892:            public final void setScanPosition(RowPosition pos) {
0893:                scan_position = pos;
0894:            }
0895:
0896:            /**************************************************************************
0897:             * Public Methods implementing ScanController:
0898:             **************************************************************************
0899:             */
0900:            private void closeScan() throws StandardException {
0901:                super .close();
0902:
0903:                // If we are closed due to catching an error in the middle of init,
0904:                // xact_manager may not be set yet. 
0905:                if (open_conglom.getXactMgr() != null)
0906:                    open_conglom.getXactMgr().closeMe(this );
0907:
0908:                // help the garbage collector.
0909:                this .init_qualifier = null;
0910:                init_scanColumnList = null;
0911:                init_startKeyValue = null;
0912:                init_stopKeyValue = null;
0913:            }
0914:
0915:            public void close() throws StandardException {
0916:                // Finish the scan - this may release locks if read committed and scan
0917:                // still holds some locks, and close comes before scan.next() returned
0918:                // that scan was done.
0919:                positionAtDoneScan(scan_position);
0920:
0921:                closeScan();
0922:            }
0923:
0924:            /**
0925:             * Reopens the scan after it has been closed as part of a commit.
0926:             * This method will check the reusableRecordIdSequenceNumber of the 
0927:             * container, and will set the rowLocationsInvalidated flag if it has 
0928:             * changed.
0929:             * @return true if the conglomerate has been reopened
0930:             * @exception StandardException Derby standard exception
0931:             */
0932:            protected final boolean reopenAfterEndTransaction()
0933:                    throws StandardException {
0934:                // Only reopen if holdable
0935:                if (!open_conglom.getHold()) {
0936:                    return (false);
0937:                }
0938:
0939:                ContainerHandle container = open_conglom.reopen();
0940:                switch (scan_state) {
0941:                case SCAN_INPROGRESS:
0942:                case SCAN_HOLD_INPROGRESS:
0943:                case SCAN_DONE:
0944:                    if (container.getReusableRecordIdSequenceNumber() != reusableRecordIdSequenceNumber) {
0945:                        rowLocationsInvalidated = true;
0946:                    }
0947:                    break;
0948:                case SCAN_INIT:
0949:                case SCAN_HOLD_INIT:
0950:                    reusableRecordIdSequenceNumber = container
0951:                            .getReusableRecordIdSequenceNumber();
0952:                    break;
0953:                default:
0954:                    break;
0955:                }
0956:                return (true);
0957:            }
0958:
0959:            public boolean closeForEndTransaction(boolean closeHeldScan)
0960:                    throws StandardException {
0961:                if ((!open_conglom.getHold()) || closeHeldScan) {
0962:                    // close the scan as part of the commit/abort
0963:
0964:                    this .scan_state = SCAN_DONE;
0965:
0966:                    closeScan();
0967:
0968:                    return (true);
0969:                } else {
0970:                    super .close();
0971:
0972:                    // allow the scan to continue after the commit.
0973:                    // locks and latches will be released as part of the commit, so
0974:                    // no need to release them by hand.
0975:
0976:                    if (this .scan_state == SCAN_INPROGRESS)
0977:                        this .scan_state = SCAN_HOLD_INPROGRESS;
0978:                    else if (this .scan_state == SCAN_INIT)
0979:                        this .scan_state = SCAN_HOLD_INIT;
0980:
0981:                    return (false);
0982:                }
0983:            }
0984:
0985:            /**
0986:            @see ScanController#delete
0987:             **/
0988:            public boolean delete() throws StandardException {
0989:                repositionScanForUpateOper();
0990:
0991:                boolean ret_val = true;
0992:
0993:                // RESOLVE (mikem) - RECID - performance could be better if we did not
0994:                // have to call isDeletedAtSlot().
0995:
0996:                // RESOLVE (mikem) - share code below with conglomerateController.
0997:
0998:                if (scan_position.current_page
0999:                        .isDeletedAtSlot(scan_position.current_slot)) {
1000:                    ret_val = false;
1001:                } else {
1002:                    // Delete the row 
1003:                    scan_position.current_page.deleteAtSlot(
1004:                            scan_position.current_slot, true,
1005:                            (LogicalUndo) null);
1006:
1007:                    if (scan_position.current_page.nonDeletedRecordCount() == 0) {
1008:                        queueDeletePostCommitWork(scan_position);
1009:                    }
1010:                }
1011:
1012:                scan_position.unlatch();
1013:
1014:                return (ret_val);
1015:            }
1016:
1017:            /**
1018:             * A call to allow client to indicate that current row does not qualify.
1019:             * <p>
1020:             * Indicates to the ScanController that the current row does not
1021:             * qualify for the scan.  If the isolation level of the scan allows, 
1022:             * this may result in the scan releasing the lock on this row.
1023:             * <p>
1024:             * Note that some scan implimentations may not support releasing locks on 
1025:             * non-qualifying rows, or may delay releasing the lock until sometime
1026:             * later in the scan (ie. it may be necessary to keep the lock until 
1027:             * either the scan is repositioned on the next row or page).
1028:             * <p>
1029:             * This call should only be made while the scan is positioned on a current
1030:             * valid row.
1031:             * RESOLVE (mikem-05/29/98) - Implement this when we support levels of
1032:             * concurrency less than serializable.
1033:             *
1034:             * @exception  StandardException  Standard exception policy.
1035:             **/
1036:            public void didNotQualify() throws StandardException {
1037:            }
1038:
1039:            /**
1040:             * Insert all rows that qualify for the current scan into the input
1041:             * Hash table.  
1042:             * <p>
1043:             * This routine scans executes the entire scan as described in the 
1044:             * openScan call.  For every qualifying unique row value an entry is
1045:             * placed into the HashTable. For unique row values the entry in the
1046:             * Hashtable has a key value of the object stored in 
1047:             * row[key_column_number], and the value of the data is row.  For row 
1048:             * values with duplicates, the key value is also row[key_column_number], 
1049:             * but the value of the data is a Vector of
1050:             * rows.  The caller will have to call "instanceof" on the data value
1051:             * object if duplicates are expected, to determine if the data value
1052:             * of the Hashtable entry is a row or is a Vector of rows.
1053:             * <p>
1054:             * Note, that for this routine to work efficiently the caller must 
1055:             * ensure that the object in row[key_column_number] implements 
1056:             * the hashCode and equals method as appropriate for it's datatype.
1057:             * <p>
1058:             * It is expected that this call will be the first and only call made in
1059:             * an openscan.  Qualifiers and stop position of the openscan are applied
1060:             * just as in a normal scan.  This call is logically equivalent to the 
1061:             * caller performing the following:
1062:             *
1063:             * import java.util.Hashtable;
1064:             *
1065:             * hash_table = new Hashtable();
1066:             *
1067:             * while (next())
1068:             * {
1069:             *     row = create_new_row();
1070:             *     fetch(row);
1071:             *     if ((duplicate_value = 
1072:             *         hash_table.put(row[key_column_number], row)) != null)
1073:             *     {
1074:             *         Vector row_vec;
1075:             *
1076:             *         // inserted a duplicate
1077:             *         if ((duplicate_value instanceof vector))
1078:             *         {
1079:             *             row_vec = (Vector) duplicate_value;
1080:             *         }
1081:             *         else
1082:             *         {
1083:             *             // allocate vector to hold duplicates
1084:             *             row_vec = new Vector(2);
1085:             *
1086:             *             // insert original row into vector
1087:             *             row_vec.addElement(duplicate_value);
1088:             *
1089:             *             // put the vector as the data rather than the row
1090:             *             hash_table.put(row[key_column_number], row_vec);
1091:             *         }
1092:             *         
1093:             *         // insert new row into vector
1094:             *         row_vec.addElement(row);
1095:             *     }
1096:             * }
1097:             * <p>
1098:             * The columns of the row will be the standard columns returned as
1099:             * part of a scan, as described by the validColumns - see openScan for
1100:             * description.
1101:             * RESOLVE - is this ok?  or should I hard code somehow the row to
1102:             *           be the first column and the row location?
1103:             * <p>
1104:             * Currently it is only possible to hash on the first column in the
1105:             * conglomerate, in the future we may change the interface to allow
1106:             * hashing either on a different column or maybe on a combination of
1107:             * columns.
1108:             * <p>
1109:             * No overflow to external storage is provided, so calling this routine
1110:             * on a 1 gigabyte conglomerate will incur at least 1 gigabyte of memory
1111:             * (probably failing with a java out of memory condition).  If this
1112:             * routine gets an out of memory condition, or if "max_rowcnt" is 
1113:             * exceeded then then the routine will give up, empty the Hashtable, 
1114:             * and return "false."
1115:             * <p>
1116:             * On exit from this routine, whether the fetchSet() succeeded or not
1117:             * the scan is complete, it is positioned just the same as if the scan
1118:             * had been drained by calling "next()" until it returns false (ie. 
1119:             * fetchNext() and next() calls will return false).  
1120:             * reopenScan() can be called to restart the scan.
1121:             * <p>
1122:             *
1123:             * RESOLVE - until we get row counts what should we do for sizing the
1124:             *           the size, capasity, and load factor of the hash table.
1125:             *           For now it is up to the caller to create the Hashtable,
1126:             *           Access does not reset any parameters.
1127:             * <p>
1128:             * RESOLVE - I am not sure if access should be in charge of allocating
1129:             *           the new row objects.  I know that I can do this in the
1130:             *           case of btree's, but I don't think I can do this in heaps.
1131:             *           Maybe this is solved by work to be done on the sort 
1132:             *           interface.
1133:             *
1134:             *
1135:             * @param max_rowcnt        The maximum number of rows to insert into the 
1136:             *                          Hash table.  Pass in -1 if there is no maximum.
1137:             * @param key_column_numbers The column numbers of the columns in the
1138:             *                          scan result row to be the key to the Hashtable.
1139:             *                          "0" is the first column in the scan result
1140:             *                          row (which may be different than the first
1141:             *                          column in the row in the table of the scan).
1142:             * @param hash_table        The java HashTable to load into.
1143:             *
1144:             * @exception  StandardException  Standard exception policy.
1145:             **/
1146:            public void fetchSet(long max_rowcnt, int[] key_column_numbers,
1147:                    BackingStoreHashtable hash_table) throws StandardException {
1148:                fetchRows((DataValueDescriptor[][]) null, (RowLocation[]) null,
1149:                        hash_table, max_rowcnt, key_column_numbers);
1150:
1151:                return;
1152:            }
1153:
1154:            /**
1155:            Reposition the current scan.  This call is semantically the same as if
1156:            the current scan had been closed and a openScan() had been called instead.
1157:            The scan is reopened with against the same conglomerate, and the scan
1158:            is reopened with the same "hold" and "forUpdate" parameters passed in
1159:            the original openScan.  The previous template row continues to be used.
1160:
1161:            @param startKeyValue  An indexable row which holds a 
1162:            (partial) key value which, in combination with the
1163:            startSearchOperator, defines the starting position of
1164:            the scan.  If null, the starting position of the scan
1165:            is the first row of the conglomerate.
1166:            
1167:            @param startSearchOperator an operator which defines
1168:            how the startKeyValue is to be searched for.  If 
1169:            startSearchOperator is ScanController.GE, the scan starts on
1170:            the first row which is greater than or equal to the 
1171:            startKeyValue.  If startSearchOperation is ScanController.GT,
1172:            the scan starts on the first row whose key is greater than
1173:            startKeyValue.  The startSearchOperation parameter is 
1174:            ignored if the startKeyValue parameter is null.
1175:
1176:            @param qualifier An array of qualifiers which, applied
1177:            to each key, restrict the rows returned by the scan.  Rows
1178:            for which any one of the qualifiers returns false are not
1179:            returned by the scan. If null, all rows are returned.
1180:
1181:            @param stopKeyValue  An indexable row which holds a 
1182:            (partial) key value which, in combination with the
1183:            stopSearchOperator, defines the ending position of
1184:            the scan.  If null, the ending position of the scan
1185:            is the last row of the conglomerate.
1186:            
1187:            @param stopSearchOperator an operator which defines
1188:            how the stopKeyValue is used to determine the scan stopping
1189:            position. If stopSearchOperation is ScanController.GE, the scan 
1190:            stops just before the first row which is greater than or
1191:            equal to the stopKeyValue.  If stopSearchOperation is
1192:            ScanController.GT, the scan stops just before the first row whose
1193:            key is greater than	startKeyValue.  The stopSearchOperation
1194:            parameter is ignored if the stopKeyValue parameter is null.
1195:
1196:            @exception StandardException Standard exception policy.
1197:             **/
1198:            public void reopenScan(DataValueDescriptor[] startKeyValue,
1199:                    int startSearchOperator, Qualifier qualifier[][],
1200:                    DataValueDescriptor[] stopKeyValue, int stopSearchOperator)
1201:                    throws StandardException {
1202:                if (SanityManager.DEBUG) {
1203:                    if (!open_conglom.getHold()) {
1204:                        SanityManager
1205:                                .ASSERT(!open_conglom.isClosed(),
1206:                                        "GenericScanController.reopenScan() called on a non-held closed scan.");
1207:                    }
1208:                }
1209:
1210:                // initialize scan position parameters at beginning of scan
1211:                this .scan_state = (!open_conglom.getHold() ? SCAN_INIT
1212:                        : SCAN_HOLD_INIT);
1213:
1214:                scan_position.current_rh = null;
1215:            }
1216:
1217:            /**
1218:            @see ScanController#replace
1219:             **/
1220:            public boolean replace(DataValueDescriptor[] row,
1221:                    FormatableBitSet validColumns) throws StandardException {
1222:                repositionScanForUpateOper();
1223:
1224:                boolean ret_val = scan_position.current_page.update(
1225:                        scan_position.current_rh, row, validColumns);
1226:
1227:                scan_position.unlatch();
1228:
1229:                return (ret_val);
1230:            }
1231:
1232:            /**
1233:            Returns true if the current position of the scan still qualifies
1234:            under the set of qualifiers passed to the openScan().  When called
1235:            this routine will reapply all qualifiers against the row currently
1236:            positioned and return true if the row still qualifies.  If the row
1237:            has been deleted or no longer passes the qualifiers then this routine
1238:            will return false.
1239:            
1240:            This case can come about if the current scan
1241:            or another scan on the same table in the same transaction 
1242:            deleted the row or changed columns referenced by the qualifier after 
1243:            the next() call which positioned the scan at this row.  
1244:
1245:            Note that for comglomerates which don't support update, like btree's, 
1246:            there is no need to recheck the qualifiers.
1247:
1248:            The results of a fetch() performed on a scan positioned on 
1249:            a deleted row are undefined.
1250:
1251:            @exception StandardException Standard exception policy.
1252:             **/
1253:            public boolean doesCurrentPositionQualify()
1254:                    throws StandardException {
1255:                if (scan_state != SCAN_INPROGRESS)
1256:                    throw StandardException
1257:                            .newException(SQLState.AM_SCAN_NOT_POSITIONED);
1258:
1259:                if (!open_conglom.latchPage(scan_position)) {
1260:                    return (false);
1261:                }
1262:
1263:                DataValueDescriptor row[] = open_conglom.getRuntimeMem()
1264:                        .get_scratch_row();
1265:
1266:                // If fetchFromSlot returns null it either means the row is deleted,
1267:                // or the qualifier evaluates to false.
1268:
1269:                boolean ret_val = (scan_position.current_page.fetchFromSlot(
1270:                        scan_position.current_rh, scan_position.current_slot,
1271:                        row, init_fetchDesc, false) != null);
1272:
1273:                scan_position.unlatch();
1274:
1275:                return (ret_val);
1276:            }
1277:
1278:            /**
1279:            Fetch the row at the current position of the Scan without applying the 
1280:            qualifiers.
1281:            
1282:            @see ScanController#fetchWithoutQualify
1283:             **/
1284:            public void fetchWithoutQualify(DataValueDescriptor[] row)
1285:                    throws StandardException {
1286:                fetch(row, false);
1287:            }
1288:
1289:            /**
1290:            Fetch the row at the current position of the Scan.
1291:
1292:            @see ScanController#fetch
1293:             **/
1294:            public void fetch(DataValueDescriptor[] row)
1295:                    throws StandardException {
1296:                fetch(row, true);
1297:            }
1298:
1299:            /**
1300:            Fetch the row at the current position of the Scan.
1301:
1302:            @param row The row into which the value of the current 
1303:             position in the scan is to be stored.
1304:
1305:            @param qualify Indicates whether the qualifiers should be applied.
1306:
1307:            @exception StandardException Standard exception policy.
1308:             **/
1309:            private void fetch(DataValueDescriptor[] row, boolean qualify)
1310:                    throws StandardException {
1311:                if (scan_state != SCAN_INPROGRESS)
1312:                    throw StandardException
1313:                            .newException(SQLState.AM_SCAN_NOT_POSITIONED);
1314:
1315:                if (!open_conglom.latchPage(scan_position)) {
1316:                    throw StandardException.newException(
1317:                            SQLState.AM_RECORD_NOT_FOUND, open_conglom
1318:                                    .getContainer().getId(), new Long(
1319:                                    scan_position.current_rh.getId()));
1320:                }
1321:
1322:                // RESOLVE (mikem) - should this call apply the qualifiers again?
1323:                RecordHandle rh = scan_position.current_page.fetchFromSlot(
1324:                        scan_position.current_rh, scan_position.current_slot,
1325:                        row, qualify ? init_fetchDesc : null, false);
1326:
1327:                scan_position.unlatch();
1328:
1329:                if (rh == null) {
1330:                    /*
1331:                    if (SanityManager.DEBUG)
1332:                    {
1333:                        if (isCurrentPositionDeleted())
1334:                            SanityManager.THROWASSERT(
1335:                                "The record (" + 
1336:                                open_conglom.getContainer().getId() +
1337:                                ", " +
1338:                                scan_position.current_rh.getPageNumber() + ", " +
1339:                                scan_position.current_rh.getId() + ") " +
1340:                                "being fetched is marked deleted on page.:\n");
1341:                    }
1342:                     */
1343:
1344:                    throw StandardException.newException(
1345:                            SQLState.AM_RECORD_NOT_FOUND, open_conglom
1346:                                    .getContainer().getId(), new Long(
1347:                                    scan_position.current_rh.getId()));
1348:                }
1349:
1350:                return;
1351:            }
1352:
1353:            /**
1354:            Fetch the location of the current position in the scan.
1355:            @see ScanController#fetchLocation
1356:
1357:            @exception  StandardException  Standard exception policy.
1358:             **/
1359:            public void fetchLocation(RowLocation templateLocation)
1360:                    throws StandardException {
1361:                throw StandardException
1362:                        .newException(SQLState.BTREE_UNIMPLEMENTED_FEATURE);
1363:            }
1364:
1365:            /**
1366:             * Return ScanInfo object which describes performance of scan.
1367:             * <p>
1368:             * Return ScanInfo object which contains information about the current
1369:             * scan.
1370:             * <p>
1371:             *
1372:             * @see ScanInfo
1373:             *
1374:             * @return The ScanInfo object which contains info about current scan.
1375:             *
1376:             * @exception  StandardException  Standard exception policy.
1377:             **/
1378:            public ScanInfo getScanInfo() throws StandardException {
1379:                throw StandardException
1380:                        .newException(SQLState.BTREE_UNIMPLEMENTED_FEATURE);
1381:            }
1382:
1383:            /**
1384:            Returns true if the current position of the scan is at a 
1385:            deleted row.  This case can come about if the current scan
1386:            or another scan on the same table in the same transaction 
1387:            deleted the row after the next() call which positioned the
1388:            scan at this row.  
1389:
1390:            The results of a fetch() performed on a scan positioned on 
1391:            a deleted row are undefined.
1392:
1393:            @exception StandardException Standard exception policy.
1394:             **/
1395:            public boolean isCurrentPositionDeleted() throws StandardException {
1396:                if (scan_state != SCAN_INPROGRESS)
1397:                    throw StandardException
1398:                            .newException(SQLState.AM_SCAN_NOT_POSITIONED);
1399:
1400:                if (!open_conglom.latchPage(scan_position)) {
1401:                    return (true);
1402:                }
1403:
1404:                boolean ret_val = scan_position.current_page
1405:                        .isDeletedAtSlot(scan_position.current_slot);
1406:
1407:                scan_position.unlatch();
1408:
1409:                return (ret_val);
1410:            }
1411:        }
w___w___w___.__j__a__v__a___2__s___.co___m_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.