/*

   Derby - Class org.apache.derby.impl.sql.compile.ProjectRestrictNode

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */

package	org.apache.derby.impl.sql.compile;

import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import org.apache.derby.catalog.UUID;
import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.reference.ClassName;
import org.apache.derby.iapi.services.classfile.VMOpcode;
import org.apache.derby.iapi.services.compiler.MethodBuilder;
import org.apache.derby.iapi.services.context.ContextManager;
import org.apache.derby.shared.common.sanity.SanityManager;
import org.apache.derby.iapi.sql.compile.AccessPath;
import org.apache.derby.iapi.sql.compile.CostEstimate;
import org.apache.derby.iapi.sql.compile.Optimizable;
import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
import org.apache.derby.iapi.sql.compile.Optimizer;
import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
import org.apache.derby.iapi.sql.compile.RowOrdering;
import org.apache.derby.iapi.sql.compile.Visitor;
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.util.JBitSet;

/**
 * A ProjectRestrictNode represents a result set for any of the basic DML
 * operations: SELECT, INSERT, UPDATE, and DELETE.  For INSERT with
 * a VALUES clause, restriction will be null. For both INSERT and UPDATE,
 * the resultColumns in the selectList will contain the names of the columns
 * being inserted into or updated.
 *
 * NOTE: A ProjectRestrictNode extends FromTable since it can exist in a FromList.
 *
 */

class ProjectRestrictNode extends SingleChildResultSetNode
{
	/**
	 * The ValueNode for the restriction to be evaluated here.
	 */
    ValueNode   restriction;

	/**
	 * Constant expressions to be evaluated here.
	 */
	ValueNode	constantRestriction = null;

	/**
	 * Restriction as a PredicateList
	 */
    PredicateList restrictionList;

	/**
	 * List of subqueries in projection
	 */
	SubqueryList projectSubquerys;

	/**
	 * List of subqueries in restriction
	 */
	SubqueryList restrictSubquerys;

	private boolean accessPathModified;

	/* Should we get the table number from this node,
	 * regardless of the class of our child.
	 */
	private boolean getTableNumberHere;

    /**
     * Used with {@code validatingBaseTableCID} to validating deferred check
     * constraints.
     */
    private boolean validatingCheckConstraints = false;
    private String validatingBaseTableUUIDString;
	/**
     * Constructor for a ProjectRestrictNode.
	 *
	 * @param childResult	The child ResultSetNode
	 * @param projection	The result column list for the projection
	 * @param restriction	An expression representing the restriction to be 
	 *					    evaluated here.
	 * @param restrictionList Restriction as a PredicateList
	 * @param projectSubquerys List of subqueries in the projection
	 * @param restrictSubquerys List of subqueries in the restriction
	 * @param tableProperties	Properties list associated with the table
     * @param cm            The context manager
	 */

    ProjectRestrictNode(ResultSetNode    childResult,
                        ResultColumnList projection,
                        ValueNode        restriction,
                        PredicateList    restrictionList,
                        SubqueryList     projectSubquerys,
                        SubqueryList     restrictSubquerys,
                        Properties       tableProperties,
                        ContextManager   cm)
	{
        super(childResult, tableProperties, cm);
        setResultColumns( projection );
        this.restriction = restriction;
        this.restrictionList = restrictionList;
        this.projectSubquerys = projectSubquerys;
        this.restrictSubquerys = restrictSubquerys;

		/* A PRN will only hold the tableProperties for
		 * a result set tree if its child is not an
		 * optimizable.  Otherwise, the properties will
		 * be transferred down to the child.
		 */
		if (tableProperties != null &&
			 (childResult instanceof Optimizable))
		{
			((Optimizable) childResult).setProperties(getProperties());
			setProperties((Properties) null);
		}
	}

	/*
	 *  Optimizable interface
	 */

	/**
		@see Optimizable#nextAccessPath
		@exception StandardException	Thrown on error
	 */
    @Override
	public boolean nextAccessPath(Optimizer optimizer,
									OptimizablePredicateList predList,
									RowOrdering rowOrdering)
			throws StandardException
	{
		/*
		** If the child result set is an optimizable, let it choose its next
		** access path.  If it is not an optimizable, we have to tell the
		** caller that there is an access path the first time we are called
		** for this position in the join order, and that there are no more
		** access paths for subsequent calls for this position in the join
		** order.  The startOptimizing() method is called once on each
		** optimizable when it is put into a join position.
		*/
		if (childResult instanceof Optimizable)
		{
			return ((Optimizable) childResult).nextAccessPath(optimizer,
																restrictionList,
																rowOrdering);
		}
		else
		{
			return super.nextAccessPath(optimizer, predList, rowOrdering);
		}
	}

	/** @see Optimizable#rememberAsBest 
		@exception StandardException	Thrown on error
	 */
    @Override
	public void rememberAsBest(int planType, Optimizer optimizer)
		throws StandardException
	{
		super.rememberAsBest(planType, optimizer);
		if (childResult instanceof Optimizable)
			((Optimizable) childResult).rememberAsBest(planType, optimizer);
	}

	/** @see Optimizable#startOptimizing */
    @Override
	public void startOptimizing(Optimizer optimizer, RowOrdering rowOrdering)
	{
		if (childResult instanceof Optimizable)
		{
			((Optimizable) childResult).startOptimizing(optimizer, rowOrdering);
		}
		else
		{
			super.startOptimizing(optimizer, rowOrdering);
		}
	}

	/** @see Optimizable#getTableNumber */
    @Override
	public int getTableNumber()
	{
		/* GROSS HACK - We need to get the tableNumber after
		 * calling modifyAccessPaths() on the child when doing
		 * a hash join on an arbitrary result set.  The problem
		 * is that the child will always be an optimizable at this
		 * point.  So, we 1st check to see if we should get it from
		 * this node.  (We set the boolean to true in the appropriate
		 * place in modifyAccessPaths().)
		 */
		if (getTableNumberHere)
		{
			return super.getTableNumber();
		}

		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).getTableNumber();

