Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / compile / ProjectRestrictNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java
new file mode 100644 (file)
index 0000000..4ff5888
--- /dev/null
@@ -0,0 +1,1845 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.ProjectRestrictNode\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package        org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+\r
+import org.apache.derby.iapi.sql.compile.Optimizable;\r
+import org.apache.derby.iapi.sql.compile.OptimizablePredicate;\r
+import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;\r
+import org.apache.derby.iapi.sql.compile.Optimizer;\r
+import org.apache.derby.iapi.sql.compile.CostEstimate;\r
+import org.apache.derby.iapi.sql.compile.OptimizableList;\r
+import org.apache.derby.iapi.sql.compile.Visitable;\r
+import org.apache.derby.iapi.sql.compile.Visitor;\r
+import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;\r
+import org.apache.derby.iapi.sql.compile.RowOrdering;\r
+import org.apache.derby.iapi.sql.compile.AccessPath;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.services.loader.GeneratedMethod;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.util.Properties;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+/**\r
+ * A ProjectRestrictNode represents a result set for any of the basic DML\r
+ * operations: SELECT, INSERT, UPDATE, and DELETE.  For INSERT with\r
+ * a VALUES clause, restriction will be null. For both INSERT and UPDATE,\r
+ * the resultColumns in the selectList will contain the names of the columns\r
+ * being inserted into or updated.\r
+ *\r
+ * NOTE: A ProjectRestrictNode extends FromTable since it can exist in a FromList.\r
+ *\r
+ */\r
+\r
+public class ProjectRestrictNode extends SingleChildResultSetNode\r
+{\r
+       /**\r
+        * The ValueNode for the restriction to be evaluated here.\r
+        */\r
+       public ValueNode        restriction;\r
+\r
+       /**\r
+        * Constant expressions to be evaluated here.\r
+        */\r
+       ValueNode       constantRestriction = null;\r
+\r
+       /**\r
+        * Restriction as a PredicateList\r
+        */\r
+       public PredicateList restrictionList;\r
+\r
+       /**\r
+        * List of subqueries in projection\r
+        */\r
+       SubqueryList projectSubquerys;\r
+\r
+       /**\r
+        * List of subqueries in restriction\r
+        */\r
+       SubqueryList restrictSubquerys;\r
+\r
+       private boolean accessPathModified;\r
+\r
+       private boolean accessPathConsidered;\r
+\r
+       private boolean childResultOptimized;\r
+\r
+       private boolean materialize;\r
+\r
+       /* Should we get the table number from this node,\r
+        * regardless of the class of our child.\r
+        */\r
+       private boolean getTableNumberHere;\r
+\r
+       /**\r
+        * Initializer for a ProjectRestrictNode.\r
+        *\r
+        * @param childResult   The child ResultSetNode\r
+        * @param projection    The result column list for the projection\r
+        * @param restriction   An expression representing the restriction to be \r
+        *                                          evaluated here.\r
+        * @param restrictionList Restriction as a PredicateList\r
+        * @param projectSubquerys List of subqueries in the projection\r
+        * @param restrictSubquerys List of subqueries in the restriction\r
+        * @param tableProperties       Properties list associated with the table\r
+        */\r
+\r
+       public void init(\r
+                                                       Object childResult,\r
+                                                       Object projection,\r
+                                                       Object restriction,\r
+                                                       Object restrictionList,\r
+                                                       Object projectSubquerys,\r
+                                                       Object restrictSubquerys,\r
+                                                       Object tableProperties)\r
+       {\r
+               super.init(childResult, tableProperties);\r
+               resultColumns = (ResultColumnList) projection;\r
+               this.restriction = (ValueNode) restriction;\r
+               this.restrictionList = (PredicateList) restrictionList;\r
+               this.projectSubquerys = (SubqueryList) projectSubquerys;\r
+               this.restrictSubquerys = (SubqueryList) restrictSubquerys;\r
+\r
+               /* A PRN will only hold the tableProperties for\r
+                * a result set tree if its child is not an\r
+                * optimizable.  Otherwise, the properties will\r
+                * be transferred down to the child.\r
+                */\r
+               if (tableProperties != null &&\r
+                        (childResult instanceof Optimizable))\r
+               {\r
+                       ((Optimizable) childResult).setProperties(getProperties());\r
+                       setProperties((Properties) null);\r
+               }\r
+       }\r
+\r
+       /*\r
+        *  Optimizable interface\r
+        */\r
+\r
+       /**\r
+               @see Optimizable#nextAccessPath\r
+               @exception StandardException    Thrown on error\r
+        */\r
+       public boolean nextAccessPath(Optimizer optimizer,\r
+                                                                       OptimizablePredicateList predList,\r
+                                                                       RowOrdering rowOrdering)\r
+                       throws StandardException\r
+       {\r
+               /*\r
+               ** If the child result set is an optimizable, let it choose its next\r
+               ** access path.  If it is not an optimizable, we have to tell the\r
+               ** caller that there is an access path the first time we are called\r
+               ** for this position in the join order, and that there are no more\r
+               ** access paths for subsequent calls for this position in the join\r
+               ** order.  The startOptimizing() method is called once on each\r
+               ** optimizable when it is put into a join position.\r
+               */\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       return ((Optimizable) childResult).nextAccessPath(optimizer,\r
+                                                                                                                               restrictionList,\r
+                                                                                                                               rowOrdering);\r
+               }\r
+               else\r
+               {\r
+                       return super.nextAccessPath(optimizer, predList, rowOrdering);\r
+               }\r
+       }\r
+\r
+       /** @see Optimizable#rememberAsBest \r
+               @exception StandardException    Thrown on error\r
+        */\r
+       public void rememberAsBest(int planType, Optimizer optimizer)\r
+               throws StandardException\r
+       {\r
+               super.rememberAsBest(planType, optimizer);\r
+               if (childResult instanceof Optimizable)\r
+                       ((Optimizable) childResult).rememberAsBest(planType, optimizer);\r
+       }\r
+\r
+       /* Don't print anything for a PRN, as their\r
+        * child has the interesting info.\r
+        */\r
+       void printRememberingBestAccessPath(int planType, AccessPath bestPath)\r
+       {\r
+       }\r
+\r
+       /** @see Optimizable#startOptimizing */\r
+       public void startOptimizing(Optimizer optimizer, RowOrdering rowOrdering)\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       ((Optimizable) childResult).startOptimizing(optimizer, rowOrdering);\r
+               }\r
+               else\r
+               {\r
+                       accessPathConsidered = false;\r
+\r
+                       super.startOptimizing(optimizer, rowOrdering);\r
+               }\r
+       }\r
+\r
+       /** @see Optimizable#getTableNumber */\r
+       public int getTableNumber()\r
+       {\r
+               /* GROSS HACK - We need to get the tableNumber after\r
+                * calling modifyAccessPaths() on the child when doing\r
+                * a hash join on an arbitrary result set.  The problem\r
+                * is that the child will always be an optimizable at this\r
+                * point.  So, we 1st check to see if we should get it from\r
+                * this node.  (We set the boolean to true in the appropriate\r
+                * place in modifyAccessPaths().)\r
+                */\r
+               if (getTableNumberHere)\r
+               {\r
+                       return super.getTableNumber();\r
+               }\r
+\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).getTableNumber();\r
+\r
+               return super.getTableNumber();\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#optimizeIt\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public CostEstimate optimizeIt(\r
+                                                       Optimizer optimizer,\r
+                                                       OptimizablePredicateList predList,\r
+                                                       CostEstimate outerCost,\r
+                                                       RowOrdering rowOrdering)\r
+                       throws StandardException\r
+       {\r
+               /*\r
+               ** RESOLVE: Most types of Optimizables only implement estimateCost(),\r
+               ** and leave it up to optimizeIt() in FromTable to figure out the\r
+               ** total cost of the join.  A ProjectRestrict can have a non-Optimizable\r
+               ** child, though, in which case we want to tell the child the\r
+               ** number of outer rows - it could affect the join strategy\r
+               ** significantly.  So we implement optimizeIt() here, which overrides\r
+               ** the optimizeIt() in FromTable.  This assumes that the join strategy\r
+               ** for which this join node is the inner table is a nested loop join,\r
+               ** which will not be a valid assumption when we implement other\r
+               ** strategies like materialization (hash join can work only on\r
+               ** base tables).  The join strategy for a base table under a\r
+               ** ProjectRestrict is set in the base table itself.\r
+               */\r
+\r
+               CostEstimate childCost;\r
+\r
+               costEstimate = getCostEstimate(optimizer);\r
+\r
+               /*\r
+               ** Don't re-optimize a child result set that has already been fully\r
+               ** optimized.  For example, if the child result set is a SelectNode,\r
+               ** it will be changed to a ProjectRestrictNode, which we don't want\r
+               ** to re-optimized.\r
+               */\r
+               // NOTE: TO GET THE RIGHT COST, THE CHILD RESULT MAY HAVE TO BE\r
+               // OPTIMIZED MORE THAN ONCE, BECAUSE THE NUMBER OF OUTER ROWS\r
+               // MAY BE DIFFERENT EACH TIME.\r
+               // if (childResultOptimized)\r
+               //      return costEstimate;\r
+\r
+               // It's possible that a call to optimize the left/right will cause\r
+               // a new "truly the best" plan to be stored in the underlying base\r
+               // tables.  If that happens and then we decide to skip that plan\r
+               // (which we might do if the call to "considerCost()" below decides\r
+               // the current path is infeasible or not the best) we need to be\r
+               // able to revert back to the "truly the best" plans that we had\r
+               // saved before we got here.  So with this next call we save the\r
+               // current plans using "this" node as the key.  If needed, we'll\r
+               // then make the call to revert the plans in OptimizerImpl's\r
+               // getNextDecoratedPermutation() method.\r
+               updateBestPlanMap(ADD_PLAN, this);\r
+\r
+               /* If the childResult is instanceof Optimizable, then we optimizeIt.\r
+                * Otherwise, we are going into a new query block.  If the new query\r
+                * block has already had its access path modified, then there is\r
+                * nothing to do.  Otherwise, we must begin the optimization process\r
+                * anew on the new query block.\r
+                */\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       childCost = ((Optimizable) childResult).optimizeIt(\r
+                                                                                                                       optimizer,\r
+                                                                                                                       restrictionList,\r
+                                                                                                                       outerCost,\r
+                                                                                                                       rowOrdering);\r
+                       /* Copy child cost to this node's cost */\r
+                       costEstimate.setCost(\r
+                                                       childCost.getEstimatedCost(),\r
+                                                       childCost.rowCount(),\r
+                                                       childCost.singleScanRowCount());\r
+\r
+\r
+                       // Note: we don't call "optimizer.considerCost()" here because\r
+                       // a) the child will make that call as part of its own\r
+                       // "optimizeIt()" work above, and b) the child might have\r
+                       // different criteria for "considering" (i.e. rejecting or\r
+                       // accepting) a plan's cost than this ProjectRestrictNode does--\r
+                       // and we don't want to override the child's decision.  So as\r
+                       // with most operations in this class, if the child is an\r
+                       // Optimizable, we just let it do its own work and make its\r
+                       // own decisions.\r
+               }\r
+               else if ( ! accessPathModified)\r
+               {\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               if (! ((childResult instanceof SelectNode) ||\r
+                                                                (childResult instanceof RowResultSetNode)))\r
+                               {\r
+                                       SanityManager.THROWASSERT(\r
+                                               "childResult is expected to be instanceof " +\r
+                                               "SelectNode or RowResultSetNode - it is a " +\r
+                                               childResult.getClass().getName());\r
+                               }\r
+                       }\r
+                       childResult = childResult.optimize(optimizer.getDataDictionary(), \r
+                                                                                          restrictionList,\r
+                                                                                          outerCost.rowCount());\r
+\r
+                       /* Copy child cost to this node's cost */\r
+                       childCost = childResult.costEstimate;\r
+\r
+                       costEstimate.setCost(\r
+                                                       childCost.getEstimatedCost(),\r
+                                                       childCost.rowCount(),\r
+                                                       childCost.singleScanRowCount());\r
+\r
+                       /* Note: Prior to the fix for DERBY-781 we had calls here\r
+                        * to set the cost estimate for BestAccessPath and\r
+                        * BestSortAvoidancePath to equal costEstimate.  That used\r
+                        * to be okay because prior to DERBY-781 we would only\r
+                        * get here once (per join order) for a given SelectNode/\r
+                        * RowResultSetNode and thus we could safely say that the\r
+                        * costEstimate from the most recent call to "optimize()"\r
+                        * was the best one so far (because we knew that we would\r
+                        * only call childResult.optimize() once).  Now that we\r
+                        * support hash joins with subqueries, though, we can get\r
+                        * here twice per join order: once when the optimizer is\r
+                        * considering a nested loop join with this PRN, and once\r
+                        * when it is considering a hash join.  This means we can't\r
+                        * just arbitrarily use the cost estimate for the most recent\r
+                        * "optimize()" as the best cost because that may not\r
+                        * be accurate--it's possible that the above call to\r
+                        * childResult.optimize() was for a hash join, but that\r
+                        * we were here once before (namely for nested loop) and\r
+                        * the cost of the nested loop is actually less than\r
+                        * the cost of the hash join.  In that case it would\r
+                        * be wrong to use costEstimate as the cost of the "best"\r
+                        * paths because it (costEstimate) holds the cost of\r
+                        * the hash join, not of the nested loop join.  So with\r
+                        * DERBY-781 the following calls were removed:\r
+                        *   getBestAccessPath().setCostEstimate(costEstimate);\r
+                        *   getBestSortAvoidancePath().setCostEstimate(costEstimate);\r
+                        * If costEstimate *does* actually hold the estimate for\r
+                        * the best path so far, then we will set BestAccessPath\r
+                        * and BestSortAvoidancePath as needed in the following\r
+                        * call to "considerCost".\r
+                        */\r
+\r
+                       // childResultOptimized = true;\r
+\r
+                       /* RESOLVE - ARBITRARYHASHJOIN - Passing restriction list here, as above, is correct.\r
+                        * However,  passing predList makes the following work:\r
+                        *      select * from t1, (select * from t2) c properties joinStrategy = hash where t1.c1 = c.c1;\r
+                        * The following works with restrictionList:\r
+                        *      select * from t1, (select c1 + 0 from t2) c(c1) properties joinStrategy = hash where t1.c1 = c.c1;\r
+                        */\r
+                       optimizer.considerCost(this, restrictionList, getCostEstimate(), outerCost);\r
+               }\r
+\r
+               return costEstimate;\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#feasibleJoinStrategy\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public boolean feasibleJoinStrategy(OptimizablePredicateList predList,\r
+                                                                               Optimizer optimizer)\r
+                                       throws StandardException\r
+       {\r
+               AccessPath ap;\r
+\r
+               /* The child being an Optimizable is a special case.  In that\r
+                * case, we want to get the current access path and join strategy\r
+                * from the child.  Otherwise, we want to get it from this node.\r
+                */\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       // With DERBY-805 it's possible that, when considering a nested\r
+                       // loop join with this PRN, we pushed predicates down into the\r
+                       // child if the child is a UNION node.  At this point, though, we\r
+                       // may be considering doing a hash join with this PRN instead of a\r
+                       // nested loop join, and if that's the case we need to pull any\r
+                       // predicates back up so that they can be searched for equijoins\r
+                       // that will in turn make the hash join possible.  So that's what\r
+                       // the next call does.  Two things to note: 1) if no predicates\r
+                       // were pushed, this call is a no-op; and 2) if we get here when\r
+                       // considering a nested loop join, the predicates that we pull\r
+                       // here (if any) will be re-pushed for subsequent costing/ \r
+                       // optimization as necessary (see OptimizerImpl.costPermutation(),\r
+                       // which will call this class's optimizeIt() method and that's\r
+                       // where the predicates are pushed down again).\r
+                       if (childResult instanceof UnionNode)\r
+                               ((UnionNode)childResult).pullOptPredicates(restrictionList);\r
+\r
+                       return ((Optimizable) childResult).\r
+                               feasibleJoinStrategy(restrictionList, optimizer);\r
+               }\r
+               else\r
+               {\r
+                       return super.feasibleJoinStrategy(restrictionList, optimizer);\r
+               }\r
+       }\r
+\r
+       /** @see Optimizable#getCurrentAccessPath */\r
+       public AccessPath getCurrentAccessPath()\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).getCurrentAccessPath();\r
+\r
+               return super.getCurrentAccessPath();\r
+       }\r
+\r
+       /** @see Optimizable#getBestAccessPath */\r
+       public AccessPath getBestAccessPath()\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).getBestAccessPath();\r
+\r
+               return super.getBestAccessPath();\r
+       }\r
+\r
+       /** @see Optimizable#getBestSortAvoidancePath */\r
+       public AccessPath getBestSortAvoidancePath()\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).getBestSortAvoidancePath();\r
+\r
+               return super.getBestSortAvoidancePath();\r
+       }\r
+\r
+       /** @see Optimizable#getTrulyTheBestAccessPath */\r
+       public AccessPath getTrulyTheBestAccessPath()\r
+       {\r
+               /* The childResult will always be an Optimizable\r
+                * during code generation.  If the childResult was\r
+                * not an Optimizable during optimization, then this node\r
+                * will have the truly the best access path, so we want to\r
+                * return it from this node, rather than traversing the tree.\r
+                * This can happen for non-flattenable derived tables.\r
+                * Anyway, we note this state when modifying the access paths.\r
+                */\r
+               if (hasTrulyTheBestAccessPath)\r
+               {\r
+                       return super.getTrulyTheBestAccessPath();\r
+               }\r
+\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).getTrulyTheBestAccessPath();\r
+\r
+               return super.getTrulyTheBestAccessPath();\r
+       }\r
+\r
+       /** @see Optimizable#rememberSortAvoidancePath */\r
+       public void rememberSortAvoidancePath()\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+                       ((Optimizable) childResult).rememberSortAvoidancePath();\r
+               else\r
+                       super.rememberSortAvoidancePath();\r
+       }\r
+\r
+       /** @see Optimizable#considerSortAvoidancePath */\r
+       public boolean considerSortAvoidancePath()\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+                       return ((Optimizable) childResult).considerSortAvoidancePath();\r
+\r
+               return super.considerSortAvoidancePath();\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#pushOptPredicate\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate)\r
+                       throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(optimizablePredicate instanceof Predicate,\r
+                               "optimizablePredicate expected to be instanceof Predicate");\r
+                       SanityManager.ASSERT(! optimizablePredicate.hasSubquery() &&\r
+                                                                ! optimizablePredicate.hasMethodCall(),\r
+                               "optimizablePredicate either has a subquery or a method call");\r
+               }\r
+\r
+               /* Add the matching predicate to the restrictionList */\r
+               if (restrictionList == null)\r
+               {\r
+                       restrictionList = (PredicateList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                                       getContextManager());\r
+               }\r
+               restrictionList.addPredicate((Predicate) optimizablePredicate);\r
+\r
+               /* Remap all of the ColumnReferences to point to the\r
+                * source of the values.\r
+                */\r
+               Predicate pred = (Predicate)optimizablePredicate;\r
+\r
+               /* If the predicate is scoped then the call to "remapScopedPred()"\r
+                * will do the necessary remapping for us and will return true;\r
+                * otherwise, we'll just do the normal remapping here.\r
+                */\r
+               if (!pred.remapScopedPred())\r
+               {\r
+                       RemapCRsVisitor rcrv = new RemapCRsVisitor(true);\r
+                       pred.getAndNode().accept(rcrv);\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#pullOptPredicates\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void pullOptPredicates(\r
+                                                               OptimizablePredicateList optimizablePredicates)\r
+                                       throws StandardException\r
+       {\r
+               if (restrictionList != null)\r
+               {\r
+                       // Pull up any predicates that may have been pushed further\r
+                       // down the tree during optimization.\r
+                       if (childResult instanceof UnionNode)\r
+                               ((UnionNode)childResult).pullOptPredicates(restrictionList);\r
+\r
+                       RemapCRsVisitor rcrv = new RemapCRsVisitor(false);\r
+                       for (int i = restrictionList.size() - 1; i >= 0; i--)\r
+                       {\r
+                               OptimizablePredicate optPred =\r
+                                       restrictionList.getOptPredicate(i);\r
+                               ((Predicate) optPred).getAndNode().accept(rcrv);\r
+                               optimizablePredicates.addOptPredicate(optPred);\r
+                               restrictionList.removeOptPredicate(i);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#modifyAccessPath\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public Optimizable modifyAccessPath(JBitSet outerTables) \r
+               throws StandardException\r
+       {\r
+               boolean origChildOptimizable = true;\r
+\r
+               /* It is okay to optimize most nodes multiple times.  However,\r
+                * modifying the access path is something that should only be done\r
+                * once per node.  One reason for this is that the predicate list\r
+                * will be empty after the 1st call, and we assert that it should\r
+                * be non-empty.  Multiple calls to modify the access path can\r
+                * occur when there is a non-flattenable FromSubquery (or view).\r
+                */\r
+               if (accessPathModified)\r
+               {\r
+                       return this;\r
+               }\r
+\r
+               /*\r
+               ** Do nothing if the child result set is not optimizable, as there\r
+               ** can be nothing to modify.\r
+               */\r
+               boolean alreadyPushed = false;\r
+               if ( ! (childResult instanceof Optimizable))\r
+               {\r
+                       // Remember that the original child was not Optimizable\r
+                       origChildOptimizable = false;\r
+\r
+                       /* When we optimized the child we passed in our restriction list\r
+                        * so that scoped predicates could be pushed further down the\r
+                        * tree.  We need to do the same when modifying the access\r
+                        * paths to ensure we generate the same plans the optimizer\r
+                        * chose.\r
+                        */\r
+                       childResult = childResult.modifyAccessPaths(restrictionList);\r
+\r
+                       /* Mark this node as having the truly ... for\r
+                        * the underlying tree.\r
+                        */\r
+                       hasTrulyTheBestAccessPath = true;\r
+\r
+                       /* Replace this PRN with a HRN if we are doing a hash join */\r
+                       if (trulyTheBestAccessPath.getJoinStrategy().isHashJoin())\r
+                       {\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.ASSERT(restrictionList != null,\r
+                                               "restrictionList expected to be non-null");\r
+                                       SanityManager.ASSERT(restrictionList.size() != 0,\r
+                                                       "restrictionList.size() expected to be non-zero");\r
+                               }\r
+                               /* We're doing a hash join on an arbitary result set.\r
+                                * We need to get the table number from this node when\r
+                                * dividing up the restriction list for a hash join.\r
+                                * We need to explicitly remember this.\r
+                                */\r
+                               getTableNumberHere = true;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* We consider materialization into a temp table as a last step.\r
+                                * Currently, we only materialize VTIs that are inner tables\r
+                                * and can't be instantiated multiple times.  In the future we\r
+                                * will consider materialization as a cost based option.\r
+                                */\r
+                               return (Optimizable) considerMaterialization(outerTables);\r
+                       }\r
+               }\r
+\r
+               /* If the child is not a FromBaseTable, then we want to\r
+                * keep going down the tree.  (Nothing to do at this node.)\r
+                */\r
+               else if (!(childResult instanceof FromBaseTable))\r
+               {\r
+                       /* Make sure that we have a join strategy */\r
+                       if (trulyTheBestAccessPath.getJoinStrategy() == null)\r
+                       {\r
+                               trulyTheBestAccessPath = (AccessPathImpl) ((Optimizable) childResult).getTrulyTheBestAccessPath();\r
+                       }\r
+\r
+                       // If the childResult is a SetOperatorNode (esp. a UnionNode),\r
+                       // then it's possible that predicates in our restrictionList are\r
+                       // supposed to be pushed further down the tree (as of DERBY-805).\r
+                       // We passed the restrictionList down when we optimized the child\r
+                       // so that the relevant predicates could be pushed further as part\r
+                       // of the optimization process; so now that we're finalizing the\r
+                       // paths, we need to do the same thing: i.e. pass restrictionList\r
+                       // down so that the predicates that need to be pushed further\r
+                       // _can_ be pushed further.\r
+                       if (childResult instanceof SetOperatorNode) {\r
+                               childResult = (ResultSetNode)\r
+                                       ((SetOperatorNode) childResult).modifyAccessPath(\r
+                                               outerTables, restrictionList);\r
+\r
+                               // Take note of the fact that we already pushed predicates\r
+                               // as part of the modifyAccessPaths call.  This is necessary\r
+                               // because there may still be predicates in restrictionList\r
+                               // that we intentionally decided not to push (ex. if we're\r
+                               // going to do hash join then we chose to not push the join\r
+                               // predicates).  Whatever the reason for not pushing the\r
+                               // predicates, we have to make sure we don't inadvertenly\r
+                               // push them later (esp. as part of the "pushUsefulPredicates"\r
+                               // call below).\r
+                               alreadyPushed = true;\r
+                       }\r
+                       else {\r
+                               childResult = \r
+                                       (ResultSetNode) ((FromTable) childResult).\r
+                                               modifyAccessPath(outerTables);\r
+                       }\r
+               }\r
+\r
+               // If we're doing a hash join with _this_ PRN (as opposed to\r
+               // with this PRN's child) then we don't attempt to push\r
+               // predicates down.  There are two reasons for this: 1)\r
+               // we don't want to push the equijoin predicate that is\r
+               // required for the hash join, and 2) if we're doing a\r
+               // hash join then we're going to materialize this node,\r
+               // but if we push predicates before materialization, we\r
+               // can end up with incorrect results (esp. missing rows).\r
+               // So don't push anything in this case.\r
+               boolean hashJoinWithThisPRN = hasTrulyTheBestAccessPath &&\r
+                       (trulyTheBestAccessPath.getJoinStrategy() != null) &&\r
+                       trulyTheBestAccessPath.getJoinStrategy().isHashJoin();\r
+\r
+               if ((restrictionList != null) && !alreadyPushed && !hashJoinWithThisPRN)\r
+               {\r
+                       restrictionList.pushUsefulPredicates((Optimizable) childResult);\r
+               }\r
+\r
+               /*\r
+               ** The optimizer's decision on the access path for the child result\r
+               ** set may require the generation of extra result sets.  For\r
+               ** example, if it chooses an index, we need an IndexToBaseRowNode\r
+               ** above the FromBaseTable (and the FromBaseTable has to change\r
+               ** its column list to match that of the index.\r
+               */\r
+               if (origChildOptimizable)\r
+               {\r
+                       childResult = childResult.changeAccessPath();\r
+               }\r
+               accessPathModified = true;\r
+\r
+               /*\r
+               ** Replace this PRN with a HTN if a hash join\r
+               ** is being done at this node.  (Hash join on a scan\r
+               ** is a special case and is handled at the FBT.)\r
+               */\r
+               if (trulyTheBestAccessPath.getJoinStrategy() != null &&\r
+                       trulyTheBestAccessPath.getJoinStrategy().isHashJoin())\r
+               {\r
+                       return replaceWithHashTableNode();\r
+               }\r
+\r
+               /* We consider materialization into a temp table as a last step.\r
+                * Currently, we only materialize VTIs that are inner tables\r
+                * and can't be instantiated multiple times.  In the future we\r
+                * will consider materialization as a cost based option.\r
+                */\r
+               return (Optimizable) considerMaterialization(outerTables);\r
+       }\r
+\r
+       /**\r
+        * This method creates a HashTableNode between the PRN and\r
+        * it's child when the optimizer chooses hash join on an\r
+        * arbitrary (non-FBT) result set tree.\r
+        * We divide up the restriction list into 3 parts and\r
+        * distribute those parts as described below.\r
+        * \r
+        * @return The new (same) top of our result set tree.\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       private Optimizable replaceWithHashTableNode()\r
+               throws StandardException\r
+       {\r
+               // If this PRN has TTB access path for its child, store that access\r
+               // path in the child here, so that we can find it later when it\r
+               // comes time to generate qualifiers for the hash predicates (we\r
+               // need the child's access path when generating qualifiers; if we\r
+               // don't pass the path down here, the child won't be able to find\r
+               // it).\r
+               if (hasTrulyTheBestAccessPath)\r
+               {\r
+                       ((FromTable)childResult).trulyTheBestAccessPath =\r
+                               (AccessPathImpl)getTrulyTheBestAccessPath();\r
+\r
+                       // If the child itself is another SingleChildResultSetNode\r
+                       // (which is also what a ProjectRestrictNode is), then tell\r
+                       // it that it is now holding TTB path for it's own child.  Again,\r
+                       // this info is needed so that child knows where to find the\r
+                       // access path at generation time.\r
+                       if (childResult instanceof SingleChildResultSetNode)\r
+                       {\r
+                               ((SingleChildResultSetNode)childResult)\r
+                                       .hasTrulyTheBestAccessPath = hasTrulyTheBestAccessPath;\r
+\r
+                               // While we're at it, add the PRN's table number to the\r
+                               // child's referenced map so that we can find the equijoin\r
+                               // predicate.  We have to do this because the predicate\r
+                               // will be referencing the PRN's tableNumber, not the\r
+                               // child's--and since we use the child as the target\r
+                               // when searching for hash keys (as can be seen in\r
+                               // HashJoinStrategy.divideUpPredicateLists()), the child\r
+                               // should know what this PRN's table number is.  This\r
+                               // is somewhat bizarre since the child doesn't\r
+                               // actually "reference" this PRN, but since the child's\r
+                               // reference map is used when searching for the equijoin\r
+                               // predicate (see "buildTableNumList" in\r
+                               // BinaryRelationalOperatorNode), this is the simplest\r
+                               // way to pass this PRN's table number down.\r
+                               childResult.getReferencedTableMap().set(tableNumber);\r
+                       }\r
+               }\r
+\r
+               /* We want to divide the predicate list into 3 separate lists -\r
+                *      o predicates against the source of the hash table, which will\r
+                *        be applied on the way into the hash table (searchRestrictionList)\r
+                *  o join clauses which are qualifiers and get applied to the\r
+                *        rows in the hash table on a probe (joinRestrictionList)\r
+                *      o non-qualifiers involving both tables which will get\r
+                *        applied after a row gets returned from the HTRS (nonQualifiers)\r
+                *\r
+                * We do some unnecessary work when doing this as we want to reuse\r
+                * as much existing code as possible.  The code that we are reusing\r
+                * was originally built for hash scans, hence the unnecessary\r
+                * requalification list.\r
+                */\r
+               PredicateList searchRestrictionList =\r
+                                                               (PredicateList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                                       getContextManager());\r
+               PredicateList joinQualifierList =\r
+                                                               (PredicateList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                                       getContextManager());\r
+               PredicateList requalificationRestrictionList =\r
+                                                               (PredicateList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                                       getContextManager());\r
+               trulyTheBestAccessPath.getJoinStrategy().divideUpPredicateLists(\r
+                                                                                       this,\r
+                                                                                       restrictionList,\r
+                                                                                       searchRestrictionList,\r
+                                                                                       joinQualifierList,\r
+                                                                                       requalificationRestrictionList,\r
+                                                                                       getDataDictionary());\r
+\r
+               /* Break out the non-qualifiers from HTN's join qualifier list and make that\r
+                * the new restriction list for this PRN.\r
+                */\r
+               restrictionList = (PredicateList) getNodeFactory().getNode(\r
+                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                       getContextManager());\r
+        /* For non-base table, we remove first 2 lists from requal list to avoid adding duplicates.\r
+         */\r
+               for (int i = 0; i < searchRestrictionList.size(); i++)\r
+                       requalificationRestrictionList.removeOptPredicate((Predicate) searchRestrictionList.elementAt(i));\r
+               for (int i = 0; i < joinQualifierList.size(); i++)\r
+                       requalificationRestrictionList.removeOptPredicate((Predicate) joinQualifierList.elementAt(i));\r
+\r
+               joinQualifierList.transferNonQualifiers(this, restrictionList); //purify joinQual list\r
+               requalificationRestrictionList.copyPredicatesToOtherList(restrictionList); //any residual\r
+\r
+               ResultColumnList        htRCList;\r
+\r
+               /* We get a shallow copy of the child's ResultColumnList and its \r
+                * ResultColumns.  (Copy maintains ResultColumn.expression for now.)\r
+                */\r
+               htRCList = childResult.getResultColumns();\r
+               childResult.setResultColumns(htRCList.copyListAndObjects());\r
+\r
+               /* Replace ResultColumn.expression with new VirtualColumnNodes\r
+                * in the HTN's ResultColumnList.  (VirtualColumnNodes include\r
+                * pointers to source ResultSetNode, this, and source ResultColumn.)\r
+                * NOTE: We don't want to mark the underlying RCs as referenced, otherwise\r
+                * we won't be able to project out any of them.\r
+                */\r
+               htRCList.genVirtualColumnNodes(childResult, childResult.getResultColumns(), false);\r
+\r
+               /* The CRs for this side of the join in both the searchRestrictionList\r
+                * the joinQualifierList now point to the HTN's RCL.  We need them\r
+                * to point to the RCL in the child of the HTN.  (We skip doing this for\r
+                * the joinQualifierList as the code to generate the Qualifiers does not\r
+                * care.)\r
+                */\r
+               RemapCRsVisitor rcrv = new RemapCRsVisitor(true);\r
+               searchRestrictionList.accept(rcrv);\r
+\r
+               /* We can finally put the HTN between ourself and our old child. */\r
+               childResult = (ResultSetNode) getNodeFactory().getNode(\r
+                                                                                       C_NodeTypes.HASH_TABLE_NODE,\r
+                                                                                       childResult,\r
+                                                                                       tableProperties, \r
+                                                                                       htRCList,\r
+                                                                                       searchRestrictionList, \r
+                                                                                       joinQualifierList,\r
+                                                                                       trulyTheBestAccessPath, \r
+                                                                                       getCostEstimate(),\r
+                                                                                       projectSubquerys,\r
+                                                                                       restrictSubquerys,\r
+                                                                                       hashKeyColumns(),\r
+                                                                                       getContextManager());\r
+               return this;\r
+       }\r
+\r
+       /** @see Optimizable#verifyProperties \r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void verifyProperties(DataDictionary dDictionary)\r
+               throws StandardException\r
+       {\r
+               /* Table properties can be attached to this node if\r
+                * its child is not an optimizable, otherwise they\r
+                * are attached to its child.\r
+                */\r
+\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       ((Optimizable) childResult).verifyProperties(dDictionary);\r
+               }\r
+               else\r
+               {\r
+                       super.verifyProperties(dDictionary);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#legalJoinOrder\r
+        */\r
+       public boolean legalJoinOrder(JBitSet assignedTableMap)\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       return ((Optimizable) childResult).legalJoinOrder(assignedTableMap);\r
+               }\r
+               else\r
+               {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * @see Optimizable#uniqueJoin\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public double uniqueJoin(OptimizablePredicateList predList)\r
+                                       throws StandardException\r
+       {\r
+               if (childResult instanceof Optimizable)\r
+               {\r
+                       return ((Optimizable) childResult).uniqueJoin(predList);\r
+               }\r
+               else\r
+               {\r
+                       return super.uniqueJoin(predList);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Return the restriction list from this node.\r
+        *\r
+        * @return      The restriction list from this node.\r
+        */\r
+       PredicateList getRestrictionList()\r
+       {\r
+               return restrictionList;\r
+       }\r
+\r
+       /** \r
+        * Return the user specified join strategy, if any for this table.\r
+        *\r
+        * @return The user specified join strategy, if any for this table.\r
+        */\r
+       String getUserSpecifiedJoinStrategy()\r
+       {\r
+               if (childResult instanceof FromTable)\r
+               {\r
+                       return ((FromTable) childResult).getUserSpecifiedJoinStrategy();\r
+               }\r
+               else\r
+               {\r
+                       return userSpecifiedJoinStrategy;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Prints the sub-nodes of this object.  See QueryTreeNode.java for\r
+        * how tree printing is supposed to work.\r
+        *\r
+        * @param depth         The depth of this node in the tree\r
+        */\r
+\r
+       public void printSubNodes(int depth)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       super.printSubNodes(depth);\r
+\r
+                       if (restriction != null)\r
+                       {\r
+                               printLabel(depth, "restriction: ");\r
+                               restriction.treePrint(depth + 1);\r
+                       }\r
+\r
+                       if (restrictionList != null)\r
+                       {\r
+                               printLabel(depth, "restrictionList: ");\r
+                               restrictionList.treePrint(depth + 1);\r
+                       }\r
+\r
+                       if (projectSubquerys != null)\r
+                       {\r
+                               printLabel(depth, "projectSubquerys: ");\r
+                               projectSubquerys.treePrint(depth + 1);\r
+                       }\r
+\r
+                       if (restrictSubquerys != null)\r
+                       {\r
+                               printLabel(depth, "restrictSubquerys: ");\r
+                               restrictSubquerys.treePrint(depth + 1);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /** \r
+        * Put a ProjectRestrictNode on top of each FromTable in the FromList.\r
+        * ColumnReferences must continue to point to the same ResultColumn, so\r
+        * that ResultColumn must percolate up to the new PRN.  However,\r
+        * that ResultColumn will point to a new expression, a VirtualColumnNode, \r
+        * which points to the FromTable and the ResultColumn that is the source for\r
+        * the ColumnReference.  \r
+        * (The new PRN will have the original of the ResultColumnList and\r
+        * the ResultColumns from that list.  The FromTable will get shallow copies\r
+        * of the ResultColumnList and its ResultColumns.  ResultColumn.expression\r
+        * will remain at the FromTable, with the PRN getting a new \r
+        * VirtualColumnNode for each ResultColumn.expression.)\r
+        * We then project out the non-referenced columns.  If there are no referenced\r
+        * columns, then the PRN's ResultColumnList will consist of a single ResultColumn\r
+        * whose expression is 1.\r
+        *\r
+        * @param numTables                     Number of tables in the DML Statement\r
+        * @param gbl                           The group by list, if any\r
+        * @param fromList                      The from list, if any\r
+        *\r
+        * @return The generated ProjectRestrictNode atop the original FromTable.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public ResultSetNode preprocess(int numTables,\r
+                                                                       GroupByList gbl,\r
+                                                                       FromList fromList) \r
+                                                               throws StandardException\r
+       {\r
+               childResult = childResult.preprocess(numTables, gbl, fromList);\r
+\r
+               /* Build the referenced table map */\r
+               referencedTableMap = (JBitSet) childResult.getReferencedTableMap().clone();\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Push expressions down to the first ResultSetNode which can do expression\r
+        * evaluation and has the same referenced table map.\r
+        * RESOLVE - This means only pushing down single table expressions to\r
+        * ProjectRestrictNodes today.  Once we have a better understanding of how\r
+        * the optimizer will work, we can push down join clauses.\r
+        *\r
+        * @param predicateList The PredicateList.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void pushExpressions(PredicateList predicateList)\r
+                                       throws StandardException\r
+       {\r
+               PredicateList   pushPList = null;\r
+\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(predicateList != null,\r
+                                                        "predicateList is expected to be non-null");\r
+\r
+               /* Push single table predicates down to the left of an outer\r
+                * join, if possible.  (We need to be able to walk an entire\r
+                * join tree.)\r
+                */\r
+               if (childResult instanceof JoinNode)\r
+               {\r
+                       ((FromTable) childResult).pushExpressions(predicateList);\r
+\r
+               }\r
+\r
+               /* Build a list of the single table predicates that we can push down */\r
+               pushPList = predicateList.getPushablePredicates(referencedTableMap);\r
+\r
+               /* If this is a PRN above a SelectNode, probably due to a \r
+                * view or derived table which couldn't be flattened, then see\r
+                * if we can push any of the predicates which just got pushed\r
+                * down to our level into the SelectNode.\r
+                */\r
+               if (pushPList != null && (childResult instanceof SelectNode))\r
+               {\r
+                       pushPList.pushExpressionsIntoSelect((SelectNode) childResult, false);\r
+               }\r
+\r
+               /* DERBY-649: Push simple predicates into Unions. It would be up to UnionNode\r
+                * to decide if these predicates can be pushed further into underlying SelectNodes\r
+                * or UnionNodes.  Note, we also keep the predicateList at this\r
+                * ProjectRestrictNode in case the predicates are not pushable or only\r
+                * partially pushable.\r
+                *\r
+                * It is possible to expand this optimization in UnionNode later.\r
+                */\r
+               if (pushPList != null && (childResult instanceof UnionNode))\r
+                       ((UnionNode)childResult).pushExpressions(pushPList);\r
+\r
+               if (restrictionList == null)\r
+               {\r
+                       restrictionList = pushPList;\r
+               }\r
+               else if (pushPList != null && pushPList.size() != 0)\r
+               {\r
+                       /* Concatenate the 2 PredicateLists */\r
+                       restrictionList.destructiveAppend(pushPList);\r
+               }\r
+\r
+               /* RESOLVE - this looks like the place to try to try to push the \r
+                * predicates through the ProjectRestrict.  Seems like we should\r
+                * "rebind" the column references and reset the referenced table maps\r
+                * in restrictionList and then call childResult.pushExpressions() on\r
+                * restrictionList.\r
+                */\r
+       }\r
+\r
+       /**\r
+        * Add a new predicate to the list.  This is useful when doing subquery\r
+        * transformations, when we build a new predicate with the left side of\r
+        * the subquery operator and the subquery's result column.\r
+        *\r
+        * @param predicate             The predicate to add\r
+        *\r
+        * @return ResultSetNode        The new top of the tree.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ResultSetNode addNewPredicate(Predicate predicate)\r
+                       throws StandardException\r
+       {\r
+               if (restrictionList == null)\r
+               {\r
+                       restrictionList = (PredicateList) getNodeFactory().getNode(\r
+                                                                                                       C_NodeTypes.PREDICATE_LIST,\r
+                                                                                                       getContextManager());\r
+               }\r
+               restrictionList.addPredicate(predicate);\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Evaluate whether or not the subquery in a FromSubquery is flattenable.  \r
+        * Currently, a FSqry is flattenable if all of the following are true:\r
+        *              o  Subquery is a SelectNode. \r
+        *              o  It contains no top level subqueries.  (RESOLVE - we can relax this)\r
+        *              o  It does not contain a group by or having clause\r
+        *              o  It does not contain aggregates.\r
+        *\r
+        * @param fromList      The outer from list\r
+        *\r
+        * @return boolean      Whether or not the FromSubquery is flattenable.\r
+        */\r
+       public boolean flattenableInFromSubquery(FromList fromList)\r
+       {\r
+               /* Flattening currently involves merging predicates and FromLists.\r
+                * We don't have a FromList, so we can't flatten for now.\r
+                */\r
+               /* RESOLVE - this will introduce yet another unnecessary PRN */\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Ensure that the top of the RSN tree has a PredicateList.\r
+        *\r
+        * @param numTables                     The number of tables in the query.\r
+        * @return ResultSetNode        A RSN tree with a node which has a PredicateList on top.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ResultSetNode ensurePredicateList(int numTables) \r
+               throws StandardException\r
+       {\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Optimize this ProjectRestrictNode.  \r
+        *\r
+        * @param dataDictionary        The DataDictionary to use for optimization\r
+        * @param predicates            The PredicateList to optimize.  This should\r
+        *                                                      be a join predicate.\r
+        * @param outerRows                     The number of outer joining rows\r
+        *\r
+        * @return      ResultSetNode   The top of the optimized subtree\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public ResultSetNode optimize(DataDictionary dataDictionary,\r
+                                                                 PredicateList predicates,\r
+                                                                 double outerRows) \r
+                                       throws StandardException\r
+       {\r
+               /* We need to implement this method since a PRN can appear above a\r
+                * SelectNode in a query tree.\r
+                */\r
+               childResult = childResult.optimize(dataDictionary,\r
+                                                                                       restrictionList,\r
+                                                                                       outerRows);\r
+\r
+               Optimizer optimizer = getOptimizer(\r
+                                                               (FromList) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.FROM_LIST,\r
+                                                                       getNodeFactory().doJoinOrderOptimization(),\r
+                                                                       this,\r
+                                                                       getContextManager()),\r
+                                                               predicates,\r
+                                                               dataDictionary,\r
+                                                               (RequiredRowOrdering) null);\r
+\r
+               // RESOLVE: SHOULD FACTOR IN THE NON-OPTIMIZABLE PREDICATES THAT\r
+               // WERE NOT PUSHED DOWN\r
+               costEstimate = optimizer.newCostEstimate();\r
+\r
+               costEstimate.setCost(childResult.getCostEstimate().getEstimatedCost(),\r
+                                                       childResult.getCostEstimate().rowCount(),\r
+                                                       childResult.getCostEstimate().singleScanRowCount());\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Get the CostEstimate for this ProjectRestrictNode.\r
+        *\r
+        * @return      The CostEstimate for this ProjectRestrictNode, which is\r
+        *                      the cost estimate for the child node.\r
+        */\r
+       public CostEstimate getCostEstimate()\r
+       {\r
+               /*\r
+               ** The cost estimate will be set here if either optimize() or\r
+               ** optimizeIt() was called on this node.  It's also possible\r
+               ** that optimization was done directly on the child node,\r
+               ** in which case the cost estimate will be null here.\r
+               */\r
+               if (costEstimate == null)\r
+                       return childResult.getCostEstimate();\r
+               else\r
+               {\r
+                       return costEstimate;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Get the final CostEstimate for this ProjectRestrictNode.\r
+        *\r
+        * @return      The final CostEstimate for this ProjectRestrictNode, which is\r
+        *                      the final cost estimate for the child node.\r
+        */\r
+       public CostEstimate getFinalCostEstimate()\r
+               throws StandardException\r
+       {\r
+               if (finalCostEstimate != null)\r
+               // we already set it, so just return it.\r
+                       return finalCostEstimate;\r
+\r
+               // If the child result set is an Optimizable, then this node's\r
+               // final cost is that of the child.  Otherwise, this node must\r
+               // hold "trulyTheBestAccessPath" for it's child so we pull\r
+               // the final cost from there.\r
+               if (childResult instanceof Optimizable)\r
+                       finalCostEstimate = childResult.getFinalCostEstimate();\r
+               else\r
+                       finalCostEstimate = getTrulyTheBestAccessPath().getCostEstimate();\r
+\r
+               return finalCostEstimate;\r
+       }\r
+\r
+    /**\r
+     * For joins, the tree will be (nodes are left out if the clauses\r
+     * are empty):\r
+     *\r
+     *      ProjectRestrictResultSet -- for the having and the select list\r
+     *      SortResultSet -- for the group by list\r
+     *      ProjectRestrictResultSet -- for the where and the select list (if no group or having)\r
+     *      the result set for the fromList\r
+     *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+     */\r
+       public void generate(ActivationClassBuilder acb,\r
+                                                               MethodBuilder mb)\r
+                                                       throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+        SanityManager.ASSERT(resultColumns != null, "Tree structure bad");\r
+\r
+               generateMinion( acb, mb, false);\r
+       }\r
+\r
+       /**\r
+        * General logic shared by Core compilation.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public void generateResultSet(ExpressionClassBuilder acb,\r
+                                                                                  MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {\r
+               generateMinion( acb, mb, true);\r
+       }\r
+\r
+       /**\r
+        * Logic shared by generate() and generateResultSet().\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       private void generateMinion(ExpressionClassBuilder acb,\r
+                                                                        MethodBuilder mb, boolean genChildResultSet)\r
+                                                                       throws StandardException\r
+       {\r
+\r
+               /* If this ProjectRestrict doesn't do anything, bypass its generation.\r
+                * (Remove any true and true predicates first, as they could be left\r
+                * by the like transformation.)\r
+                */\r
+               if (restrictionList != null && restrictionList.size() > 0)\r
+               {\r
+                       restrictionList.eliminateBooleanTrueAndBooleanTrue();\r
+               }\r
+\r
+               if (nopProjectRestrict())\r
+               {\r
+                       generateNOPProjectRestrict();\r
+                       if (genChildResultSet)\r
+                               childResult.generateResultSet(acb, mb);\r
+                       else\r
+                               childResult.generate((ActivationClassBuilder)acb, mb);\r
+                       costEstimate = childResult.getFinalCostEstimate();\r
+                       return;\r
+               }\r
+\r
+               // build up the tree.\r
+\r
+               /* Put the predicates back into the tree */\r
+               if (restrictionList != null)\r
+               {\r
+                       constantRestriction = restrictionList.restoreConstantPredicates();\r
+                       // Remove any redundant predicates before restoring\r
+                       restrictionList.removeRedundantPredicates();\r
+                       restriction = restrictionList.restorePredicates();\r
+                       /* Allow the restrictionList to get garbage collected now\r
+                        * that we're done with it.\r
+                        */\r
+                       restrictionList = null;\r
+               }\r
+\r
+               // for the restriction, we generate an exprFun\r
+               // that evaluates the expression of the clause\r
+               // against the current row of the child's result.\r
+               // if the restriction is empty, simply pass null\r
+               // to optimize for run time performance.\r
+\r
+               // generate the function and initializer:\r
+               // Note: Boolean lets us return nulls (boolean would not)\r
+               // private Boolean exprN()\r
+               // {\r
+               //   return <<restriction.generate(ps)>>;\r
+               // }\r
+               // static Method exprN = method pointer to exprN;\r
+\r
+\r
+\r
+\r
+               // Map the result columns to the source columns\r
+               int[] mapArray = resultColumns.mapSourceColumns();\r
+               int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray));\r
+\r
+               /* Will this node do a projection? */\r
+               boolean doesProjection = true;\r
+\r
+               /* Does a projection unless same # of columns in same order\r
+                * as child.\r
+                */\r
+               if ( (! reflectionNeededForProjection()) && \r
+                   mapArray != null && \r
+                       mapArray.length == childResult.getResultColumns().size())\r
+               {\r
+                       /* mapArray entries are 1-based */\r
+                       int index = 0;\r
+                       for ( ; index < mapArray.length; index++)\r
+                       {\r
+                               if (mapArray[index] != index + 1)\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if (index == mapArray.length)\r
+                       {\r
+                               doesProjection = false;\r
+                       }\r
+               }\r
+\r
+\r
+\r
+               /* Generate the ProjectRestrictSet:\r
+                *      arg1: childExpress - Expression for childResultSet\r
+                *  arg2: Activation\r
+                *  arg3: restrictExpress - Expression for restriction\r
+                *  arg4: projectExpress - Expression for projection\r
+                *  arg5: resultSetNumber\r
+                *  arg6: constantExpress - Expression for constant restriction\r
+                *                      (for example, where 1 = 2)\r
+                *  arg7: mapArrayItem - item # for mapping of source columns\r
+                *  arg8: reuseResult - whether or not the result row can be reused\r
+                *                                              (ie, will it always be the same)\r
+                *  arg9: doesProjection - does this node do a projection\r
+                *  arg10: estimated row count\r
+                *  arg11: estimated cost\r
+                *  arg12: close method\r
+                */\r
+\r
+               acb.pushGetResultSetFactoryExpression(mb);\r
+               if (genChildResultSet)\r
+                       childResult.generateResultSet(acb, mb);\r
+               else\r
+                       childResult.generate((ActivationClassBuilder)acb, mb);\r
+\r
+               /* Get the next ResultSet #, so that we can number this ResultSetNode, its\r
+                * ResultColumnList and ResultSet.\r
+                */\r
+               assignResultSetNumber();\r
+               \r
+               /* Set the point of attachment in all subqueries attached\r
+                * to this node.\r
+                */\r
+               if (projectSubquerys != null && projectSubquerys.size() > 0)\r
+               {\r
+                       projectSubquerys.setPointOfAttachment(resultSetNumber);\r
+               }\r
+               if (restrictSubquerys != null && restrictSubquerys.size() > 0)\r
+               {\r
+                       restrictSubquerys.setPointOfAttachment(resultSetNumber);\r
+               }\r
+\r
+               // Load our final cost estimate.\r
+               costEstimate = getFinalCostEstimate();\r
+\r
+               // if there is no restriction, we just want to pass null.\r
+               if (restriction == null)\r
+               {\r
+                       mb.pushNull(ClassName.GeneratedMethod);\r
+               }\r
+               else\r
+               {\r
+                       // this sets up the method and the static field.\r
+                       // generates:\r
+                       //      Object userExprFun { }\r
+                       MethodBuilder userExprFun = acb.newUserExprFun();\r
+\r
+                       // restriction knows it is returning its value;\r
+\r
+                       /* generates:\r
+                        *    return  <restriction.generate(acb)>;\r
+                        * and adds it to userExprFun\r
+                        * NOTE: The explicit cast to DataValueDescriptor is required\r
+                        * since the restriction may simply be a boolean column or subquery\r
+                        * which returns a boolean.  For example:\r
+                        *              where booleanColumn\r
+                        */\r
+                       restriction.generateExpression(acb, userExprFun);\r
+                       userExprFun.methodReturn();\r
+\r
+                       // we are done modifying userExprFun, complete it.\r
+                       userExprFun.complete();\r
+\r
+                       // restriction is used in the final result set as an access of the new static\r
+                       // field holding a reference to this new method.\r
+                       // generates:\r
+                       //      ActivationClass.userExprFun\r
+                       // which is the static field that "points" to the userExprFun\r
+                       // that evaluates the where clause.\r
+                       acb.pushMethodReference(mb, userExprFun);\r
+               }\r
+\r
+               /* Determine whether or not reflection is needed for the projection.\r
+                * Reflection is not needed if all of the columns map directly to source\r
+                * columns.\r
+                */\r
+               if (reflectionNeededForProjection())\r
+               {\r
+                       // for the resultColumns, we generate a userExprFun\r
+                       // that creates a new row from expressions against\r
+                       // the current row of the child's result.\r
+                       // (Generate optimization: see if we can simply\r
+                       // return the current row -- we could, but don't, optimize\r
+                       // the function call out and have execution understand\r
+                       // that a null function pointer means take the current row\r
+                       // as-is, with the performance trade-off as discussed above.)\r
+\r
+                       /* Generate the Row function for the projection */\r
+                       resultColumns.generateCore(acb, mb, false);\r
+               }\r
+               else\r
+               {\r
+                       mb.pushNull(ClassName.GeneratedMethod);\r
+               }\r
+               \r
+               mb.push(resultSetNumber);\r
+\r
+               // if there is no constant restriction, we just want to pass null.\r
+               if (constantRestriction == null)\r
+               {\r
+                       mb.pushNull(ClassName.GeneratedMethod);\r
+               }\r
+               else\r
+               {\r
+                       // this sets up the method and the static field.\r
+                       // generates:\r
+                       //      userExprFun { }\r
+                       MethodBuilder userExprFun = acb.newUserExprFun();\r
+\r
+                       // restriction knows it is returning its value;\r
+\r
+                       /* generates:\r
+                        *    return <restriction.generate(acb)>;\r
+                        * and adds it to userExprFun\r
+                        * NOTE: The explicit cast to DataValueDescriptor is required\r
+                        * since the restriction may simply be a boolean column or subquery\r
+                        * which returns a boolean.  For example:\r
+                        *              where booleanColumn\r
+                        */\r
+                       constantRestriction.generateExpression(acb, userExprFun);\r
+\r
+                       userExprFun.methodReturn();\r
+\r
+                       // we are done modifying userExprFun, complete it.\r
+                       userExprFun.complete();\r
+\r
+                       // restriction is used in the final result set as an access\r
+                       // of the new static field holding a reference to this new method.\r
+                       // generates:\r
+                       //      ActivationClass.userExprFun\r
+                       // which is the static field that "points" to the userExprFun\r
+                       // that evaluates the where clause.\r
+                       acb.pushMethodReference(mb, userExprFun);\r
+               }\r
+               \r
+               mb.push(mapArrayItem);\r
+               mb.push(resultColumns.reusableResult());\r
+               mb.push(doesProjection);\r
+               mb.push(costEstimate.rowCount());\r
+               mb.push(costEstimate.getEstimatedCost());\r
+\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getProjectRestrictResultSet",\r
+                                       ClassName.NoPutResultSet, 10);\r
+       }\r
+\r
+       /**\r
+        * Determine whether this ProjectRestrict does anything.  If it doesn't\r
+        * filter out any rows or columns, it's a No-Op.\r
+        *\r
+        * @return      true if this ProjectRestrict is a No-Op.\r
+        */\r
+       boolean nopProjectRestrict()\r
+       {\r
+               /*\r
+               ** This ProjectRestrictNode is not a No-Op if it does any\r
+               ** restriction.\r
+               */\r
+               if ( (restriction != null) ||\r
+                        (restrictionList != null && restrictionList.size() > 0) )\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               ResultColumnList        childColumns = childResult.getResultColumns();\r
+               ResultColumnList        PRNColumns = this.getResultColumns();\r
+\r
+               /*\r
+               ** The two lists have the same numbers of elements.  Are the lists\r
+               ** identical?  In other words, is the expression in every ResultColumn\r
+               ** in the PRN's RCL a ColumnReference that points to the same-numbered\r
+               ** column?\r
+               */\r
+               if (PRNColumns.nopProjection(childColumns))\r
+                       return true;\r
+\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Bypass the generation of this No-Op ProjectRestrict, and just generate\r
+        * its child result set.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void generateNOPProjectRestrict()\r
+                       throws StandardException\r
+       {\r
+               this.getResultColumns().setRedundant();\r
+       }\r
+\r
+       /**\r
+        * Consider materialization for this ResultSet tree if it is valid and cost effective\r
+        * (It is not valid if incorrect results would be returned.)\r
+        *\r
+        * @return Top of the new/same ResultSet tree.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ResultSetNode considerMaterialization(JBitSet outerTables)\r
+               throws StandardException\r
+       {\r
+               childResult = childResult.considerMaterialization(outerTables);\r
+               if (childResult.performMaterialization(outerTables))\r
+               {\r
+                       MaterializeResultSetNode        mrsn;\r
+                       ResultColumnList                        prRCList;\r
+\r
+                       /* If the restriction contians a ColumnReference from another\r
+                        * table then the MRSN must go above the childResult.  Otherwise we can put\r
+                        * it above ourselves. (The later is optimal since projection and restriction \r
+                        * will only happen once.)\r
+                        * Put MRSN above PRN if any of the following are true:\r
+                        *      o  PRN doesn't have a restriction list\r
+                        *      o  PRN's restriction list is empty \r
+                        *  o  Table's referenced in PRN's restriction list are a subset of\r
+                        *         table's referenced in PRN's childResult.  (NOTE: Rather than construct\r
+                        *     a new, empty JBitSet before checking, we simply clone the childResult's\r
+                        *         referencedTableMap.  This is done for code simplicity and will not \r
+                        *         affect the result.)\r
+                        */\r
+                       ReferencedTablesVisitor rtv = new ReferencedTablesVisitor(\r
+                                                                                               (JBitSet) childResult.getReferencedTableMap().clone());\r
+                       boolean emptyRestrictionList = (restrictionList == null || restrictionList.size() == 0);\r
+                       if (! emptyRestrictionList)\r
+                       {\r
+                               restrictionList.accept(rtv);\r
+                       }\r
+                       if (emptyRestrictionList ||\r
+                               childResult.getReferencedTableMap().contains(rtv.getTableMap()))\r
+                       {\r
+                               /* We get a shallow copy of the ResultColumnList and its \r
+                                * ResultColumns.  (Copy maintains ResultColumn.expression for now.)\r
+                                */\r
+                               prRCList = resultColumns;\r
+                               setResultColumns(resultColumns.copyListAndObjects());\r
+\r
+                               /* Replace ResultColumn.expression with new VirtualColumnNodes\r
+                                * in the NormalizeResultSetNode's ResultColumnList.  (VirtualColumnNodes include\r
+                                * pointers to source ResultSetNode, this, and source ResultColumn.)\r
+                                */\r
+                               prRCList.genVirtualColumnNodes(this, resultColumns);\r
+\r
+                               /* Finally, we create the new MaterializeResultSetNode */\r
+                               mrsn = (MaterializeResultSetNode) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.MATERIALIZE_RESULT_SET_NODE,\r
+                                                                       this,\r
+                                                                       prRCList,\r
+                                                                       tableProperties,\r
+                                                                       getContextManager());\r
+                               // Propagate the referenced table map if it's already been created\r
+                               if (referencedTableMap != null)\r
+                               {\r
+                                       mrsn.setReferencedTableMap((JBitSet) referencedTableMap.clone());\r
+                               }\r
+                               return mrsn;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* We get a shallow copy of the ResultColumnList and its \r
+                                * ResultColumns.  (Copy maintains ResultColumn.expression for now.)\r
+                                */\r
+                               prRCList = childResult.getResultColumns();\r
+                               childResult.setResultColumns(prRCList.copyListAndObjects());\r
+\r
+                               /* Replace ResultColumn.expression with new VirtualColumnNodes\r
+                                * in the MaterializeResultSetNode's ResultColumnList.  (VirtualColumnNodes include\r
+                                * pointers to source ResultSetNode, this, and source ResultColumn.)\r
+                                */\r
+                               prRCList.genVirtualColumnNodes(childResult, childResult.getResultColumns());\r
+\r
+                               /* RESOLVE - we need to push single table predicates down so that\r
+                                * they get applied while building the MaterializeResultSet.\r
+                                */\r
+\r
+                               /* Finally, we create the new MaterializeResultSetNode */\r
+                               mrsn = (MaterializeResultSetNode) getNodeFactory().getNode(\r
+                                                                       C_NodeTypes.MATERIALIZE_RESULT_SET_NODE,\r
+                                                                       childResult,\r
+                                                                       prRCList,\r
+                                                                       tableProperties,\r
+                                                                       getContextManager());\r
+                               // Propagate the referenced table map if it's already been created\r
+                               if (childResult.getReferencedTableMap() != null)\r
+                               {\r
+                                       mrsn.setReferencedTableMap((JBitSet) childResult.getReferencedTableMap().clone());\r
+                               }\r
+                               childResult = mrsn;\r
+                       }\r
+               }\r
+\r
+               return this;\r
+       }\r
+\r
+       /** \r
+        * Determine whether or not the specified name is an exposed name in\r
+        * the current query block.\r
+        *\r
+        * @param name  The specified name to search for as an exposed name.\r
+        * @param schemaName    Schema name, if non-null.\r
+        * @param exactMatch    Whether or not we need an exact match on specified schema and table\r
+        *                                              names or match on table id.\r
+        *\r
+        * @return The FromTable, if any, with the exposed name.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch)\r
+               throws StandardException\r
+       {\r
+               return childResult.getFromTableByName(name, schemaName, exactMatch);\r
+       }\r
+\r
+       /**\r
+        * Get the lock mode for the target of an update statement\r
+        * (a delete or update).  The update mode will always be row for\r
+        * CurrentOfNodes.  It will be table if there is no where clause.\r
+        *\r
+        * @return      The lock mode\r
+        */\r
+       public int updateTargetLockMode()\r
+       {\r
+               if (restriction != null || constantRestriction != null)\r
+               {\r
+                       return TransactionController.MODE_RECORD;\r
+               }\r
+               else\r
+               {\r
+                       return childResult.updateTargetLockMode();\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Is it possible to do a distinct scan on this ResultSet tree.\r
+        * (See SelectNode for the criteria.)\r
+        *\r
+        * @param distinctColumns the set of distinct columns\r
+        * @return Whether or not it is possible to do a distinct scan on this ResultSet tree.\r
+        */\r
+       boolean isPossibleDistinctScan(Set distinctColumns)\r
+       {\r
+               if (restriction != null || \r
+                       (restrictionList != null && restrictionList.size() != 0))\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               HashSet columns = new HashSet();\r
+               for (int i = 0; i < resultColumns.size(); i++) {\r
+                       ResultColumn rc = (ResultColumn) resultColumns.elementAt(i);\r
+                       BaseColumnNode bc = rc.getBaseColumnNode();\r
+                       if (bc == null) return false;\r
+                       columns.add(bc);\r
+               }\r
+\r
+               return columns.equals(distinctColumns) && childResult.isPossibleDistinctScan(distinctColumns);\r
+       }\r
+\r
+       /**\r
+        * Mark the underlying scan as a distinct scan.\r
+        */\r
+       void markForDistinctScan()\r
+       {\r
+               childResult.markForDistinctScan();\r
+       }\r
+\r
+\r
+       /**\r
+        * Accept a visitor, and call v.visit()\r
+        * on child nodes as necessary.  \r
+        * \r
+        * @param v the visitor\r
+        *\r
+        * @exception StandardException on error\r
+        */\r
+       public Visitable accept(Visitor v) \r
+               throws StandardException\r
+       {\r
+               if (v.skipChildren(this))\r
+               {\r
+                       return v.visit(this);\r
+               }\r
+\r
+               Visitable returnNode = super.accept(v);\r
+\r
+               if (restriction != null && !v.stopTraversal())\r
+               {\r
+                       restriction = (ValueNode)restriction.accept(v);\r
+               }\r
+\r
+               if (restrictionList != null && !v.stopTraversal())\r
+               {\r
+                       restrictionList = (PredicateList)restrictionList.accept(v);\r
+               }\r
+\r
+               return returnNode;\r
+       }\r
+\r
+\r
+\r
+       /**\r
+        * set the Information gathered from the parent table that is \r
+        * required to peform a referential action on dependent table.\r
+        */\r
+       public void setRefActionInfo(long fkIndexConglomId, \r
+                                                                int[]fkColArray, \r
+                                                                String parentResultSetId,\r
+                                                                boolean dependentScan)\r
+       {\r
+               childResult.setRefActionInfo(fkIndexConglomId,\r
+                                                                  fkColArray,\r
+                                                                  parentResultSetId,\r
+                                                                  dependentScan);\r
+       }\r
+\r
+       public void setRestriction(ValueNode restriction) {\r
+               this.restriction = restriction;\r
+       }\r
+\r
+}\r