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


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.sql.compile.ProjectRestrictNode
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.compile;
0023:
0024:        import org.apache.derby.iapi.services.context.ContextManager;
0025:
0026:        import org.apache.derby.iapi.sql.compile.Optimizable;
0027:        import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
0028:        import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
0029:        import org.apache.derby.iapi.sql.compile.Optimizer;
0030:        import org.apache.derby.iapi.sql.compile.CostEstimate;
0031:        import org.apache.derby.iapi.sql.compile.OptimizableList;
0032:        import org.apache.derby.iapi.sql.compile.Visitable;
0033:        import org.apache.derby.iapi.sql.compile.Visitor;
0034:        import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
0035:        import org.apache.derby.iapi.sql.compile.RowOrdering;
0036:        import org.apache.derby.iapi.sql.compile.AccessPath;
0037:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
0038:
0039:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
0040:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
0041:
0042:        import org.apache.derby.iapi.types.DataValueDescriptor;
0043:
0044:        import org.apache.derby.iapi.sql.execute.NoPutResultSet;
0045:
0046:        import org.apache.derby.iapi.sql.Activation;
0047:        import org.apache.derby.iapi.sql.ResultSet;
0048:
0049:        import org.apache.derby.iapi.error.StandardException;
0050:        import org.apache.derby.iapi.reference.ClassName;
0051:
0052:        import org.apache.derby.iapi.store.access.TransactionController;
0053:
0054:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
0055:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
0056:
0057:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
0058:
0059:        import org.apache.derby.iapi.services.loader.GeneratedMethod;
0060:
0061:        import org.apache.derby.iapi.services.sanity.SanityManager;
0062:
0063:        import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;
0064:        import org.apache.derby.iapi.util.JBitSet;
0065:        import org.apache.derby.iapi.services.classfile.VMOpcode;
0066:
0067:        import java.util.Properties;
0068:        import java.util.HashSet;
0069:        import java.util.Set;
0070:
0071:        /**
0072:         * A ProjectRestrictNode represents a result set for any of the basic DML
0073:         * operations: SELECT, INSERT, UPDATE, and DELETE.  For INSERT with
0074:         * a VALUES clause, restriction will be null. For both INSERT and UPDATE,
0075:         * the resultColumns in the selectList will contain the names of the columns
0076:         * being inserted into or updated.
0077:         *
0078:         * NOTE: A ProjectRestrictNode extends FromTable since it can exist in a FromList.
0079:         *
0080:         * @author Jeff Lichtman
0081:         */
0082:
0083:        public class ProjectRestrictNode extends SingleChildResultSetNode {
0084:            /**
0085:             * The ValueNode for the restriction to be evaluated here.
0086:             */
0087:            public ValueNode restriction;
0088:
0089:            /**
0090:             * Constant expressions to be evaluated here.
0091:             */
0092:            ValueNode constantRestriction = null;
0093:
0094:            /**
0095:             * Restriction as a PredicateList
0096:             */
0097:            public PredicateList restrictionList;
0098:
0099:            /**
0100:             * List of subqueries in projection
0101:             */
0102:            SubqueryList projectSubquerys;
0103:
0104:            /**
0105:             * List of subqueries in restriction
0106:             */
0107:            SubqueryList restrictSubquerys;
0108:
0109:            private boolean accessPathModified;
0110:
0111:            private boolean accessPathConsidered;
0112:
0113:            private boolean childResultOptimized;
0114:
0115:            private boolean materialize;
0116:
0117:            /* Should we get the table number from this node,
0118:             * regardless of the class of our child.
0119:             */
0120:            private boolean getTableNumberHere;
0121:
0122:            /**
0123:             * Initializer for a ProjectRestrictNode.
0124:             *
0125:             * @param childResult	The child ResultSetNode
0126:             * @param projection	The result column list for the projection
0127:             * @param restriction	An expression representing the restriction to be 
0128:             *					    evaluated here.
0129:             * @param restrictionList Restriction as a PredicateList
0130:             * @param projectSubquerys List of subqueries in the projection
0131:             * @param restrictSubquerys List of subqueries in the restriction
0132:             * @param tableProperties	Properties list associated with the table
0133:             */
0134:
0135:            public void init(Object childResult, Object projection,
0136:                    Object restriction, Object restrictionList,
0137:                    Object projectSubquerys, Object restrictSubquerys,
0138:                    Object tableProperties) {
0139:                super .init(childResult, tableProperties);
0140:                resultColumns = (ResultColumnList) projection;
0141:                this .restriction = (ValueNode) restriction;
0142:                this .restrictionList = (PredicateList) restrictionList;
0143:                this .projectSubquerys = (SubqueryList) projectSubquerys;
0144:                this .restrictSubquerys = (SubqueryList) restrictSubquerys;
0145:
0146:                /* A PRN will only hold the tableProperties for
0147:                 * a result set tree if its child is not an
0148:                 * optimizable.  Otherwise, the properties will
0149:                 * be transferred down to the child.
0150:                 */
0151:                if (tableProperties != null
0152:                        && (childResult instanceof  Optimizable)) {
0153:                    ((Optimizable) childResult).setProperties(getProperties());
0154:                    setProperties((Properties) null);
0155:                }
0156:            }
0157:
0158:            /*
0159:             *  Optimizable interface
0160:             */
0161:
0162:            /**
0163:            	@see Optimizable#nextAccessPath
0164:            	@exception StandardException	Thrown on error
0165:             */
0166:            public boolean nextAccessPath(Optimizer optimizer,
0167:                    OptimizablePredicateList predList, RowOrdering rowOrdering)
0168:                    throws StandardException {
0169:                /*
0170:                 ** If the child result set is an optimizable, let it choose its next
0171:                 ** access path.  If it is not an optimizable, we have to tell the
0172:                 ** caller that there is an access path the first time we are called
0173:                 ** for this position in the join order, and that there are no more
0174:                 ** access paths for subsequent calls for this position in the join
0175:                 ** order.  The startOptimizing() method is called once on each
0176:                 ** optimizable when it is put into a join position.
0177:                 */
0178:                if (childResult instanceof  Optimizable) {
0179:                    return ((Optimizable) childResult).nextAccessPath(
0180:                            optimizer, restrictionList, rowOrdering);
0181:                } else {
0182:                    return super .nextAccessPath(optimizer, predList,
0183:                            rowOrdering);
0184:                }
0185:            }
0186:
0187:            /** @see Optimizable#rememberAsBest 
0188:            	@exception StandardException	Thrown on error
0189:             */
0190:            public void rememberAsBest(int planType, Optimizer optimizer)
0191:                    throws StandardException {
0192:                super .rememberAsBest(planType, optimizer);
0193:                if (childResult instanceof  Optimizable)
0194:                    ((Optimizable) childResult).rememberAsBest(planType,
0195:                            optimizer);
0196:            }
0197:
0198:            /* Don't print anything for a PRN, as their
0199:             * child has the interesting info.
0200:             */
0201:            void printRememberingBestAccessPath(int planType,
0202:                    AccessPath bestPath) {
0203:            }
0204:
0205:            /** @see Optimizable#startOptimizing */
0206:            public void startOptimizing(Optimizer optimizer,
0207:                    RowOrdering rowOrdering) {
0208:                if (childResult instanceof  Optimizable) {
0209:                    ((Optimizable) childResult).startOptimizing(optimizer,
0210:                            rowOrdering);
0211:                } else {
0212:                    accessPathConsidered = false;
0213:
0214:                    super .startOptimizing(optimizer, rowOrdering);
0215:                }
0216:            }
0217:
0218:            /** @see Optimizable#getTableNumber */
0219:            public int getTableNumber() {
0220:                /* GROSS HACK - We need to get the tableNumber after
0221:                 * calling modifyAccessPaths() on the child when doing
0222:                 * a hash join on an arbitrary result set.  The problem
0223:                 * is that the child will always be an optimizable at this
0224:                 * point.  So, we 1st check to see if we should get it from
0225:                 * this node.  (We set the boolean to true in the appropriate
0226:                 * place in modifyAccessPaths().)
0227:                 */
0228:                if (getTableNumberHere) {
0229:                    return super .getTableNumber();
0230:                }
0231:
0232:                if (childResult instanceof  Optimizable)
0233:                    return ((Optimizable) childResult).getTableNumber();
0234:
0235:                return super .getTableNumber();
0236:            }
0237:
0238:            /**
0239:             * @see Optimizable#optimizeIt
0240:             *
0241:             * @exception StandardException		Thrown on error
0242:             */
0243:            public CostEstimate optimizeIt(Optimizer optimizer,
0244:                    OptimizablePredicateList predList, CostEstimate outerCost,
0245:                    RowOrdering rowOrdering) throws StandardException {
0246:                /*
0247:                 ** RESOLVE: Most types of Optimizables only implement estimateCost(),
0248:                 ** and leave it up to optimizeIt() in FromTable to figure out the
0249:                 ** total cost of the join.  A ProjectRestrict can have a non-Optimizable
0250:                 ** child, though, in which case we want to tell the child the
0251:                 ** number of outer rows - it could affect the join strategy
0252:                 ** significantly.  So we implement optimizeIt() here, which overrides
0253:                 ** the optimizeIt() in FromTable.  This assumes that the join strategy
0254:                 ** for which this join node is the inner table is a nested loop join,
0255:                 ** which will not be a valid assumption when we implement other
0256:                 ** strategies like materialization (hash join can work only on
0257:                 ** base tables).  The join strategy for a base table under a
0258:                 ** ProjectRestrict is set in the base table itself.
0259:                 */
0260:
0261:                CostEstimate childCost;
0262:
0263:                costEstimate = getCostEstimate(optimizer);
0264:
0265:                /*
0266:                 ** Don't re-optimize a child result set that has already been fully
0267:                 ** optimized.  For example, if the child result set is a SelectNode,
0268:                 ** it will be changed to a ProjectRestrictNode, which we don't want
0269:                 ** to re-optimized.
0270:                 */
0271:                // NOTE: TO GET THE RIGHT COST, THE CHILD RESULT MAY HAVE TO BE
0272:                // OPTIMIZED MORE THAN ONCE, BECAUSE THE NUMBER OF OUTER ROWS
0273:                // MAY BE DIFFERENT EACH TIME.
0274:                // if (childResultOptimized)
0275:                // 	return costEstimate;
0276:                // It's possible that a call to optimize the left/right will cause
0277:                // a new "truly the best" plan to be stored in the underlying base
0278:                // tables.  If that happens and then we decide to skip that plan
0279:                // (which we might do if the call to "considerCost()" below decides
0280:                // the current path is infeasible or not the best) we need to be
0281:                // able to revert back to the "truly the best" plans that we had
0282:                // saved before we got here.  So with this next call we save the
0283:                // current plans using "this" node as the key.  If needed, we'll
0284:                // then make the call to revert the plans in OptimizerImpl's
0285:                // getNextDecoratedPermutation() method.
0286:                updateBestPlanMap(ADD_PLAN, this );
0287:
0288:                /* If the childResult is instanceof Optimizable, then we optimizeIt.
0289:                 * Otherwise, we are going into a new query block.  If the new query
0290:                 * block has already had its access path modified, then there is
0291:                 * nothing to do.  Otherwise, we must begin the optimization process
0292:                 * anew on the new query block.
0293:                 */
0294:                if (childResult instanceof  Optimizable) {
0295:                    childCost = ((Optimizable) childResult).optimizeIt(
0296:                            optimizer, restrictionList, outerCost, rowOrdering);
0297:                    /* Copy child cost to this node's cost */
0298:                    costEstimate.setCost(childCost.getEstimatedCost(),
0299:                            childCost.rowCount(), childCost
0300:                                    .singleScanRowCount());
0301:
0302:                    // Note: we don't call "optimizer.considerCost()" here because
0303:                    // a) the child will make that call as part of its own
0304:                    // "optimizeIt()" work above, and b) the child might have
0305:                    // different criteria for "considering" (i.e. rejecting or
0306:                    // accepting) a plan's cost than this ProjectRestrictNode does--
0307:                    // and we don't want to override the child's decision.  So as
0308:                    // with most operations in this class, if the child is an
0309:                    // Optimizable, we just let it do its own work and make its
0310:                    // own decisions.
0311:                } else if (!accessPathModified) {
0312:                    if (SanityManager.DEBUG) {
0313:                        if (!((childResult instanceof  SelectNode) || (childResult instanceof  RowResultSetNode))) {
0314:                            SanityManager
0315:                                    .THROWASSERT("childResult is expected to be instanceof "
0316:                                            + "SelectNode or RowResultSetNode - it is a "
0317:                                            + childResult.getClass().getName());
0318:                        }
0319:                    }
0320:                    childResult = childResult.optimize(optimizer
0321:                            .getDataDictionary(), restrictionList, outerCost
0322:                            .rowCount());
0323:
0324:                    /* Copy child cost to this node's cost */
0325:                    childCost = childResult.costEstimate;
0326:
0327:                    costEstimate.setCost(childCost.getEstimatedCost(),
0328:                            childCost.rowCount(), childCost
0329:                                    .singleScanRowCount());
0330:
0331:                    /* Note: Prior to the fix for DERBY-781 we had calls here
0332:                     * to set the cost estimate for BestAccessPath and
0333:                     * BestSortAvoidancePath to equal costEstimate.  That used
0334:                     * to be okay because prior to DERBY-781 we would only
0335:                     * get here once (per join order) for a given SelectNode/
0336:                     * RowResultSetNode and thus we could safely say that the
0337:                     * costEstimate from the most recent call to "optimize()"
0338:                     * was the best one so far (because we knew that we would
0339:                     * only call childResult.optimize() once).  Now that we
0340:                     * support hash joins with subqueries, though, we can get
0341:                     * here twice per join order: once when the optimizer is
0342:                     * considering a nested loop join with this PRN, and once
0343:                     * when it is considering a hash join.  This means we can't
0344:                     * just arbitrarily use the cost estimate for the most recent
0345:                     * "optimize()" as the best cost because that may not
0346:                     * be accurate--it's possible that the above call to
0347:                     * childResult.optimize() was for a hash join, but that
0348:                     * we were here once before (namely for nested loop) and
0349:                     * the cost of the nested loop is actually less than
0350:                     * the cost of the hash join.  In that case it would
0351:                     * be wrong to use costEstimate as the cost of the "best"
0352:                     * paths because it (costEstimate) holds the cost of
0353:                     * the hash join, not of the nested loop join.  So with
0354:                     * DERBY-781 the following calls were removed:
0355:                     *   getBestAccessPath().setCostEstimate(costEstimate);
0356:                     *   getBestSortAvoidancePath().setCostEstimate(costEstimate);
0357:                     * If costEstimate *does* actually hold the estimate for
0358:                     * the best path so far, then we will set BestAccessPath
0359:                     * and BestSortAvoidancePath as needed in the following
0360:                     * call to "considerCost".
0361:                     */
0362:
0363:                    // childResultOptimized = true;
0364:                    /* RESOLVE - ARBITRARYHASHJOIN - Passing restriction list here, as above, is correct.
0365:                     * However,  passing predList makes the following work:
0366:                     *	select * from t1, (select * from t2) c properties joinStrategy = hash where t1.c1 = c.c1;
0367:                     * The following works with restrictionList:
0368:                     *	select * from t1, (select c1 + 0 from t2) c(c1) properties joinStrategy = hash where t1.c1 = c.c1;
0369:                     */
0370:                    optimizer.considerCost(this , restrictionList,
0371:                            getCostEstimate(), outerCost);
0372:                }
0373:
0374:                return costEstimate;
0375:            }
0376:
0377:            /**
0378:             * @see Optimizable#feasibleJoinStrategy
0379:             *
0380:             * @exception StandardException		Thrown on error
0381:             */
0382:            public boolean feasibleJoinStrategy(
0383:                    OptimizablePredicateList predList, Optimizer optimizer)
0384:                    throws StandardException {
0385:                AccessPath ap;
0386:
0387:                /* The child being an Optimizable is a special case.  In that
0388:                 * case, we want to get the current access path and join strategy
0389:                 * from the child.  Otherwise, we want to get it from this node.
0390:                 */
0391:                if (childResult instanceof  Optimizable) {
0392:                    // With DERBY-805 it's possible that, when considering a nested
0393:                    // loop join with this PRN, we pushed predicates down into the
0394:                    // child if the child is a UNION node.  At this point, though, we
0395:                    // may be considering doing a hash join with this PRN instead of a
0396:                    // nested loop join, and if that's the case we need to pull any
0397:                    // predicates back up so that they can be searched for equijoins
0398:                    // that will in turn make the hash join possible.  So that's what
0399:                    // the next call does.  Two things to note: 1) if no predicates
0400:                    // were pushed, this call is a no-op; and 2) if we get here when
0401:                    // considering a nested loop join, the predicates that we pull
0402:                    // here (if any) will be re-pushed for subsequent costing/ 
0403:                    // optimization as necessary (see OptimizerImpl.costPermutation(),
0404:                    // which will call this class's optimizeIt() method and that's
0405:                    // where the predicates are pushed down again).
0406:                    if (childResult instanceof  UnionNode)
0407:                        ((UnionNode) childResult)
0408:                                .pullOptPredicates(restrictionList);
0409:
0410:                    return ((Optimizable) childResult).feasibleJoinStrategy(
0411:                            restrictionList, optimizer);
0412:                } else {
0413:                    return super .feasibleJoinStrategy(restrictionList,
0414:                            optimizer);
0415:                }
0416:            }
0417:
0418:            /** @see Optimizable#getCurrentAccessPath */
0419:            public AccessPath getCurrentAccessPath() {
0420:                if (childResult instanceof  Optimizable)
0421:                    return ((Optimizable) childResult).getCurrentAccessPath();
0422:
0423:                return super .getCurrentAccessPath();
0424:            }
0425:
0426:            /** @see Optimizable#getBestAccessPath */
0427:            public AccessPath getBestAccessPath() {
0428:                if (childResult instanceof  Optimizable)
0429:                    return ((Optimizable) childResult).getBestAccessPath();
0430:
0431:                return super .getBestAccessPath();
0432:            }
0433:
0434:            /** @see Optimizable#getBestSortAvoidancePath */
0435:            public AccessPath getBestSortAvoidancePath() {
0436:                if (childResult instanceof  Optimizable)
0437:                    return ((Optimizable) childResult)
0438:                            .getBestSortAvoidancePath();
0439:
0440:                return super .getBestSortAvoidancePath();
0441:            }
0442:
0443:            /** @see Optimizable#getTrulyTheBestAccessPath */
0444:            public AccessPath getTrulyTheBestAccessPath() {
0445:                /* The childResult will always be an Optimizable
0446:                 * during code generation.  If the childResult was
0447:                 * not an Optimizable during optimization, then this node
0448:                 * will have the truly the best access path, so we want to
0449:                 * return it from this node, rather than traversing the tree.
0450:                 * This can happen for non-flattenable derived tables.
0451:                 * Anyway, we note this state when modifying the access paths.
0452:                 */
0453:                if (hasTrulyTheBestAccessPath) {
0454:                    return super .getTrulyTheBestAccessPath();
0455:                }
0456:
0457:                if (childResult instanceof  Optimizable)
0458:                    return ((Optimizable) childResult)
0459:                            .getTrulyTheBestAccessPath();
0460:
0461:                return super .getTrulyTheBestAccessPath();
0462:            }
0463:
0464:            /** @see Optimizable#rememberSortAvoidancePath */
0465:            public void rememberSortAvoidancePath() {
0466:                if (childResult instanceof  Optimizable)
0467:                    ((Optimizable) childResult).rememberSortAvoidancePath();
0468:                else
0469:                    super .rememberSortAvoidancePath();
0470:            }
0471:
0472:            /** @see Optimizable#considerSortAvoidancePath */
0473:            public boolean considerSortAvoidancePath() {
0474:                if (childResult instanceof  Optimizable)
0475:                    return ((Optimizable) childResult)
0476:                            .considerSortAvoidancePath();
0477:
0478:                return super .considerSortAvoidancePath();
0479:            }
0480:
0481:            /**
0482:             * @see Optimizable#pushOptPredicate
0483:             *
0484:             * @exception StandardException		Thrown on error
0485:             */
0486:
0487:            public boolean pushOptPredicate(
0488:                    OptimizablePredicate optimizablePredicate)
0489:                    throws StandardException {
0490:                if (SanityManager.DEBUG) {
0491:                    SanityManager
0492:                            .ASSERT(optimizablePredicate instanceof  Predicate,
0493:                                    "optimizablePredicate expected to be instanceof Predicate");
0494:                    SanityManager
0495:                            .ASSERT(!optimizablePredicate.hasSubquery()
0496:                                    && !optimizablePredicate.hasMethodCall(),
0497:                                    "optimizablePredicate either has a subquery or a method call");
0498:                }
0499:
0500:                /* Add the matching predicate to the restrictionList */
0501:                if (restrictionList == null) {
0502:                    restrictionList = (PredicateList) getNodeFactory().getNode(
0503:                            C_NodeTypes.PREDICATE_LIST, getContextManager());
0504:                }
0505:                restrictionList.addPredicate((Predicate) optimizablePredicate);
0506:
0507:                /* Remap all of the ColumnReferences to point to the
0508:                 * source of the values.
0509:                 */
0510:                Predicate pred = (Predicate) optimizablePredicate;
0511:
0512:                /* If the predicate is scoped then the call to "remapScopedPred()"
0513:                 * will do the necessary remapping for us and will return true;
0514:                 * otherwise, we'll just do the normal remapping here.
0515:                 */
0516:                if (!pred.remapScopedPred()) {
0517:                    RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
0518:                    pred.getAndNode().accept(rcrv);
0519:                }
0520:
0521:                return true;
0522:            }
0523:
0524:            /**
0525:             * @see Optimizable#pullOptPredicates
0526:             *
0527:             * @exception StandardException		Thrown on error
0528:             */
0529:            public void pullOptPredicates(
0530:                    OptimizablePredicateList optimizablePredicates)
0531:                    throws StandardException {
0532:                if (restrictionList != null) {
0533:                    // Pull up any predicates that may have been pushed further
0534:                    // down the tree during optimization.
0535:                    if (childResult instanceof  UnionNode)
0536:                        ((UnionNode) childResult)
0537:                                .pullOptPredicates(restrictionList);
0538:
0539:                    RemapCRsVisitor rcrv = new RemapCRsVisitor(false);
0540:                    for (int i = restrictionList.size() - 1; i >= 0; i--) {
0541:                        OptimizablePredicate optPred = restrictionList
0542:                                .getOptPredicate(i);
0543:                        ((Predicate) optPred).getAndNode().accept(rcrv);
0544:                        optimizablePredicates.addOptPredicate(optPred);
0545:                        restrictionList.removeOptPredicate(i);
0546:                    }
0547:                }
0548:            }
0549:
0550:            /**
0551:             * @see Optimizable#modifyAccessPath
0552:             *
0553:             * @exception StandardException		Thrown on error
0554:             */
0555:            public Optimizable modifyAccessPath(JBitSet outerTables)
0556:                    throws StandardException {
0557:                boolean origChildOptimizable = true;
0558:
0559:                /* It is okay to optimize most nodes multiple times.  However,
0560:                 * modifying the access path is something that should only be done
0561:                 * once per node.  One reason for this is that the predicate list
0562:                 * will be empty after the 1st call, and we assert that it should
0563:                 * be non-empty.  Multiple calls to modify the access path can
0564:                 * occur when there is a non-flattenable FromSubquery (or view).
0565:                 */
0566:                if (accessPathModified) {
0567:                    return this ;
0568:                }
0569:
0570:                /*
0571:                 ** Do nothing if the child result set is not optimizable, as there
0572:                 ** can be nothing to modify.
0573:                 */
0574:                boolean alreadyPushed = false;
0575:                if (!(childResult instanceof  Optimizable)) {
0576:                    // Remember that the original child was not Optimizable
0577:                    origChildOptimizable = false;
0578:
0579:                    /* When we optimized the child we passed in our restriction list
0580:                     * so that scoped predicates could be pushed further down the
0581:                     * tree.  We need to do the same when modifying the access
0582:                     * paths to ensure we generate the same plans the optimizer
0583:                     * chose.
0584:                     */
0585:                    childResult = childResult
0586:                            .modifyAccessPaths(restrictionList);
0587:
0588:                    /* Mark this node as having the truly ... for
0589:                     * the underlying tree.
0590:                     */
0591:                    hasTrulyTheBestAccessPath = true;
0592:
0593:                    /* Replace this PRN with a HRN if we are doing a hash join */
0594:                    if (trulyTheBestAccessPath.getJoinStrategy().isHashJoin()) {
0595:                        if (SanityManager.DEBUG) {
0596:                            SanityManager.ASSERT(restrictionList != null,
0597:                                    "restrictionList expected to be non-null");
0598:                            SanityManager
0599:                                    .ASSERT(restrictionList.size() != 0,
0600:                                            "restrictionList.size() expected to be non-zero");
0601:                        }
0602:                        /* We're doing a hash join on an arbitary result set.
0603:                         * We need to get the table number from this node when
0604:                         * dividing up the restriction list for a hash join.
0605:                         * We need to explicitly remember this.
0606:                         */
0607:                        getTableNumberHere = true;
0608:                    } else {
0609:                        /* We consider materialization into a temp table as a last step.
0610:                         * Currently, we only materialize VTIs that are inner tables
0611:                         * and can't be instantiated multiple times.  In the future we
0612:                         * will consider materialization as a cost based option.
0613:                         */
0614:                        return (Optimizable) considerMaterialization(outerTables);
0615:                    }
0616:                }
0617:
0618:                /* If the child is not a FromBaseTable, then we want to
0619:                 * keep going down the tree.  (Nothing to do at this node.)
0620:                 */
0621:                else if (!(childResult instanceof  FromBaseTable)) {
0622:                    /* Make sure that we have a join strategy */
0623:                    if (trulyTheBestAccessPath.getJoinStrategy() == null) {
0624:                        trulyTheBestAccessPath = (AccessPathImpl) ((Optimizable) childResult)
0625:                                .getTrulyTheBestAccessPath();
0626:                    }
0627:
0628:                    // If the childResult is a SetOperatorNode (esp. a UnionNode),
0629:                    // then it's possible that predicates in our restrictionList are
0630:                    // supposed to be pushed further down the tree (as of DERBY-805).
0631:                    // We passed the restrictionList down when we optimized the child
0632:                    // so that the relevant predicates could be pushed further as part
0633:                    // of the optimization process; so now that we're finalizing the
0634:                    // paths, we need to do the same thing: i.e. pass restrictionList
0635:                    // down so that the predicates that need to be pushed further
0636:                    // _can_ be pushed further.
0637:                    if (childResult instanceof  SetOperatorNode) {
0638:                        childResult = (ResultSetNode) ((SetOperatorNode) childResult)
0639:                                .modifyAccessPath(outerTables, restrictionList);
0640:
0641:                        // Take note of the fact that we already pushed predicates
0642:                        // as part of the modifyAccessPaths call.  This is necessary
0643:                        // because there may still be predicates in restrictionList
0644:                        // that we intentionally decided not to push (ex. if we're
0645:                        // going to do hash join then we chose to not push the join
0646:                        // predicates).  Whatever the reason for not pushing the
0647:                        // predicates, we have to make sure we don't inadvertenly
0648:                        // push them later (esp. as part of the "pushUsefulPredicates"
0649:                        // call below).
0650:                        alreadyPushed = true;
0651:                    } else {
0652:                        childResult = (ResultSetNode) ((FromTable) childResult)
0653:                                .modifyAccessPath(outerTables);
0654:                    }
0655:                }
0656:
0657:                // If we're doing a hash join with _this_ PRN (as opposed to
0658:                // with this PRN's child) then we don't attempt to push
0659:                // predicates down.  There are two reasons for this: 1)
0660:                // we don't want to push the equijoin predicate that is
0661:                // required for the hash join, and 2) if we're doing a
0662:                // hash join then we're going to materialize this node,
0663:                // but if we push predicates before materialization, we
0664:                // can end up with incorrect results (esp. missing rows).
0665:                // So don't push anything in this case.
0666:                boolean hashJoinWithThisPRN = hasTrulyTheBestAccessPath
0667:                        && (trulyTheBestAccessPath.getJoinStrategy() != null)
0668:                        && trulyTheBestAccessPath.getJoinStrategy()
0669:                                .isHashJoin();
0670:
0671:                if ((restrictionList != null) && !alreadyPushed
0672:                        && !hashJoinWithThisPRN) {
0673:                    restrictionList
0674:                            .pushUsefulPredicates((Optimizable) childResult);
0675:                }
0676:
0677:                /*
0678:                 ** The optimizer's decision on the access path for the child result
0679:                 ** set may require the generation of extra result sets.  For
0680:                 ** example, if it chooses an index, we need an IndexToBaseRowNode
0681:                 ** above the FromBaseTable (and the FromBaseTable has to change
0682:                 ** its column list to match that of the index.
0683:                 */
0684:                if (origChildOptimizable) {
0685:                    childResult = childResult.changeAccessPath();
0686:                }
0687:                accessPathModified = true;
0688:
0689:                /*
0690:                 ** Replace this PRN with a HTN if a hash join
0691:                 ** is being done at this node.  (Hash join on a scan
0692:                 ** is a special case and is handled at the FBT.)
0693:                 */
0694:                if (trulyTheBestAccessPath.getJoinStrategy() != null
0695:                        && trulyTheBestAccessPath.getJoinStrategy()
0696:                                .isHashJoin()) {
0697:                    return replaceWithHashTableNode();
0698:                }
0699:
0700:                /* We consider materialization into a temp table as a last step.
0701:                 * Currently, we only materialize VTIs that are inner tables
0702:                 * and can't be instantiated multiple times.  In the future we
0703:                 * will consider materialization as a cost based option.
0704:                 */
0705:                return (Optimizable) considerMaterialization(outerTables);
0706:            }
0707:
0708:            /**
0709:             * This method creates a HashTableNode between the PRN and
0710:             * it's child when the optimizer chooses hash join on an
0711:             * arbitrary (non-FBT) result set tree.
0712:             * We divide up the restriction list into 3 parts and
0713:             * distribute those parts as described below.
0714:             * 
0715:             * @return The new (same) top of our result set tree.
0716:             * @exception StandardException		Thrown on error
0717:             */
0718:            private Optimizable replaceWithHashTableNode()
0719:                    throws StandardException {
0720:                // If this PRN has TTB access path for its child, store that access
0721:                // path in the child here, so that we can find it later when it
0722:                // comes time to generate qualifiers for the hash predicates (we
0723:                // need the child's access path when generating qualifiers; if we
0724:                // don't pass the path down here, the child won't be able to find
0725:                // it).
0726:                if (hasTrulyTheBestAccessPath) {
0727:                    ((FromTable) childResult).trulyTheBestAccessPath = (AccessPathImpl) getTrulyTheBestAccessPath();
0728:
0729:                    // If the child itself is another SingleChildResultSetNode
0730:                    // (which is also what a ProjectRestrictNode is), then tell
0731:                    // it that it is now holding TTB path for it's own child.  Again,
0732:                    // this info is needed so that child knows where to find the
0733:                    // access path at generation time.
0734:                    if (childResult instanceof  SingleChildResultSetNode) {
0735:                        ((SingleChildResultSetNode) childResult).hasTrulyTheBestAccessPath = hasTrulyTheBestAccessPath;
0736:
0737:                        // While we're at it, add the PRN's table number to the
0738:                        // child's referenced map so that we can find the equijoin
0739:                        // predicate.  We have to do this because the predicate
0740:                        // will be referencing the PRN's tableNumber, not the
0741:                        // child's--and since we use the child as the target
0742:                        // when searching for hash keys (as can be seen in
0743:                        // HashJoinStrategy.divideUpPredicateLists()), the child
0744:                        // should know what this PRN's table number is.  This
0745:                        // is somewhat bizarre since the child doesn't
0746:                        // actually "reference" this PRN, but since the child's
0747:                        // reference map is used when searching for the equijoin
0748:                        // predicate (see "buildTableNumList" in
0749:                        // BinaryRelationalOperatorNode), this is the simplest
0750:                        // way to pass this PRN's table number down.
0751:                        childResult.getReferencedTableMap().set(tableNumber);
0752:                    }
0753:                }
0754:
0755:                /* We want to divide the predicate list into 3 separate lists -
0756:                 *	o predicates against the source of the hash table, which will
0757:                 *	  be applied on the way into the hash table (searchRestrictionList)
0758:                 *  o join clauses which are qualifiers and get applied to the
0759:                 *	  rows in the hash table on a probe (joinRestrictionList)
0760:                 *	o non-qualifiers involving both tables which will get
0761:                 *	  applied after a row gets returned from the HTRS (nonQualifiers)
0762:                 *
0763:                 * We do some unnecessary work when doing this as we want to reuse
0764:                 * as much existing code as possible.  The code that we are reusing
0765:                 * was originally built for hash scans, hence the unnecessary
0766:                 * requalification list.
0767:                 */
0768:                PredicateList searchRestrictionList = (PredicateList) getNodeFactory()
0769:                        .getNode(C_NodeTypes.PREDICATE_LIST,
0770:                                getContextManager());
0771:                PredicateList joinQualifierList = (PredicateList) getNodeFactory()
0772:                        .getNode(C_NodeTypes.PREDICATE_LIST,
0773:                                getContextManager());
0774:                PredicateList requalificationRestrictionList = (PredicateList) getNodeFactory()
0775:                        .getNode(C_NodeTypes.PREDICATE_LIST,
0776:                                getContextManager());
0777:                trulyTheBestAccessPath.getJoinStrategy()
0778:                        .divideUpPredicateLists(this , restrictionList,
0779:                                searchRestrictionList, joinQualifierList,
0780:                                requalificationRestrictionList,
0781:                                getDataDictionary());
0782:
0783:                /* Break out the non-qualifiers from HTN's join qualifier list and make that
0784:                 * the new restriction list for this PRN.
0785:                 */
0786:                restrictionList = (PredicateList) getNodeFactory().getNode(
0787:                        C_NodeTypes.PREDICATE_LIST, getContextManager());
0788:                /* For non-base table, we remove first 2 lists from requal list to avoid adding duplicates.
0789:                 */
0790:                for (int i = 0; i < searchRestrictionList.size(); i++)
0791:                    requalificationRestrictionList
0792:                            .removeOptPredicate((Predicate) searchRestrictionList
0793:                                    .elementAt(i));
0794:                for (int i = 0; i < joinQualifierList.size(); i++)
0795:                    requalificationRestrictionList
0796:                            .removeOptPredicate((Predicate) joinQualifierList
0797:                                    .elementAt(i));
0798:
0799:                joinQualifierList.transferNonQualifiers(this , restrictionList); //purify joinQual list
0800:                requalificationRestrictionList
0801:                        .copyPredicatesToOtherList(restrictionList); //any residual
0802:
0803:                ResultColumnList htRCList;
0804:
0805:                /* We get a shallow copy of the child's ResultColumnList and its 
0806:                 * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
0807:                 */
0808:                htRCList = childResult.getResultColumns();
0809:                childResult.setResultColumns(htRCList.copyListAndObjects());
0810:
0811:                /* Replace ResultColumn.expression with new VirtualColumnNodes
0812:                 * in the HTN's ResultColumnList.  (VirtualColumnNodes include
0813:                 * pointers to source ResultSetNode, this, and source ResultColumn.)
0814:                 * NOTE: We don't want to mark the underlying RCs as referenced, otherwise
0815:                 * we won't be able to project out any of them.
0816:                 */
0817:                htRCList.genVirtualColumnNodes(childResult, childResult
0818:                        .getResultColumns(), false);
0819:
0820:                /* The CRs for this side of the join in both the searchRestrictionList
0821:                 * the joinQualifierList now point to the HTN's RCL.  We need them
0822:                 * to point to the RCL in the child of the HTN.  (We skip doing this for
0823:                 * the joinQualifierList as the code to generate the Qualifiers does not
0824:                 * care.)
0825:                 */
0826:                RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
0827:                searchRestrictionList.accept(rcrv);
0828:
0829:                /* We can finally put the HTN between ourself and our old child. */
0830:                childResult = (ResultSetNode) getNodeFactory().getNode(
0831:                        C_NodeTypes.HASH_TABLE_NODE, childResult,
0832:                        tableProperties, htRCList, searchRestrictionList,
0833:                        joinQualifierList, trulyTheBestAccessPath,
0834:                        getCostEstimate(), projectSubquerys, restrictSubquerys,
0835:                        hashKeyColumns(), getContextManager());
0836:                return this ;
0837:            }
0838:
0839:            /** @see Optimizable#verifyProperties 
0840:             * @exception StandardException		Thrown on error
0841:             */
0842:            public void verifyProperties(DataDictionary dDictionary)
0843:                    throws StandardException {
0844:                /* Table properties can be attached to this node if
0845:                 * its child is not an optimizable, otherwise they
0846:                 * are attached to its child.
0847:                 */
0848:
0849:                if (childResult instanceof  Optimizable) {
0850:                    ((Optimizable) childResult).verifyProperties(dDictionary);
0851:                } else {
0852:                    super .verifyProperties(dDictionary);
0853:                }
0854:            }
0855:
0856:            /**
0857:             * @see Optimizable#legalJoinOrder
0858:             */
0859:            public boolean legalJoinOrder(JBitSet assignedTableMap) {
0860:                if (childResult instanceof  Optimizable) {
0861:                    return ((Optimizable) childResult)
0862:                            .legalJoinOrder(assignedTableMap);
0863:                } else {
0864:                    return true;
0865:                }
0866:            }
0867:
0868:            /**
0869:             * @see Optimizable#uniqueJoin
0870:             *
0871:             * @exception StandardException		Thrown on error
0872:             */
0873:            public double uniqueJoin(OptimizablePredicateList predList)
0874:                    throws StandardException {
0875:                if (childResult instanceof  Optimizable) {
0876:                    return ((Optimizable) childResult).uniqueJoin(predList);
0877:                } else {
0878:                    return super .uniqueJoin(predList);
0879:                }
0880:            }
0881:
0882:            /**
0883:             * Return the restriction list from this node.
0884:             *
0885:             * @return	The restriction list from this node.
0886:             */
0887:            PredicateList getRestrictionList() {
0888:                return restrictionList;
0889:            }
0890:
0891:            /** 
0892:             * Return the user specified join strategy, if any for this table.
0893:             *
0894:             * @return The user specified join strategy, if any for this table.
0895:             */
0896:            String getUserSpecifiedJoinStrategy() {
0897:                if (childResult instanceof  FromTable) {
0898:                    return ((FromTable) childResult)
0899:                            .getUserSpecifiedJoinStrategy();
0900:                } else {
0901:                    return userSpecifiedJoinStrategy;
0902:                }
0903:            }
0904:
0905:            /**
0906:             * Prints the sub-nodes of this object.  See QueryTreeNode.java for
0907:             * how tree printing is supposed to work.
0908:             *
0909:             * @param depth		The depth of this node in the tree
0910:             */
0911:
0912:            public void printSubNodes(int depth) {
0913:                if (SanityManager.DEBUG) {
0914:                    super .printSubNodes(depth);
0915:
0916:                    if (restriction != null) {
0917:                        printLabel(depth, "restriction: ");
0918:                        restriction.treePrint(depth + 1);
0919:                    }
0920:
0921:                    if (restrictionList != null) {
0922:                        printLabel(depth, "restrictionList: ");
0923:                        restrictionList.treePrint(depth + 1);
0924:                    }
0925:
0926:                    if (projectSubquerys != null) {
0927:                        printLabel(depth, "projectSubquerys: ");
0928:                        projectSubquerys.treePrint(depth + 1);
0929:                    }
0930:
0931:                    if (restrictSubquerys != null) {
0932:                        printLabel(depth, "restrictSubquerys: ");
0933:                        restrictSubquerys.treePrint(depth + 1);
0934:                    }
0935:                }
0936:            }
0937:
0938:            /** 
0939:             * Put a ProjectRestrictNode on top of each FromTable in the FromList.
0940:             * ColumnReferences must continue to point to the same ResultColumn, so
0941:             * that ResultColumn must percolate up to the new PRN.  However,
0942:             * that ResultColumn will point to a new expression, a VirtualColumnNode, 
0943:             * which points to the FromTable and the ResultColumn that is the source for
0944:             * the ColumnReference.  
0945:             * (The new PRN will have the original of the ResultColumnList and
0946:             * the ResultColumns from that list.  The FromTable will get shallow copies
0947:             * of the ResultColumnList and its ResultColumns.  ResultColumn.expression
0948:             * will remain at the FromTable, with the PRN getting a new 
0949:             * VirtualColumnNode for each ResultColumn.expression.)
0950:             * We then project out the non-referenced columns.  If there are no referenced
0951:             * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
0952:             * whose expression is 1.
0953:             *
0954:             * @param numTables			Number of tables in the DML Statement
0955:             * @param gbl				The group by list, if any
0956:             * @param fromList			The from list, if any
0957:             *
0958:             * @return The generated ProjectRestrictNode atop the original FromTable.
0959:             *
0960:             * @exception StandardException		Thrown on error
0961:             */
0962:
0963:            public ResultSetNode preprocess(int numTables, GroupByList gbl,
0964:                    FromList fromList) throws StandardException {
0965:                childResult = childResult.preprocess(numTables, gbl, fromList);
0966:
0967:                /* Build the referenced table map */
0968:                referencedTableMap = (JBitSet) childResult
0969:                        .getReferencedTableMap().clone();
0970:
0971:                return this ;
0972:            }
0973:
0974:            /**
0975:             * Push expressions down to the first ResultSetNode which can do expression
0976:             * evaluation and has the same referenced table map.
0977:             * RESOLVE - This means only pushing down single table expressions to
0978:             * ProjectRestrictNodes today.  Once we have a better understanding of how
0979:             * the optimizer will work, we can push down join clauses.
0980:             *
0981:             * @param predicateList	The PredicateList.
0982:             *
0983:             * @exception StandardException		Thrown on error
0984:             */
0985:            public void pushExpressions(PredicateList predicateList)
0986:                    throws StandardException {
0987:                PredicateList pushPList = null;
0988:
0989:                if (SanityManager.DEBUG)
0990:                    SanityManager.ASSERT(predicateList != null,
0991:                            "predicateList is expected to be non-null");
0992:
0993:                /* Push single table predicates down to the left of an outer
0994:                 * join, if possible.  (We need to be able to walk an entire
0995:                 * join tree.)
0996:                 */
0997:                if (childResult instanceof  JoinNode) {
0998:                    ((FromTable) childResult).pushExpressions(predicateList);
0999:
1000:                }
1001:
1002:                /* Build a list of the single table predicates that we can push down */
1003:                pushPList = predicateList
1004:                        .getPushablePredicates(referencedTableMap);
1005:
1006:                /* If this is a PRN above a SelectNode, probably due to a 
1007:                 * view or derived table which couldn't be flattened, then see
1008:                 * if we can push any of the predicates which just got pushed
1009:                 * down to our level into the SelectNode.
1010:                 */
1011:                if (pushPList != null && (childResult instanceof  SelectNode)) {
1012:                    pushPList.pushExpressionsIntoSelect(
1013:                            (SelectNode) childResult, false);
1014:                }
1015:
1016:                /* DERBY-649: Push simple predicates into Unions. It would be up to UnionNode
1017:                 * to decide if these predicates can be pushed further into underlying SelectNodes
1018:                 * or UnionNodes.  Note, we also keep the predicateList at this
1019:                 * ProjectRestrictNode in case the predicates are not pushable or only
1020:                 * partially pushable.
1021:                 *
1022:                 * It is possible to expand this optimization in UnionNode later.
1023:                 */
1024:                if (pushPList != null && (childResult instanceof  UnionNode))
1025:                    ((UnionNode) childResult).pushExpressions(pushPList);
1026:
1027:                if (restrictionList == null) {
1028:                    restrictionList = pushPList;
1029:                } else if (pushPList != null && pushPList.size() != 0) {
1030:                    /* Concatenate the 2 PredicateLists */
1031:                    restrictionList.destructiveAppend(pushPList);
1032:                }
1033:
1034:                /* RESOLVE - this looks like the place to try to try to push the 
1035:                 * predicates through the ProjectRestrict.  Seems like we should
1036:                 * "rebind" the column references and reset the referenced table maps
1037:                 * in restrictionList and then call childResult.pushExpressions() on
1038:                 * restrictionList.
1039:                 */
1040:            }
1041:
1042:            /**
1043:             * Add a new predicate to the list.  This is useful when doing subquery
1044:             * transformations, when we build a new predicate with the left side of
1045:             * the subquery operator and the subquery's result column.
1046:             *
1047:             * @param predicate		The predicate to add
1048:             *
1049:             * @return ResultSetNode	The new top of the tree.
1050:             *
1051:             * @exception StandardException		Thrown on error
1052:             */
1053:            public ResultSetNode addNewPredicate(Predicate predicate)
1054:                    throws StandardException {
1055:                if (restrictionList == null) {
1056:                    restrictionList = (PredicateList) getNodeFactory().getNode(
1057:                            C_NodeTypes.PREDICATE_LIST, getContextManager());
1058:                }
1059:                restrictionList.addPredicate(predicate);
1060:                return this ;
1061:            }
1062:
1063:            /**
1064:             * Evaluate whether or not the subquery in a FromSubquery is flattenable.  
1065:             * Currently, a FSqry is flattenable if all of the following are true:
1066:             *		o  Subquery is a SelectNode. 
1067:             *		o  It contains no top level subqueries.  (RESOLVE - we can relax this)
1068:             *		o  It does not contain a group by or having clause
1069:             *		o  It does not contain aggregates.
1070:             *
1071:             * @param fromList	The outer from list
1072:             *
1073:             * @return boolean	Whether or not the FromSubquery is flattenable.
1074:             */
1075:            public boolean flattenableInFromSubquery(FromList fromList) {
1076:                /* Flattening currently involves merging predicates and FromLists.
1077:                 * We don't have a FromList, so we can't flatten for now.
1078:                 */
1079:                /* RESOLVE - this will introduce yet another unnecessary PRN */
1080:                return false;
1081:            }
1082:
1083:            /**
1084:             * Ensure that the top of the RSN tree has a PredicateList.
1085:             *
1086:             * @param numTables			The number of tables in the query.
1087:             * @return ResultSetNode	A RSN tree with a node which has a PredicateList on top.
1088:             *
1089:             * @exception StandardException		Thrown on error
1090:             */
1091:            public ResultSetNode ensurePredicateList(int numTables)
1092:                    throws StandardException {
1093:                return this ;
1094:            }
1095:
1096:            /**
1097:             * Optimize this ProjectRestrictNode.  
1098:             *
1099:             * @param dataDictionary	The DataDictionary to use for optimization
1100:             * @param predicates		The PredicateList to optimize.  This should
1101:             *							be a join predicate.
1102:             * @param outerRows			The number of outer joining rows
1103:             *
1104:             * @return	ResultSetNode	The top of the optimized subtree
1105:             *
1106:             * @exception StandardException		Thrown on error
1107:             */
1108:
1109:            public ResultSetNode optimize(DataDictionary dataDictionary,
1110:                    PredicateList predicates, double outerRows)
1111:                    throws StandardException {
1112:                /* We need to implement this method since a PRN can appear above a
1113:                 * SelectNode in a query tree.
1114:                 */
1115:                childResult = childResult.optimize(dataDictionary,
1116:                        restrictionList, outerRows);
1117:
1118:                Optimizer optimizer = getOptimizer((FromList) getNodeFactory()
1119:                        .getNode(C_NodeTypes.FROM_LIST,
1120:                                getNodeFactory().doJoinOrderOptimization(),
1121:                                this , getContextManager()), predicates,
1122:                        dataDictionary, (RequiredRowOrdering) null);
1123:
1124:                // RESOLVE: SHOULD FACTOR IN THE NON-OPTIMIZABLE PREDICATES THAT
1125:                // WERE NOT PUSHED DOWN
1126:                costEstimate = optimizer.newCostEstimate();
1127:
1128:                costEstimate.setCost(childResult.getCostEstimate()
1129:                        .getEstimatedCost(), childResult.getCostEstimate()
1130:                        .rowCount(), childResult.getCostEstimate()
1131:                        .singleScanRowCount());
1132:
1133:                return this ;
1134:            }
1135:
1136:            /**
1137:             * Get the CostEstimate for this ProjectRestrictNode.
1138:             *
1139:             * @return	The CostEstimate for this ProjectRestrictNode, which is
1140:             * 			the cost estimate for the child node.
1141:             */
1142:            public CostEstimate getCostEstimate() {
1143:                /*
1144:                 ** The cost estimate will be set here if either optimize() or
1145:                 ** optimizeIt() was called on this node.  It's also possible
1146:                 ** that optimization was done directly on the child node,
1147:                 ** in which case the cost estimate will be null here.
1148:                 */
1149:                if (costEstimate == null)
1150:                    return childResult.getCostEstimate();
1151:                else {
1152:                    return costEstimate;
1153:                }
1154:            }
1155:
1156:            /**
1157:             * Get the final CostEstimate for this ProjectRestrictNode.
1158:             *
1159:             * @return	The final CostEstimate for this ProjectRestrictNode, which is
1160:             * 			the final cost estimate for the child node.
1161:             */
1162:            public CostEstimate getFinalCostEstimate() throws StandardException {
1163:                if (finalCostEstimate != null)
1164:                    // we already set it, so just return it.
1165:                    return finalCostEstimate;
1166:
1167:                // If the child result set is an Optimizable, then this node's
1168:                // final cost is that of the child.  Otherwise, this node must
1169:                // hold "trulyTheBestAccessPath" for it's child so we pull
1170:                // the final cost from there.
1171:                if (childResult instanceof  Optimizable)
1172:                    finalCostEstimate = childResult.getFinalCostEstimate();
1173:                else
1174:                    finalCostEstimate = getTrulyTheBestAccessPath()
1175:                            .getCostEstimate();
1176:
1177:                return finalCostEstimate;
1178:            }
1179:
1180:            /**
1181:             * For joins, the tree will be (nodes are left out if the clauses
1182:             * are empty):
1183:             *
1184:             *      ProjectRestrictResultSet -- for the having and the select list
1185:             *      SortResultSet -- for the group by list
1186:             *      ProjectRestrictResultSet -- for the where and the select list (if no group or having)
1187:             *      the result set for the fromList
1188:             *
1189:             *
1190:             * @exception StandardException		Thrown on error
1191:             */
1192:            public void generate(ActivationClassBuilder acb, MethodBuilder mb)
1193:                    throws StandardException {
1194:                if (SanityManager.DEBUG)
1195:                    SanityManager.ASSERT(resultColumns != null,
1196:                            "Tree structure bad");
1197:
1198:                generateMinion(acb, mb, false);
1199:            }
1200:
1201:            /**
1202:             * General logic shared by Core compilation.
1203:             *
1204:             * @param acb	The ExpressionClassBuilder for the class being built
1205:             * @param mb	The method the expression will go into
1206:             *
1207:             *
1208:             * @exception StandardException		Thrown on error
1209:             */
1210:
1211:            public void generateResultSet(ExpressionClassBuilder acb,
1212:                    MethodBuilder mb) throws StandardException {
1213:                generateMinion(acb, mb, true);
1214:            }
1215:
1216:            /**
1217:             * Logic shared by generate() and generateResultSet().
1218:             *
1219:             * @param acb	The ExpressionClassBuilder for the class being built
1220:             * @param mb	The method the expression will go into
1221:             *
1222:             * @exception StandardException		Thrown on error
1223:             */
1224:
1225:            private void generateMinion(ExpressionClassBuilder acb,
1226:                    MethodBuilder mb, boolean genChildResultSet)
1227:                    throws StandardException {
1228:
1229:                /* If this ProjectRestrict doesn't do anything, bypass its generation.
1230:                 * (Remove any true and true predicates first, as they could be left
1231:                 * by the like transformation.)
1232:                 */
1233:                if (restrictionList != null && restrictionList.size() > 0) {
1234:                    restrictionList.eliminateBooleanTrueAndBooleanTrue();
1235:                }
1236:
1237:                if (nopProjectRestrict()) {
1238:                    generateNOPProjectRestrict();
1239:                    if (genChildResultSet)
1240:                        childResult.generateResultSet(acb, mb);
1241:                    else
1242:                        childResult.generate((ActivationClassBuilder) acb, mb);
1243:                    costEstimate = childResult.getFinalCostEstimate();
1244:                    return;
1245:                }
1246:
1247:                // build up the tree.
1248:
1249:                /* Put the predicates back into the tree */
1250:                if (restrictionList != null) {
1251:                    constantRestriction = restrictionList
1252:                            .restoreConstantPredicates();
1253:                    // Remove any redundant predicates before restoring
1254:                    restrictionList.removeRedundantPredicates();
1255:                    restriction = restrictionList.restorePredicates();
1256:                    /* Allow the restrictionList to get garbage collected now
1257:                     * that we're done with it.
1258:                     */
1259:                    restrictionList = null;
1260:                }
1261:
1262:                // for the restriction, we generate an exprFun
1263:                // that evaluates the expression of the clause
1264:                // against the current row of the child's result.
1265:                // if the restriction is empty, simply pass null
1266:                // to optimize for run time performance.
1267:
1268:                // generate the function and initializer:
1269:                // Note: Boolean lets us return nulls (boolean would not)
1270:                // private Boolean exprN()
1271:                // {
1272:                //   return <<restriction.generate(ps)>>;
1273:                // }
1274:                // static Method exprN = method pointer to exprN;
1275:
1276:                // Map the result columns to the source columns
1277:                int[] mapArray = resultColumns.mapSourceColumns();
1278:                int mapArrayItem = acb
1279:                        .addItem(new ReferencedColumnsDescriptorImpl(mapArray));
1280:
1281:                /* Will this node do a projection? */
1282:                boolean doesProjection = true;
1283:
1284:                /* Does a projection unless same # of columns in same order
1285:                 * as child.
1286:                 */
1287:                if ((!reflectionNeededForProjection())
1288:                        && mapArray != null
1289:                        && mapArray.length == childResult.getResultColumns()
1290:                                .size()) {
1291:                    /* mapArray entries are 1-based */
1292:                    int index = 0;
1293:                    for (; index < mapArray.length; index++) {
1294:                        if (mapArray[index] != index + 1) {
1295:                            break;
1296:                        }
1297:                    }
1298:                    if (index == mapArray.length) {
1299:                        doesProjection = false;
1300:                    }
1301:                }
1302:
1303:                /* Generate the ProjectRestrictSet:
1304:                 *	arg1: childExpress - Expression for childResultSet
1305:                 *  arg2: Activation
1306:                 *  arg3: restrictExpress - Expression for restriction
1307:                 *  arg4: projectExpress - Expression for projection
1308:                 *  arg5: resultSetNumber
1309:                 *  arg6: constantExpress - Expression for constant restriction
1310:                 *			(for example, where 1 = 2)
1311:                 *  arg7: mapArrayItem - item # for mapping of source columns
1312:                 *  arg8: reuseResult - whether or not the result row can be reused
1313:                 *						(ie, will it always be the same)
1314:                 *  arg9: doesProjection - does this node do a projection
1315:                 *  arg10: estimated row count
1316:                 *  arg11: estimated cost
1317:                 *  arg12: close method
1318:                 */
1319:
1320:                acb.pushGetResultSetFactoryExpression(mb);
1321:                if (genChildResultSet)
1322:                    childResult.generateResultSet(acb, mb);
1323:                else
1324:                    childResult.generate((ActivationClassBuilder) acb, mb);
1325:
1326:                /* Get the next ResultSet #, so that we can number this ResultSetNode, its
1327:                 * ResultColumnList and ResultSet.
1328:                 */
1329:                assignResultSetNumber();
1330:
1331:                /* Set the point of attachment in all subqueries attached
1332:                 * to this node.
1333:                 */
1334:                if (projectSubquerys != null && projectSubquerys.size() > 0) {
1335:                    projectSubquerys.setPointOfAttachment(resultSetNumber);
1336:                }
1337:                if (restrictSubquerys != null && restrictSubquerys.size() > 0) {
1338:                    restrictSubquerys.setPointOfAttachment(resultSetNumber);
1339:                }
1340:
1341:                // Load our final cost estimate.
1342:                costEstimate = getFinalCostEstimate();
1343:
1344:                // if there is no restriction, we just want to pass null.
1345:                if (restriction == null) {
1346:                    mb.pushNull(ClassName.GeneratedMethod);
1347:                } else {
1348:                    // this sets up the method and the static field.
1349:                    // generates:
1350:                    // 	Object userExprFun { }
1351:                    MethodBuilder userExprFun = acb.newUserExprFun();
1352:
1353:                    // restriction knows it is returning its value;
1354:
1355:                    /* generates:
1356:                     *    return  <restriction.generate(acb)>;
1357:                     * and adds it to userExprFun
1358:                     * NOTE: The explicit cast to DataValueDescriptor is required
1359:                     * since the restriction may simply be a boolean column or subquery
1360:                     * which returns a boolean.  For example:
1361:                     *		where booleanColumn
1362:                     */
1363:                    restriction.generateExpression(acb, userExprFun);
1364:                    userExprFun.methodReturn();
1365:
1366:                    // we are done modifying userExprFun, complete it.
1367:                    userExprFun.complete();
1368:
1369:                    // restriction is used in the final result set as an access of the new static
1370:                    // field holding a reference to this new method.
1371:                    // generates:
1372:                    //	ActivationClass.userExprFun
1373:                    // which is the static field that "points" to the userExprFun
1374:                    // that evaluates the where clause.
1375:                    acb.pushMethodReference(mb, userExprFun);
1376:                }
1377:
1378:                /* Determine whether or not reflection is needed for the projection.
1379:                 * Reflection is not needed if all of the columns map directly to source
1380:                 * columns.
1381:                 */
1382:                if (reflectionNeededForProjection()) {
1383:                    // for the resultColumns, we generate a userExprFun
1384:                    // that creates a new row from expressions against
1385:                    // the current row of the child's result.
1386:                    // (Generate optimization: see if we can simply
1387:                    // return the current row -- we could, but don't, optimize
1388:                    // the function call out and have execution understand
1389:                    // that a null function pointer means take the current row
1390:                    // as-is, with the performance trade-off as discussed above.)
1391:
1392:                    /* Generate the Row function for the projection */
1393:                    resultColumns.generateCore(acb, mb, false);
1394:                } else {
1395:                    mb.pushNull(ClassName.GeneratedMethod);
1396:                }
1397:
1398:                mb.push(resultSetNumber);
1399:
1400:                // if there is no constant restriction, we just want to pass null.
1401:                if (constantRestriction == null) {
1402:                    mb.pushNull(ClassName.GeneratedMethod);
1403:                } else {
1404:                    // this sets up the method and the static field.
1405:                    // generates:
1406:                    // 	userExprFun { }
1407:                    MethodBuilder userExprFun = acb.newUserExprFun();
1408:
1409:                    // restriction knows it is returning its value;
1410:
1411:                    /* generates:
1412:                     *    return <restriction.generate(acb)>;
1413:                     * and adds it to userExprFun
1414:                     * NOTE: The explicit cast to DataValueDescriptor is required
1415:                     * since the restriction may simply be a boolean column or subquery
1416:                     * which returns a boolean.  For example:
1417:                     *		where booleanColumn
1418:                     */
1419:                    constantRestriction.generateExpression(acb, userExprFun);
1420:
1421:                    userExprFun.methodReturn();
1422:
1423:                    // we are done modifying userExprFun, complete it.
1424:                    userExprFun.complete();
1425:
1426:                    // restriction is used in the final result set as an access
1427:                    // of the new static field holding a reference to this new method.
1428:                    // generates:
1429:                    //	ActivationClass.userExprFun
1430:                    // which is the static field that "points" to the userExprFun
1431:                    // that evaluates the where clause.
1432:                    acb.pushMethodReference(mb, userExprFun);
1433:                }
1434:
1435:                mb.push(mapArrayItem);
1436:                mb.push(resultColumns.reusableResult());
1437:                mb.push(doesProjection);
1438:                mb.push(costEstimate.rowCount());
1439:                mb.push(costEstimate.getEstimatedCost());
1440:
1441:                mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
1442:                        "getProjectRestrictResultSet",
1443:                        ClassName.NoPutResultSet, 10);
1444:            }
1445:
1446:            /**
1447:             * Determine whether this ProjectRestrict does anything.  If it doesn't
1448:             * filter out any rows or columns, it's a No-Op.
1449:             *
1450:             * @return	true if this ProjectRestrict is a No-Op.
1451:             */
1452:            boolean nopProjectRestrict() {
1453:                /*
1454:                 ** This ProjectRestrictNode is not a No-Op if it does any
1455:                 ** restriction.
1456:                 */
1457:                if ((restriction != null)
1458:                        || (restrictionList != null && restrictionList.size() > 0)) {
1459:                    return false;
1460:                }
1461:
1462:                ResultColumnList childColumns = childResult.getResultColumns();
1463:                ResultColumnList PRNColumns = this .getResultColumns();
1464:
1465:                /*
1466:                 ** The two lists have the same numbers of elements.  Are the lists
1467:                 ** identical?  In other words, is the expression in every ResultColumn
1468:                 ** in the PRN's RCL a ColumnReference that points to the same-numbered
1469:                 ** column?
1470:                 */
1471:                if (PRNColumns.nopProjection(childColumns))
1472:                    return true;
1473:
1474:                return false;
1475:            }
1476:
1477:            /**
1478:             * Bypass the generation of this No-Op ProjectRestrict, and just generate
1479:             * its child result set.
1480:             *
1481:             * @exception StandardException		Thrown on error
1482:             */
1483:            public void generateNOPProjectRestrict() throws StandardException {
1484:                this .getResultColumns().setRedundant();
1485:            }
1486:
1487:            /**
1488:             * Consider materialization for this ResultSet tree if it is valid and cost effective
1489:             * (It is not valid if incorrect results would be returned.)
1490:             *
1491:             * @return Top of the new/same ResultSet tree.
1492:             *
1493:             * @exception StandardException		Thrown on error
1494:             */
1495:            public ResultSetNode considerMaterialization(JBitSet outerTables)
1496:                    throws StandardException {
1497:                childResult = childResult.considerMaterialization(outerTables);
1498:                if (childResult.performMaterialization(outerTables)) {
1499:                    MaterializeResultSetNode mrsn;
1500:                    ResultColumnList prRCList;
1501:
1502:                    /* If the restriction contians a ColumnReference from another
1503:                     * table then the MRSN must go above the childResult.  Otherwise we can put
1504:                     * it above ourselves. (The later is optimal since projection and restriction 
1505:                     * will only happen once.)
1506:                     * Put MRSN above PRN if any of the following are true:
1507:                     *	o  PRN doesn't have a restriction list
1508:                     *	o  PRN's restriction list is empty 
1509:                     *  o  Table's referenced in PRN's restriction list are a subset of
1510:                     *	   table's referenced in PRN's childResult.  (NOTE: Rather than construct
1511:                     *     a new, empty JBitSet before checking, we simply clone the childResult's
1512:                     *	   referencedTableMap.  This is done for code simplicity and will not 
1513:                     *	   affect the result.)
1514:                     */
1515:                    ReferencedTablesVisitor rtv = new ReferencedTablesVisitor(
1516:                            (JBitSet) childResult.getReferencedTableMap()
1517:                                    .clone());
1518:                    boolean emptyRestrictionList = (restrictionList == null || restrictionList
1519:                            .size() == 0);
1520:                    if (!emptyRestrictionList) {
1521:                        restrictionList.accept(rtv);
1522:                    }
1523:                    if (emptyRestrictionList
1524:                            || childResult.getReferencedTableMap().contains(
1525:                                    rtv.getTableMap())) {
1526:                        /* We get a shallow copy of the ResultColumnList and its 
1527:                         * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
1528:                         */
1529:                        prRCList = resultColumns;
1530:                        setResultColumns(resultColumns.copyListAndObjects());
1531:
1532:                        /* Replace ResultColumn.expression with new VirtualColumnNodes
1533:                         * in the NormalizeResultSetNode's ResultColumnList.  (VirtualColumnNodes include
1534:                         * pointers to source ResultSetNode, this, and source ResultColumn.)
1535:                         */
1536:                        prRCList.genVirtualColumnNodes(this , resultColumns);
1537:
1538:                        /* Finally, we create the new MaterializeResultSetNode */
1539:                        mrsn = (MaterializeResultSetNode) getNodeFactory()
1540:                                .getNode(
1541:                                        C_NodeTypes.MATERIALIZE_RESULT_SET_NODE,
1542:                                        this , prRCList, tableProperties,
1543:                                        getContextManager());
1544:                        // Propagate the referenced table map if it's already been created
1545:                        if (referencedTableMap != null) {
1546:                            mrsn
1547:                                    .setReferencedTableMap((JBitSet) referencedTableMap
1548:                                            .clone());
1549:                        }
1550:                        return mrsn;
1551:                    } else {
1552:                        /* We get a shallow copy of the ResultColumnList and its 
1553:                         * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
1554:                         */
1555:                        prRCList = childResult.getResultColumns();
1556:                        childResult.setResultColumns(prRCList
1557:                                .copyListAndObjects());
1558:
1559:                        /* Replace ResultColumn.expression with new VirtualColumnNodes
1560:                         * in the MaterializeResultSetNode's ResultColumnList.  (VirtualColumnNodes include
1561:                         * pointers to source ResultSetNode, this, and source ResultColumn.)
1562:                         */
1563:                        prRCList.genVirtualColumnNodes(childResult, childResult
1564:                                .getResultColumns());
1565:
1566:                        /* RESOLVE - we need to push single table predicates down so that
1567:                         * they get applied while building the MaterializeResultSet.
1568:                         */
1569:
1570:                        /* Finally, we create the new MaterializeResultSetNode */
1571:                        mrsn = (MaterializeResultSetNode) getNodeFactory()
1572:                                .getNode(
1573:                                        C_NodeTypes.MATERIALIZE_RESULT_SET_NODE,
1574:                                        childResult, prRCList, tableProperties,
1575:                                        getContextManager());
1576:                        // Propagate the referenced table map if it's already been created
1577:                        if (childResult.getReferencedTableMap() != null) {
1578:                            mrsn.setReferencedTableMap((JBitSet) childResult
1579:                                    .getReferencedTableMap().clone());
1580:                        }
1581:                        childResult = mrsn;
1582:                    }
1583:                }
1584:
1585:                return this ;
1586:            }
1587:
1588:            /** 
1589:             * Determine whether or not the specified name is an exposed name in
1590:             * the current query block.
1591:             *
1592:             * @param name	The specified name to search for as an exposed name.
1593:             * @param schemaName	Schema name, if non-null.
1594:             * @param exactMatch	Whether or not we need an exact match on specified schema and table
1595:             *						names or match on table id.
1596:             *
1597:             * @return The FromTable, if any, with the exposed name.
1598:             *
1599:             * @exception StandardException		Thrown on error
1600:             */
1601:            protected FromTable getFromTableByName(String name,
1602:                    String schemaName, boolean exactMatch)
1603:                    throws StandardException {
1604:                return childResult.getFromTableByName(name, schemaName,
1605:                        exactMatch);
1606:            }
1607:
1608:            /**
1609:             * Get the lock mode for the target of an update statement
1610:             * (a delete or update).  The update mode will always be row for
1611:             * CurrentOfNodes.  It will be table if there is no where clause.
1612:             *
1613:             * @return	The lock mode
1614:             */
1615:            public int updateTargetLockMode() {
1616:                if (restriction != null || constantRestriction != null) {
1617:                    return TransactionController.MODE_RECORD;
1618:                } else {
1619:                    return childResult.updateTargetLockMode();
1620:                }
1621:            }
1622:
1623:            /**
1624:             * Is it possible to do a distinct scan on this ResultSet tree.
1625:             * (See SelectNode for the criteria.)
1626:             *
1627:             * @param distinctColumns the set of distinct columns
1628:             * @return Whether or not it is possible to do a distinct scan on this ResultSet tree.
1629:             */
1630:            boolean isPossibleDistinctScan(Set distinctColumns) {
1631:                if (restriction != null
1632:                        || (restrictionList != null && restrictionList.size() != 0)) {
1633:                    return false;
1634:                }
1635:
1636:                HashSet columns = new HashSet();
1637:                for (int i = 0; i < resultColumns.size(); i++) {
1638:                    ResultColumn rc = (ResultColumn) resultColumns.elementAt(i);
1639:                    BaseColumnNode bc = rc.getBaseColumnNode();
1640:                    if (bc == null)
1641:                        return false;
1642:                    columns.add(bc);
1643:                }
1644:
1645:                return columns.equals(distinctColumns)
1646:                        && childResult.isPossibleDistinctScan(distinctColumns);
1647:            }
1648:
1649:            /**
1650:             * Mark the underlying scan as a distinct scan.
1651:             */
1652:            void markForDistinctScan() {
1653:                childResult.markForDistinctScan();
1654:            }
1655:
1656:            /**
1657:             * Accept a visitor, and call v.visit()
1658:             * on child nodes as necessary.  
1659:             * 
1660:             * @param v the visitor
1661:             *
1662:             * @exception StandardException on error
1663:             */
1664:            public Visitable accept(Visitor v) throws StandardException {
1665:                if (v.skipChildren(this )) {
1666:                    return v.visit(this );
1667:                }
1668:
1669:                Visitable returnNode = super .accept(v);
1670:
1671:                if (restriction != null && !v.stopTraversal()) {
1672:                    restriction = (ValueNode) restriction.accept(v);
1673:                }
1674:
1675:                if (restrictionList != null && !v.stopTraversal()) {
1676:                    restrictionList = (PredicateList) restrictionList.accept(v);
1677:                }
1678:
1679:                return returnNode;
1680:            }
1681:
1682:            /**
1683:             * set the Information gathered from the parent table that is 
1684:             * required to peform a referential action on dependent table.
1685:             */
1686:            public void setRefActionInfo(long fkIndexConglomId,
1687:                    int[] fkColArray, String parentResultSetId,
1688:                    boolean dependentScan) {
1689:                childResult.setRefActionInfo(fkIndexConglomId, fkColArray,
1690:                        parentResultSetId, dependentScan);
1691:            }
1692:
1693:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.