** 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;
costEstimate = 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 */
costEstimate.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.costEstimate;
costEstimate.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