		return super.getTableNumber();
	}

	/**
	 * @see Optimizable#optimizeIt
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public CostEstimate optimizeIt(
							Optimizer optimizer,
							OptimizablePredicateList predList,
							CostEstimate outerCost,
							RowOrdering rowOrdering)
			throws StandardException
	{
		/*
		** RESOLVE: Most types of Optimizables only implement estimateCost(),
		** and leave it up to optimizeIt() in FromTable to figure out the
		** total cost of the join.  A ProjectRestrict can have a non-Optimizable
		** child, though, in which case we want to tell the child the
		** number of outer rows - it could affect the join strategy
		** significantly.  So we implement optimizeIt() here, which overrides
		** the optimizeIt() in FromTable.  This assumes that the join strategy
		** for which this join node is the inner table is a nested loop join,
		** which will not be a valid assumption when we implement other
		** strategies like materialization (hash join can work only on
		** base tables).  The join strategy for a base table under a
		** ProjectRestrict is set in the base table itself.
		*/

		CostEstimate childCost;

		setCostEstimate( getCostEstimate( optimizer ) );

		/*
		** Don't re-optimize a child result set that has already been fully
		** optimized.  For example, if the child result set is a SelectNode,
		** it will be changed to a ProjectRestrictNode, which we don't want
		** to re-optimized.
		*/
		// NOTE: TO GET THE RIGHT COST, THE CHILD RESULT MAY HAVE TO BE
		// OPTIMIZED MORE THAN ONCE, BECAUSE THE NUMBER OF OUTER ROWS
		// MAY BE DIFFERENT EACH TIME.
		// if (childResultOptimized)
		// 	return costEstimate;

		// It's possible that a call to optimize the left/right will cause
		// a new "truly the best" plan to be stored in the underlying base
		// tables.  If that happens and then we decide to skip that plan
		// (which we might do if the call to "considerCost()" below decides
		// the current path is infeasible or not the best) we need to be
		// able to revert back to the "truly the best" plans that we had
		// saved before we got here.  So with this next call we save the
		// current plans using "this" node as the key.  If needed, we'll
		// then make the call to revert the plans in OptimizerImpl's
		// getNextDecoratedPermutation() method.
		updateBestPlanMap(ADD_PLAN, this);

		/* If the childResult is instanceof Optimizable, then we optimizeIt.
		 * Otherwise, we are going into a new query block.  If the new query
		 * block has already had its access path modified, then there is
		 * nothing to do.  Otherwise, we must begin the optimization process
		 * anew on the new query block.
		 */
		if (childResult instanceof Optimizable)
		{
			childCost = ((Optimizable) childResult).optimizeIt(
															optimizer,
															restrictionList,
															outerCost,
															rowOrdering);
			/* Copy child cost to this node's cost */
			getCostEstimate().setCost(
							childCost.getEstimatedCost(),
							childCost.rowCount(),
							childCost.singleScanRowCount());


			// Note: we don't call "optimizer.considerCost()" here because
			// a) the child will make that call as part of its own
			// "optimizeIt()" work above, and b) the child might have
			// different criteria for "considering" (i.e. rejecting or
			// accepting) a plan's cost than this ProjectRestrictNode does--
			// and we don't want to override the child's decision.  So as
			// with most operations in this class, if the child is an
			// Optimizable, we just let it do its own work and make its
			// own decisions.
		}
		else if ( ! accessPathModified)
		{
			if (SanityManager.DEBUG)
			{
				if (! ((childResult instanceof SelectNode) ||
								 (childResult instanceof RowResultSetNode)))
				{
					SanityManager.THROWASSERT(
						"childResult is expected to be instanceof " +
						"SelectNode or RowResultSetNode - it is a " +
						childResult.getClass().getName());
				}
			}
			childResult = childResult.optimize(optimizer.getDataDictionary(), 
											   restrictionList,
											   outerCost.rowCount());

			/* Copy child cost to this node's cost */
			childCost = childResult.getCostEstimate();

			getCostEstimate().setCost(
							childCost.getEstimatedCost(),
							childCost.rowCount(),
							childCost.singleScanRowCount());

			/* Note: Prior to the fix for DERBY-781 we had calls here
			 * to set the cost estimate for BestAccessPath and
			 * BestSortAvoidancePath to equal costEstimate.  That used
			 * to be okay because prior to DERBY-781 we would only
			 * get here once (per join order) for a given SelectNode/
			 * RowResultSetNode and thus we could safely say that the
			 * costEstimate from the most recent call to "optimize()"
			 * was the best one so far (because we knew that we would
			 * only call childResult.optimize() once).  Now that we
			 * support hash joins with subqueries, though, we can get
			 * here twice per join order: once when the optimizer is
			 * considering a nested loop join with this PRN, and once
			 * when it is considering a hash join.  This means we can't
			 * just arbitrarily use the cost estimate for the most recent
			 * "optimize()" as the best cost because that may not
			 * be accurate--it's possible that the above call to
			 * childResult.optimize() was for a hash join, but that
			 * we were here once before (namely for nested loop) and
			 * the cost of the nested loop is actually less than
			 * the cost of the hash join.  In that case it would
			 * be wrong to use costEstimate as the cost of the "best"
			 * paths because it (costEstimate) holds the cost of
			 * the hash join, not of the nested loop join.  So with
			 * DERBY-781 the following calls were removed:
			 *   getBestAccessPath().setCostEstimate(costEstimate);
			 *   getBestSortAvoidancePath().setCostEstimate(costEstimate);
			 * If costEstimate *does* actually hold the estimate for
			 * the best path so far, then we will set BestAccessPath
			 * and BestSortAvoidancePath as needed in the following
			 * call to "considerCost".
			 */

			// childResultOptimized = true;

			/* RESOLVE - ARBITRARYHASHJOIN - Passing restriction list here, as above, is correct.
			 * However,  passing predList makes the following work:
			 *	select * from t1, (select * from t2) c properties joinStrategy = hash where t1.c1 = c.c1;
			 * The following works with restrictionList:
			 *	select * from t1, (select c1 + 0 from t2) c(c1) properties joinStrategy = hash where t1.c1 = c.c1;
			 */
			optimizer.considerCost(this, restrictionList, getCostEstimate(), outerCost);
		}

		return getCostEstimate();
	}

	/**
	 * @see Optimizable#feasibleJoinStrategy
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public boolean feasibleJoinStrategy(OptimizablePredicateList predList,
										Optimizer optimizer)
					throws StandardException
	{
		AccessPath ap;

		/* The child being an Optimizable is a special case.  In that
		 * case, we want to get the current access path and join strategy
		 * from the child.  Otherwise, we want to get it from this node.
		 */
		if (childResult instanceof Optimizable)
		{
			// With DERBY-805 it's possible that, when considering a nested
			// loop join with this PRN, we pushed predicates down into the
			// child if the child is a UNION node.  At this point, though, we
			// may be considering doing a hash join with this PRN instead of a
			// nested loop join, and if that's the case we need to pull any
			// predicates back up so that they can be searched for equijoins
			// that will in turn make the hash join possible.  So that's what
			// the next call does.  Two things to note: 1) if no predicates
			// were pushed, this call is a no-op; and 2) if we get here when
			// considering a nested loop join, the predicates that we pull
			// here (if any) will be re-pushed for subsequent costing/ 
			// optimization as necessary (see OptimizerImpl.costPermutation(),
			// which will call this class's optimizeIt() method and that's
			// where the predicates are pushed down again).
			if (childResult instanceof UnionNode)
				((UnionNode)childResult).pullOptPredicates(restrictionList);

			return ((Optimizable) childResult).
				feasibleJoinStrategy(restrictionList, optimizer);
		}
		else
		{
			return super.feasibleJoinStrategy(restrictionList, optimizer);
		}
	}

	/** @see Optimizable#getCurrentAccessPath */
    @Override
	public AccessPath getCurrentAccessPath()
	{
		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).getCurrentAccessPath();

		return super.getCurrentAccessPath();
	}

	/** @see Optimizable#getBestAccessPath */
    @Override
	public AccessPath getBestAccessPath()
	{
		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).getBestAccessPath();

		return super.getBestAccessPath();
	}

	/** @see Optimizable#getBestSortAvoidancePath */
    @Override
	public AccessPath getBestSortAvoidancePath()
	{
		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).getBestSortAvoidancePath();

		return super.getBestSortAvoidancePath();
	}

	/** @see Optimizable#getTrulyTheBestAccessPath */
    @Override
	public AccessPath getTrulyTheBestAccessPath()
	{
		/* The childResult will always be an Optimizable
		 * during code generation.  If the childResult was
		 * not an Optimizable during optimization, then this node
		 * will have the truly the best access path, so we want to
		 * return it from this node, rather than traversing the tree.
		 * This can happen for non-flattenable derived tables.
		 * Anyway, we note this state when modifying the access paths.
		 */
		if (hasTrulyTheBestAccessPath)
		{
			return super.getTrulyTheBestAccessPath();
		}

		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).getTrulyTheBestAccessPath();

		return super.getTrulyTheBestAccessPath();
	}

	/** @see Optimizable#rememberSortAvoidancePath */
    @Override
	public void rememberSortAvoidancePath()
	{
		if (childResult instanceof Optimizable)
			((Optimizable) childResult).rememberSortAvoidancePath();
		else
			super.rememberSortAvoidancePath();
	}

	/** @see Optimizable#considerSortAvoidancePath */
    @Override
	public boolean considerSortAvoidancePath()
	{
		if (childResult instanceof Optimizable)
			return ((Optimizable) childResult).considerSortAvoidancePath();

		return super.considerSortAvoidancePath();
	}

	/**
	 * @see Optimizable#pushOptPredicate
	 *
	 * @exception StandardException		Thrown on error
	 */

    @Override
	public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate)
			throws StandardException
	{
		if (SanityManager.DEBUG)
		{
			SanityManager.ASSERT(optimizablePredicate instanceof Predicate,
				"optimizablePredicate expected to be instanceof Predicate");
			SanityManager.ASSERT(! optimizablePredicate.hasSubquery() &&
								 ! optimizablePredicate.hasMethodCall(),
				"optimizablePredicate either has a subquery or a method call");
		}

		/* Add the matching predicate to the restrictionList */
		if (restrictionList == null)
		{
            restrictionList = new PredicateList(getContextManager());
		}
		restrictionList.addPredicate((Predicate) optimizablePredicate);

		/* Remap all of the ColumnReferences to point to the
		 * source of the values.
		 */
		Predicate pred = (Predicate)optimizablePredicate;

		/* If the predicate is scoped then the call to "remapScopedPred()"
		 * will do the necessary remapping for us and will return true;
		 * otherwise, we'll just do the normal remapping here.
		 */
		if (!pred.remapScopedPred())
		{
			RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
			pred.getAndNode().accept(rcrv);
		}

		return true;
	}

	/**
	 * @see Optimizable#pullOptPredicates
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public void pullOptPredicates(
								OptimizablePredicateList optimizablePredicates)
					throws StandardException
	{
        // DERBY-4001: Don't pull predicates if this node is part of a NOT
        // EXISTS join. For example, in the query below, if we allowed the
        // predicate 1<>1 (always false) to be pulled, no rows would be
        // returned, whereas it should return all the rows in table T.
        // SELECT * FROM T WHERE NOT EXISTS (SELECT * FROM T WHERE 1<>1)
		if (restrictionList != null && !isNotExists())
		{
			// Pull up any predicates that may have been pushed further
			// down the tree during optimization.
			if (childResult instanceof UnionNode)
				((UnionNode)childResult).pullOptPredicates(restrictionList);

			RemapCRsVisitor rcrv = new RemapCRsVisitor(false);
			for (int i = restrictionList.size() - 1; i >= 0; i--)
			{
				OptimizablePredicate optPred =
					restrictionList.getOptPredicate(i);
				((Predicate) optPred).getAndNode().accept(rcrv);
				optimizablePredicates.addOptPredicate(optPred);
				restrictionList.removeOptPredicate(i);
			}
		}
	}

	/**
	 * @see Optimizable#modifyAccessPath
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public Optimizable modifyAccessPath(JBitSet outerTables) 
		throws StandardException
	{
		boolean origChildOptimizable = true;

		/* It is okay to optimize most nodes multiple times.  However,
		 * modifying the access path is something that should only be done
		 * once per node.  One reason for this is that the predicate list
		 * will be empty after the 1st call, and we assert that it should
		 * be non-empty.  Multiple calls to modify the access path can
		 * occur when there is a non-flattenable FromSubquery (or view).
		 */
		if (accessPathModified)
		{
			return this;
		}

		/*
		** Do nothing if the child result set is not optimizable, as there
		** can be nothing to modify.
		*/
		boolean alreadyPushed = false;
		if ( ! (childResult instanceof Optimizable))
		{
			// Remember that the original child was not Optimizable
			origChildOptimizable = false;

			/* When we optimized the child we passed in our restriction list
			 * so that scoped predicates could be pushed further down the
			 * tree.  We need to do the same when modifying the access
			 * paths to ensure we generate the same plans the optimizer
			 * chose.
			 */
			childResult = childResult.modifyAccessPaths(restrictionList);

			/* Mark this node as having the truly ... for
			 * the underlying tree.
			 */
			hasTrulyTheBestAccessPath = true;

			/* Replace this PRN with a HRN if we are doing a hash join */
			if (trulyTheBestAccessPath.getJoinStrategy().isHashJoin())
			{
				if (SanityManager.DEBUG)
				{
					SanityManager.ASSERT(restrictionList != null,
						"restrictionList expected to be non-null");
					SanityManager.ASSERT(restrictionList.size() != 0,
							"restrictionList.size() expected to be non-zero");
				}
				/* We're doing a hash join on an arbitary result set.
				 * We need to get the table number from this node when
				 * dividing up the restriction list for a hash join.
				 * We need to explicitly remember this.
				 */
				getTableNumberHere = true;
			}
			else
			{
				/* We consider materialization into a temp table as a last step.
				 * Currently, we only materialize VTIs that are inner tables
				 * and can't be instantiated multiple times.  In the future we
				 * will consider materialization as a cost based option.
				 */
				return (Optimizable) considerMaterialization(outerTables);
			}
		}

		/* If the child is not a FromBaseTable, then we want to
		 * keep going down the tree.  (Nothing to do at this node.)
		 */
		else if (!(childResult instanceof FromBaseTable))
		{
			/* Make sure that we have a join strategy */
			if (trulyTheBestAccessPath.getJoinStrategy() == null)
			{
				trulyTheBestAccessPath = (AccessPathImpl) ((Optimizable) childResult).getTrulyTheBestAccessPath();
			}

			// If the childResult is a SetOperatorNode (esp. a UnionNode),
			// then it's possible that predicates in our restrictionList are
			// supposed to be pushed further down the tree (as of DERBY-805).
			// We passed the restrictionList down when we optimized the child
			// so that the relevant predicates could be pushed further as part
			// of the optimization process; so now that we're finalizing the
			// paths, we need to do the same thing: i.e. pass restrictionList
			// down so that the predicates that need to be pushed further
			// _can_ be pushed further.
			if (childResult instanceof SetOperatorNode) {
				childResult = (ResultSetNode)
					((SetOperatorNode) childResult).modifyAccessPath(
						outerTables, restrictionList);

				// Take note of the fact that we already pushed predicates
				// as part of the modifyAccessPaths call.  This is necessary
				// because there may still be predicates in restrictionList
				// that we intentionally decided not to push (ex. if we're
				// going to do hash join then we chose to not push the join
				// predicates).  Whatever the reason for not pushing the
				// predicates, we have to make sure we don't inadvertenly
				// push them later (esp. as part of the "pushUsefulPredicates"
				// call below).
				alreadyPushed = true;
			}
			else {
				childResult = 
					(ResultSetNode) ((FromTable) childResult).
						modifyAccessPath(outerTables);
			}
		}

		// If we're doing a hash join with _this_ PRN (as opposed to
		// with this PRN's child) then we don't attempt to push
		// predicates down.  There are two reasons for this: 1)
		// we don't want to push the equijoin predicate that is
		// required for the hash join, and 2) if we're doing a
		// hash join then we're going to materialize this node,
		// but if we push predicates before materialization, we
		// can end up with incorrect results (esp. missing rows).
		// So don't push anything in this case.
		boolean hashJoinWithThisPRN = hasTrulyTheBestAccessPath &&
			(trulyTheBestAccessPath.getJoinStrategy() != null) &&
			trulyTheBestAccessPath.getJoinStrategy().isHashJoin();

        if ((restrictionList != null) &&
            !alreadyPushed &&
            !hashJoinWithThisPRN &&
            !validatingCheckConstraints)
		{
			restrictionList.pushUsefulPredicates((Optimizable) childResult);
		}

		/*
		** The optimizer's decision on the access path for the child result
		** set may require the generation of extra result sets.  For
		** example, if it chooses an index, we need an IndexToBaseRowNode
		** above the FromBaseTable (and the FromBaseTable has to change
		** its column list to match that of the index.
		*/
		if (origChildOptimizable)
		{
			childResult = childResult.changeAccessPath();
		}
		accessPathModified = true;

		/*
		** Replace this PRN with a HTN if a hash join
		** is being done at this node.  (Hash join on a scan
		** is a special case and is handled at the FBT.)
		*/
		if (trulyTheBestAccessPath.getJoinStrategy() != null &&
			trulyTheBestAccessPath.getJoinStrategy().isHashJoin())
		{
			return replaceWithHashTableNode();
		}

		/* We consider materialization into a temp table as a last step.
		 * Currently, we only materialize VTIs that are inner tables
		 * and can't be instantiated multiple times.  In the future we
		 * will consider materialization as a cost based option.
		 */
		return (Optimizable) considerMaterialization(outerTables);
	}

	/**
	 * This method creates a HashTableNode between the PRN and
	 * it's child when the optimizer chooses hash join on an
	 * arbitrary (non-FBT) result set tree.
	 * We divide up the restriction list into 3 parts and
	 * distribute those parts as described below.
	 * 
	 * @return The new (same) top of our result set tree.
	 * @exception StandardException		Thrown on error
	 */
	private Optimizable replaceWithHashTableNode()
		throws StandardException
	{
		// If this PRN has TTB access path for its child, store that access
		// path in the child here, so that we can find it later when it
		// comes time to generate qualifiers for the hash predicates (we
		// need the child's access path when generating qualifiers; if we
		// don't pass the path down here, the child won't be able to find
		// it).
		if (hasTrulyTheBestAccessPath)
		{
			((FromTable)childResult).trulyTheBestAccessPath =
				(AccessPathImpl)getTrulyTheBestAccessPath();

			// If the child itself is another SingleChildResultSetNode
			// (which is also what a ProjectRestrictNode is), then tell
			// it that it is now holding TTB path for it's own child.  Again,
			// this info is needed so that child knows where to find the
			// access path at generation time.
			if (childResult instanceof SingleChildResultSetNode)
			{
				((SingleChildResultSetNode)childResult)
					.hasTrulyTheBestAccessPath = hasTrulyTheBestAccessPath;

				// While we're at it, add the PRN's table number to the
				// child's referenced map so that we can find the equijoin
				// predicate.  We have to do this because the predicate
				// will be referencing the PRN's tableNumber, not the
				// child's--and since we use the child as the target
				// when searching for hash keys (as can be seen in
				// HashJoinStrategy.divideUpPredicateLists()), the child
				// should know what this PRN's table number is.  This
				// is somewhat bizarre since the child doesn't
				// actually "reference" this PRN, but since the child's
				// reference map is used when searching for the equijoin
				// predicate (see "buildTableNumList" in
				// BinaryRelationalOperatorNode), this is the simplest
				// way to pass this PRN's table number down.
				childResult.getReferencedTableMap().set(tableNumber);
			}
		}

		/* We want to divide the predicate list into 3 separate lists -
		 *	o predicates against the source of the hash table, which will
		 *	  be applied on the way into the hash table (searchRestrictionList)
		 *  o join clauses which are qualifiers and get applied to the
		 *	  rows in the hash table on a probe (joinRestrictionList)
		 *	o non-qualifiers involving both tables which will get
		 *	  applied after a row gets returned from the HTRS (nonQualifiers)
		 *
		 * We do some unnecessary work when doing this as we want to reuse
		 * as much existing code as possible.  The code that we are reusing
		 * was originally built for hash scans, hence the unnecessary
		 * requalification list.
		 */
		PredicateList searchRestrictionList =
                new PredicateList(getContextManager());
		PredicateList joinQualifierList =
                new PredicateList(getContextManager());
		PredicateList requalificationRestrictionList =
                new PredicateList(getContextManager());
		trulyTheBestAccessPath.getJoinStrategy().divideUpPredicateLists(
											this,
											restrictionList,
											searchRestrictionList,
											joinQualifierList,
											requalificationRestrictionList,
											getDataDictionary());

		/* Break out the non-qualifiers from HTN's join qualifier list and make that
		 * the new restriction list for this PRN.
		 */
        restrictionList = new PredicateList(getContextManager());
        /* For non-base table, we remove first 2 lists from requal list to avoid adding duplicates.
         */
        for (Predicate p : searchRestrictionList) {
            requalificationRestrictionList.removeOptPredicate(p);
        }

        for (Predicate p : joinQualifierList) {
            requalificationRestrictionList.removeOptPredicate(p);
        }

		joinQualifierList.transferNonQualifiers(this, restrictionList); //purify joinQual list
		requalificationRestrictionList.copyPredicatesToOtherList(restrictionList); //any residual

		ResultColumnList	htRCList;

		/* We get a shallow copy of the child's ResultColumnList and its 
		 * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
		 */
		htRCList = childResult.getResultColumns();
		childResult.setResultColumns(htRCList.copyListAndObjects());

		/* Replace ResultColumn.expression with new VirtualColumnNodes
		 * in the HTN's ResultColumnList.  (VirtualColumnNodes include
		 * pointers to source ResultSetNode, this, and source ResultColumn.)
		 * NOTE: We don't want to mark the underlying RCs as referenced, otherwise
		 * we won't be able to project out any of them.
		 */
		htRCList.genVirtualColumnNodes(childResult, childResult.getResultColumns(), false);

		/* The CRs for this side of the join in both the searchRestrictionList
		 * the joinQualifierList now point to the HTN's RCL.  We need them
		 * to point to the RCL in the child of the HTN.  (We skip doing this for
		 * the joinQualifierList as the code to generate the Qualifiers does not
		 * care.)
		 */
		RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
		searchRestrictionList.accept(rcrv);

		/* We can finally put the HTN between ourself and our old child. */
        childResult = new HashTableNode(childResult,
                                        tableProperties,
                                        htRCList,
                                        searchRestrictionList,
                                        joinQualifierList,
                                        trulyTheBestAccessPath,
                                        getCostEstimate(),
                                        projectSubquerys,
                                        restrictSubquerys,
                                        hashKeyColumns(),
                                        getContextManager());
		return this;
	}

	/** @see Optimizable#verifyProperties 
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public void verifyProperties(DataDictionary dDictionary)
		throws StandardException
	{
		/* Table properties can be attached to this node if
		 * its child is not an optimizable, otherwise they
		 * are attached to its child.
		 */

		if (childResult instanceof Optimizable)
		{
			((Optimizable) childResult).verifyProperties(dDictionary);
		}
		else
		{
			super.verifyProperties(dDictionary);
		}
	}

	/**
	 * @see Optimizable#legalJoinOrder
	 */
    @Override
	public boolean legalJoinOrder(JBitSet assignedTableMap)
	{
		if (childResult instanceof Optimizable)
		{
			return ((Optimizable) childResult).legalJoinOrder(assignedTableMap);
		}
		else
		{
			return true;
		}
	}

	/**
	 * @see Optimizable#uniqueJoin
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
	public double uniqueJoin(OptimizablePredicateList predList)
					throws StandardException
	{
		if (childResult instanceof Optimizable)
		{
			return ((Optimizable) childResult).uniqueJoin(predList);
		}
		else
		{
			return super.uniqueJoin(predList);
		}
	}

	/**
	 * Return the restriction list from this node.
	 *
	 * @return	The restriction list from this node.
	 */
	PredicateList getRestrictionList()
	{
		return restrictionList;
	}

	/** 
	 * Return the user specified join strategy, if any for this table.
	 *
	 * @return The user specified join strategy, if any for this table.
	 */
    @Override
	String getUserSpecifiedJoinStrategy()
	{
		if (childResult instanceof FromTable)
		{
			return ((FromTable) childResult).getUserSpecifiedJoinStrategy();
		}
		else
		{
			return userSpecifiedJoinStrategy;
		}
	}

	/**
	 * Prints the sub-nodes of this object.  See QueryTreeNode.java for
	 * how tree printing is supposed to work.
	 *
	 * @param depth		The depth of this node in the tree
	 */
    @Override
    void printSubNodes(int depth)
	{
		if (SanityManager.DEBUG)
		{
			super.printSubNodes(depth);

			if (restriction != null)
			{
				printLabel(depth, "restriction: ");
				restriction.treePrint(depth + 1);
			}

			if (restrictionList != null)
			{
				printLabel(depth, "restrictionList: ");
				restrictionList.treePrint(depth + 1);
			}

			if (projectSubquerys != null)
			{
				printLabel(depth, "projectSubquerys: ");
				projectSubquerys.treePrint(depth + 1);
			}

			if (restrictSubquerys != null)
			{
				printLabel(depth, "restrictSubquerys: ");
				restrictSubquerys.treePrint(depth + 1);
			}
		}
	}

	/** 
	 * Put a ProjectRestrictNode on top of each FromTable in the FromList.
	 * ColumnReferences must continue to point to the same ResultColumn, so
	 * that ResultColumn must percolate up to the new PRN.  However,
	 * that ResultColumn will point to a new expression, a VirtualColumnNode, 
	 * which points to the FromTable and the ResultColumn that is the source for
	 * the ColumnReference.  
	 * (The new PRN will have the original of the ResultColumnList and
	 * the ResultColumns from that list.  The FromTable will get shallow copies
	 * of the ResultColumnList and its ResultColumns.  ResultColumn.expression
	 * will remain at the FromTable, with the PRN getting a new 
	 * VirtualColumnNode for each ResultColumn.expression.)
	 * We then project out the non-referenced columns.  If there are no referenced
	 * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
	 * whose expression is 1.
	 *
	 * @param numTables			Number of tables in the DML Statement
	 * @param gbl				The group by list, if any
	 * @param fromList			The from list, if any
	 *
	 * @return The generated ProjectRestrictNode atop the original FromTable.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    ResultSetNode preprocess(int numTables,
									GroupByList gbl,
									FromList fromList) 
								throws StandardException
	{
		childResult = childResult.preprocess(numTables, gbl, fromList);

		/* Build the referenced table map */
		setReferencedTableMap( (JBitSet) childResult.getReferencedTableMap().clone() );

		return this;
	}

	/**
	 * Push expressions down to the first ResultSetNode which can do expression
	 * evaluation and has the same referenced table map.
	 * RESOLVE - This means only pushing down single table expressions to
	 * ProjectRestrictNodes today.  Once we have a better understanding of how
	 * the optimizer will work, we can push down join clauses.
	 *
	 * @param predicateList	The PredicateList.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    void pushExpressions(PredicateList predicateList)
					throws StandardException
	{
		if (SanityManager.DEBUG)
		SanityManager.ASSERT(predicateList != null,
							 "predicateList is expected to be non-null");

		/* Push single table predicates down to the left of an outer
		 * join, if possible.  (We need to be able to walk an entire
		 * join tree.)
		 */
		if (childResult instanceof JoinNode)
		{
			((FromTable) childResult).pushExpressions(predicateList);

		}

		/* Build a list of the single table predicates that we can push down */
        PredicateList pushPList =
            predicateList.getPushablePredicates(getReferencedTableMap());

		/* If this is a PRN above a SelectNode, probably due to a 
		 * view or derived table which couldn't be flattened, then see
		 * if we can push any of the predicates which just got pushed
		 * down to our level into the SelectNode.
		 */
		if (pushPList != null &&
				(childResult instanceof SelectNode))
		{
            SelectNode childSelect = (SelectNode)childResult;

            // We can't push down if there is a window
            // function because that would make ROW_NUMBER give wrong
            // result:
            // E.g.
            //     SELECT * from (SELECT ROW_NUMBER() OVER (), j FROM T
            //                    ORDER BY j) WHERE j=5
            //
            // Similarly, don't push if we have OFFSET and/or FETCH FROM.
            //
            if (childSelect.hasWindows() ||
                childSelect.hasOffsetFetchFirst()) {
            } else {
                pushPList.pushExpressionsIntoSelect((SelectNode) childResult,
                                                    false);
            }
        }


		/* DERBY-649: Push simple predicates into Unions. It would be up to UnionNode
		 * to decide if these predicates can be pushed further into underlying SelectNodes
		 * or UnionNodes.  Note, we also keep the predicateList at this
		 * ProjectRestrictNode in case the predicates are not pushable or only
		 * partially pushable.
		 *
		 * It is possible to expand this optimization in UnionNode later.
		 */
		if (pushPList != null && (childResult instanceof UnionNode))
			((UnionNode)childResult).pushExpressions(pushPList);

		if (restrictionList == null)
		{
			restrictionList = pushPList;
		}
		else if (pushPList != null && pushPList.size() != 0)
		{
			/* Concatenate the 2 PredicateLists */
			restrictionList.destructiveAppend(pushPList);
		}

		/* RESOLVE - this looks like the place to try to try to push the 
		 * predicates through the ProjectRestrict.  Seems like we should
		 * "rebind" the column references and reset the referenced table maps
		 * in restrictionList and then call childResult.pushExpressions() on
		 * restrictionList.
		 */
	}

	/**
	 * Add a new predicate to the list.  This is useful when doing subquery
	 * transformations, when we build a new predicate with the left side of
	 * the subquery operator and the subquery's result column.
	 *
	 * @param predicate		The predicate to add
	 *
	 * @return ResultSetNode	The new top of the tree.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    ResultSetNode addNewPredicate(Predicate predicate)
			throws StandardException
	{
		if (restrictionList == null)
		{
            restrictionList = new PredicateList(getContextManager());
		}
		restrictionList.addPredicate(predicate);
		return this;
	}

	/**
	 * Evaluate whether or not the subquery in a FromSubquery is flattenable.  
	 * Currently, a FSqry is flattenable if all of the following are true:
	 *		o  Subquery is a SelectNode. 
	 *		o  It contains no top level subqueries.  (RESOLVE - we can relax this)
	 *		o  It does not contain a group by or having clause
	 *		o  It does not contain aggregates.
	 *
	 * @param fromList	The outer from list
	 *
	 * @return boolean	Whether or not the FromSubquery is flattenable.
	 */
    @Override
    boolean flattenableInFromSubquery(FromList fromList)
	{
		/* Flattening currently involves merging predicates and FromLists.
		 * We don't have a FromList, so we can't flatten for now.
		 */
		/* RESOLVE - this will introduce yet another unnecessary PRN */
		return false;
	}

	/**
	 * Ensure that the top of the RSN tree has a PredicateList.
	 *
	 * @param numTables			The number of tables in the query.
	 * @return ResultSetNode	A RSN tree with a node which has a PredicateList on top.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    ResultSetNode ensurePredicateList(int numTables)
		throws StandardException
	{
		return this;
	}

	/**
	 * Optimize this ProjectRestrictNode.  
	 *
	 * @param dataDictionary	The DataDictionary to use for optimization
	 * @param predicates		The PredicateList to optimize.  This should
	 *							be a join predicate.
	 * @param outerRows			The number of outer joining rows
	 *
	 * @return	ResultSetNode	The top of the optimized subtree
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    ResultSetNode optimize(DataDictionary dataDictionary,
								  PredicateList predicates,
								  double outerRows) 
					throws StandardException
	{
		/* We need to implement this method since a PRN can appear above a
		 * SelectNode in a query tree.
		 */
		childResult = childResult.optimize(dataDictionary,
											restrictionList,
											outerRows);

		// RESOLVE: SHOULD FACTOR IN THE NON-OPTIMIZABLE PREDICATES THAT
		// WERE NOT PUSHED DOWN
        setCostEstimate( getOptimizerFactory().getCostEstimate() );

		getCostEstimate().setCost(childResult.getCostEstimate().getEstimatedCost(),
							childResult.getCostEstimate().rowCount(),
							childResult.getCostEstimate().singleScanRowCount());

		return this;
	}

	/**
	 * Get the CostEstimate for this ProjectRestrictNode.
	 *
	 * @return	The CostEstimate for this ProjectRestrictNode, which is
	 * 			the cost estimate for the child node.
	 */
    @Override
    CostEstimate getCostEstimate()
	{
		/*
		** The cost estimate will be set here if either optimize() or
		** optimizeIt() was called on this node.  It's also possible
		** that optimization was done directly on the child node,
		** in which case the cost estimate will be null here.
		*/
		if (super.getCostEstimate() == null)
        {
			return childResult.getCostEstimate();
        }
		else
		{
			return super.getCostEstimate();
		}
	}

	/**
	 * Get the final CostEstimate for this ProjectRestrictNode.
	 *
	 * @return	The final CostEstimate for this ProjectRestrictNode, which is
	 * 			the final cost estimate for the child node.
	 */
    @Override
    CostEstimate getFinalCostEstimate()
		throws StandardException
	{
		if (getCandidateFinalCostEstimate() != null)
        {
            // we already set it, so just return it.
			return getCandidateFinalCostEstimate();
        }

		// If the child result set is an Optimizable, then this node's
		// final cost is that of the child.  Otherwise, this node must
		// hold "trulyTheBestAccessPath" for it's child so we pull
		// the final cost from there.
		if (childResult instanceof Optimizable)
        {
			setCandidateFinalCostEstimate( childResult.getFinalCostEstimate() );
        }
		else
        {
			setCandidateFinalCostEstimate( getTrulyTheBestAccessPath().getCostEstimate() );
        }

		return getCandidateFinalCostEstimate();
	}

    /**
     * For joins, the tree will be (nodes are left out if the clauses
     * are empty):
     *
     *      ProjectRestrictResultSet -- for the having and the select list
     *      SortResultSet -- for the group by list
     *      ProjectRestrictResultSet -- for the where and the select list (if no group or having)
     *      the result set for the fromList
     *
	 *
	 * @exception StandardException		Thrown on error
     */
    @Override
    void generate(ActivationClassBuilder acb, MethodBuilder mb)
							throws StandardException
	{
		if (SanityManager.DEBUG)
            SanityManager.ASSERT(getResultColumns() != null, "Tree structure bad");

        //
        // If we are projecting and restricting the stream from a table
        // function, then give the table function all of the information that
        // it needs in order to push the projection and qualifiers into
        // the table function. See DERBY-4357.
        //
        if ( childResult instanceof FromVTI )
        {
            ((FromVTI) childResult).computeProjectionAndRestriction( restrictionList );
        }

		generateMinion( acb, mb, false);
	}

	/**
	 * General logic shared by Core compilation.
	 *
	 * @param acb	The ExpressionClassBuilder for the class being built
	 * @param mb	The method the expression will go into
	 *
	 *
	 * @exception StandardException		Thrown on error
	 */

    @Override
    void generateResultSet(ExpressionClassBuilder acb, MethodBuilder mb)
									throws StandardException
	{
		generateMinion( acb, mb, true);
	}

	/**
	 * Logic shared by generate() and generateResultSet().
	 *
	 * @param acb	The ExpressionClassBuilder for the class being built
	 * @param mb	The method the expression will go into
	 *
	 * @exception StandardException		Thrown on error
	 */

	private void generateMinion(ExpressionClassBuilder acb,
									 MethodBuilder mb, boolean genChildResultSet)
									throws StandardException
	{
		/* If this ProjectRestrict doesn't do anything, bypass its generation.
		 * (Remove any true and true predicates first, as they could be left
		 * by the like transformation.)
		 */
		if (restrictionList != null && restrictionList.size() > 0)
		{
			restrictionList.eliminateBooleanTrueAndBooleanTrue();
		}

		if (nopProjectRestrict())
		{
			generateNOPProjectRestrict();
			if (genChildResultSet)
				childResult.generateResultSet(acb, mb);
			else
				childResult.generate((ActivationClassBuilder)acb, mb);
			setCostEstimate( childResult.getFinalCostEstimate() );
			return;
		}

		// build up the tree.

		/* Put the predicates back into the tree */
		if (restrictionList != null)
		{
			constantRestriction = restrictionList.restoreConstantPredicates();
			// Remove any redundant predicates before restoring
			restrictionList.removeRedundantPredicates();
			restriction = restrictionList.restorePredicates();
			/* Allow the restrictionList to get garbage collected now
			 * that we're done with it.
			 */
			restrictionList = null;
		}

		// for the restriction, we generate an exprFun
		// that evaluates the expression of the clause
		// against the current row of the child's result.
		// if the restriction is empty, simply pass null
		// to optimize for run time performance.

   		// generate the function and initializer:
   		// Note: Boolean lets us return nulls (boolean would not)
   		// private Boolean exprN()
   		// {
   		//   return <<restriction.generate(ps)>>;
   		// }
   		// static Method exprN = method pointer to exprN;




		// Map the result columns to the source columns

        ResultColumnList.ColumnMapping mappingArrays =
            getResultColumns().mapSourceColumns();

        int[] mapArray = mappingArrays.mapArray;
        boolean[] cloneMap = mappingArrays.cloneMap;

		int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray));
        int cloneMapItem = acb.addItem(cloneMap);

		/* Will this node do a projection? */
		boolean doesProjection = true;

		/* Does a projection unless same # of columns in same order
		 * as child.
		 */
		if ( (! reflectionNeededForProjection()) && 
		    mapArray != null && 
			mapArray.length == childResult.getResultColumns().size())
		{
			/* mapArray entries are 1-based */
			int index = 0;
			for ( ; index < mapArray.length; index++)
			{
				if (mapArray[index] != index + 1)
				{
					break;
				}
			}
			if (index == mapArray.length)
			{
				doesProjection = false;
			}
		}



		/* Generate the ProjectRestrictSet:
		 *	arg1: childExpress - Expression for childResultSet
		 *  arg2: Activation
		 *  arg3: restrictExpress - Expression for restriction
		 *  arg4: projectExpress - Expression for projection
		 *  arg5: resultSetNumber
		 *  arg6: constantExpress - Expression for constant restriction
		 *			(for example, where 1 = 2)
		 *  arg7: mapArrayItem - item # for mapping of source columns
         *  arg8: cloneMapItem - item # for mapping of columns that need cloning
         *  arg9: reuseResult - whether or not the result row can be reused
         *                      (ie, will it always be the same)
         *  arg10: doesProjection - does this node do a projection
         *  arg11: estimated row count
         *  arg12: estimated cost
         *  arg13: close method
         */

		acb.pushGetResultSetFactoryExpression(mb);
		if (genChildResultSet)
			childResult.generateResultSet(acb, mb);
		else
			childResult.generate((ActivationClassBuilder)acb, mb);

		/* Get the next ResultSet #, so that we can number this ResultSetNode, its
		 * ResultColumnList and ResultSet.
		 */
		assignResultSetNumber();
		
		/* Set the point of attachment in all subqueries attached
		 * to this node.
		 */
		if (projectSubquerys != null && projectSubquerys.size() > 0)
		{
			projectSubquerys.setPointOfAttachment(getResultSetNumber());
		}
		if (restrictSubquerys != null && restrictSubquerys.size() > 0)
		{
			restrictSubquerys.setPointOfAttachment(getResultSetNumber());
		}

		// Load our final cost estimate.
		setCostEstimate( getFinalCostEstimate() );

		// if there is no restriction, we just want to pass null.
		if (restriction == null)
		{
		   	mb.pushNull(ClassName.GeneratedMethod);
		}
		else
		{
			// this sets up the method and the static field.
			// generates:
			// 	Object userExprFun { }
			MethodBuilder userExprFun = acb.newUserExprFun();

			// restriction knows it is returning its value;

			/* generates:
			 *    return  <restriction.generate(acb)>;
			 * and adds it to userExprFun
			 * NOTE: The explicit cast to DataValueDescriptor is required
			 * since the restriction may simply be a boolean column or subquery
			 * which returns a boolean.  For example:
			 *		where booleanColumn
			 */
			restriction.generateExpression(acb, userExprFun);
			userExprFun.methodReturn();

			// we are done modifying userExprFun, complete it.
			userExprFun.complete();

	   		// restriction is used in the final result set as an access of the new static
   			// field holding a reference to this new method.
			// generates:
			//	ActivationClass.userExprFun
			// which is the static field that "points" to the userExprFun
			// that evaluates the where clause.
   			acb.pushMethodReference(mb, userExprFun);
		}

		/* Determine whether or not reflection is needed for the projection.
		 * Reflection is not needed if all of the columns map directly to source
		 * columns.
		 */
		if (reflectionNeededForProjection())
		{
			// for the resultColumns, we generate a userExprFun
			// that creates a new row from expressions against
			// the current row of the child's result.
			// (Generate optimization: see if we can simply
			// return the current row -- we could, but don't, optimize
			// the function call out and have execution understand
			// that a null function pointer means take the current row
			// as-is, with the performance trade-off as discussed above.)

			/* Generate the Row function for the projection */
			getResultColumns().generateCore(acb, mb, false);
		}
		else
		{
		   	mb.pushNull(ClassName.GeneratedMethod);
		}
		
		mb.push(getResultSetNumber());

		// if there is no constant restriction, we just want to pass null.
		if (constantRestriction == null)
		{
		   	mb.pushNull(ClassName.GeneratedMethod);
		}
		else
		{
			// this sets up the method and the static field.
			// generates:
			// 	userExprFun { }
			MethodBuilder userExprFun = acb.newUserExprFun();

			// restriction knows it is returning its value;

			/* generates:
			 *    return <restriction.generate(acb)>;
			 * and adds it to userExprFun
			 * NOTE: The explicit cast to DataValueDescriptor is required
			 * since the restriction may simply be a boolean column or subquery
			 * which returns a boolean.  For example:
			 *		where booleanColumn
			 */
			constantRestriction.generateExpression(acb, userExprFun);

			userExprFun.methodReturn();

			// we are done modifying userExprFun, complete it.
			userExprFun.complete();

	   		// restriction is used in the final result set as an access
			// of the new static field holding a reference to this new method.
			// generates:
			//	ActivationClass.userExprFun
			// which is the static field that "points" to the userExprFun
			// that evaluates the where clause.
   			acb.pushMethodReference(mb, userExprFun);
		}
		
		mb.push(mapArrayItem);
        mb.push(cloneMapItem);
		mb.push(getResultColumns().reusableResult());
		mb.push(doesProjection);
        mb.push(validatingCheckConstraints);
        if ( validatingBaseTableUUIDString == null )
        {
            mb.push( UUID.NULL );
        }
        else
        {
            mb.push(validatingBaseTableUUIDString);
        }
		mb.push(getCostEstimate().rowCount());
		mb.push(getCostEstimate().getEstimatedCost());

		mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getProjectRestrictResultSet",
                    ClassName.NoPutResultSet, 13);
	}

	/**
	 * Determine whether this ProjectRestrict does anything.  If it doesn't
	 * filter out any rows or columns, it's a No-Op.
	 *
	 * @return	true if this ProjectRestrict is a No-Op.
	 */
	boolean nopProjectRestrict()
	{
		/*
		** This ProjectRestrictNode is not a No-Op if it does any
		** restriction.
		*/
		if ( (restriction != null) || (constantRestriction != null) ||
			 (restrictionList != null && restrictionList.size() > 0) )
		{
			return false;
		}

		ResultColumnList	childColumns = childResult.getResultColumns();
		ResultColumnList	PRNColumns = this.getResultColumns();

		/*
		** The two lists have the same numbers of elements.  Are the lists
		** identical?  In other words, is the expression in every ResultColumn
		** in the PRN's RCL a ColumnReference that points to the same-numbered
		** column?
		*/
		if (PRNColumns.nopProjection(childColumns))
			return true;

		return false;
	}

	/**
	 * Bypass the generation of this No-Op ProjectRestrict, and just generate
	 * its child result set.
	 *
	 * @exception StandardException		Thrown on error
	 */
    void generateNOPProjectRestrict()
			throws StandardException
	{
		this.getResultColumns().setRedundant();
	}

	/**
	 * Consider materialization for this ResultSet tree if it is valid and cost effective
	 * (It is not valid if incorrect results would be returned.)
	 *
	 * @return Top of the new/same ResultSet tree.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    ResultSetNode considerMaterialization(JBitSet outerTables)
		throws StandardException
	{
		childResult = childResult.considerMaterialization(outerTables);
		if (childResult.performMaterialization(outerTables))
		{
			MaterializeResultSetNode	mrsn;
			ResultColumnList			prRCList;

			/* If the restriction contians a ColumnReference from another
			 * table then the MRSN must go above the childResult.  Otherwise we can put
			 * it above ourselves. (The later is optimal since projection and restriction 
			 * will only happen once.)
			 * Put MRSN above PRN if any of the following are true:
			 *	o  PRN doesn't have a restriction list
			 *	o  PRN's restriction list is empty 
			 *  o  Table's referenced in PRN's restriction list are a subset of
			 *	   table's referenced in PRN's childResult.  (NOTE: Rather than construct
			 *     a new, empty JBitSet before checking, we simply clone the childResult's
			 *	   referencedTableMap.  This is done for code simplicity and will not 
			 *	   affect the result.)
			 */
			ReferencedTablesVisitor rtv = new ReferencedTablesVisitor(
												(JBitSet) childResult.getReferencedTableMap().clone());
			boolean emptyRestrictionList = (restrictionList == null || restrictionList.size() == 0);
			if (! emptyRestrictionList)
			{
				restrictionList.accept(rtv);
			}
			if (emptyRestrictionList ||
				childResult.getReferencedTableMap().contains(rtv.getTableMap()))
			{
				/* We get a shallow copy of the ResultColumnList and its 
				 * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
				 */
				prRCList = getResultColumns();
				setResultColumns(getResultColumns().copyListAndObjects());

				/* Replace ResultColumn.expression with new VirtualColumnNodes
				 * in the NormalizeResultSetNode's ResultColumnList.  (VirtualColumnNodes include
				 * pointers to source ResultSetNode, this, and source ResultColumn.)
				 */
				prRCList.genVirtualColumnNodes(this, getResultColumns());

				/* Finally, we create the new MaterializeResultSetNode */
                mrsn = new MaterializeResultSetNode(
									this,
									prRCList,
									tableProperties,
									getContextManager());
				// Propagate the referenced table map if it's already been created
				if (getReferencedTableMap() != null)
				{
					mrsn.setReferencedTableMap((JBitSet) getReferencedTableMap().clone());
				}
				return mrsn;
			}
			else
			{
				/* We get a shallow copy of the ResultColumnList and its 
				 * ResultColumns.  (Copy maintains ResultColumn.expression for now.)
				 */
				prRCList = childResult.getResultColumns();
				childResult.setResultColumns(prRCList.copyListAndObjects());

				/* Replace ResultColumn.expression with new VirtualColumnNodes
				 * in the MaterializeResultSetNode's ResultColumnList.  (VirtualColumnNodes include
				 * pointers to source ResultSetNode, this, and source ResultColumn.)
				 */
				prRCList.genVirtualColumnNodes(childResult, childResult.getResultColumns());

				/* RESOLVE - we need to push single table predicates down so that
				 * they get applied while building the MaterializeResultSet.
				 */

                mrsn = new MaterializeResultSetNode(
									childResult,
									prRCList,
									tableProperties,
									getContextManager());
				// Propagate the referenced table map if it's already been created
				if (childResult.getReferencedTableMap() != null)
				{
					mrsn.setReferencedTableMap((JBitSet) childResult.getReferencedTableMap().clone());
				}
				childResult = mrsn;
			}
		}

		return this;
	}

	/** 
	 * Determine whether or not the specified name is an exposed name in
	 * the current query block.
	 *
	 * @param name	The specified name to search for as an exposed name.
	 * @param schemaName	Schema name, if non-null.
	 * @param exactMatch	Whether or not we need an exact match on specified schema and table
	 *						names or match on table id.
	 *
	 * @return The FromTable, if any, with the exposed name.
	 *
	 * @exception StandardException		Thrown on error
	 */
    @Override
    FromTable getFromTableByName(String name, String schemaName, boolean exactMatch)
		throws StandardException
	{
		return childResult.getFromTableByName(name, schemaName, exactMatch);
	}

	/**
	 * Get the lock mode for the target of an update statement
	 * (a delete or update).  The update mode will always be row for
	 * CurrentOfNodes.  It will be table if there is no where clause.
	 *
	 * @return	The lock mode
	 */
    @Override
    int updateTargetLockMode()
	{
		if (restriction != null || constantRestriction != null)
		{
			return TransactionController.MODE_RECORD;
		}
		else
		{
			return childResult.updateTargetLockMode();
		}
	}

	/**
	 * Is it possible to do a distinct scan on this ResultSet tree.
	 * (See SelectNode for the criteria.)
	 *
	 * @param distinctColumns the set of distinct columns
	 * @return Whether or not it is possible to do a distinct scan on this ResultSet tree.
	 */
    @Override
    boolean isPossibleDistinctScan(Set<BaseColumnNode> distinctColumns)
	{
		if (restriction != null || 
			(restrictionList != null && restrictionList.size() != 0))
		{
			return false;
		}

		HashSet<BaseColumnNode> columns = new HashSet<BaseColumnNode>();

        for (ResultColumn rc : getResultColumns()) {
			BaseColumnNode bc = rc.getBaseColumnNode();
			if (bc == null) return false;
			columns.add(bc);
		}

		return columns.equals(distinctColumns) && childResult.isPossibleDistinctScan(distinctColumns);
	}

	/**
	 * Mark the underlying scan as a distinct scan.
	 */
    @Override
	void markForDistinctScan()
	{
		childResult.markForDistinctScan();
	}


	/**
	 * Accept the visitor for all visitable children of this node.
	 * 
	 * @param v the visitor
	 *
	 * @exception StandardException on error
	 */
    @Override
	void acceptChildren(Visitor v)
		throws StandardException
	{
		super.acceptChildren(v);

		if (restriction != null)
		{
			restriction = (ValueNode)restriction.accept(v);
		}

		if (restrictionList != null)
		{
			restrictionList = (PredicateList)restrictionList.accept(v);
		}
	}



	/**
	 * set the Information gathered from the parent table that is 
     * required to perform a referential action on dependent table.
	 */
    @Override
    void setRefActionInfo(long fkIndexConglomId,
								 int[]fkColArray, 
								 String parentResultSetId,
								 boolean dependentScan)
	{
		childResult.setRefActionInfo(fkIndexConglomId,
								   fkColArray,
								   parentResultSetId,
								   dependentScan);
	}

    void setRestriction(ValueNode restriction) {
		this.restriction = restriction;
	}

    @Override
    public void pushQueryExpressionSuffix() {
        childResult.pushQueryExpressionSuffix();
    }


	/**
	 * Push the order by list down from InsertNode into its child result set so
	 * that the optimizer has all of the information that it needs to consider
	 * sort avoidance.
	 *
	 * @param orderByList	The order by list
	 */
    @Override
	void pushOrderByList(OrderByList orderByList)
	{
		childResult.pushOrderByList(orderByList);
	}

    /**
     * Push down the offset and fetch first parameters, if any, to the
     * underlying child result set.
     *
     * @param offset    the OFFSET, if any
     * @param fetchFirst the OFFSET FIRST, if any
     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics of) a JDBC limit clause
     */
    @Override
    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause )
    {
        childResult.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
    }

    void setValidatingCheckConstraints( String baseTableUUIDString ) {
        validatingCheckConstraints = true;
        validatingBaseTableUUIDString = baseTableUUIDString;
    }
}
