* @exception StandardException Thrown on error
*/
public ResultSetNode changeAccessPath() throws StandardException
{
ResultSetNode retval;
AccessPath ap = getTrulyTheBestAccessPath();
ConglomerateDescriptor trulyTheBestConglomerateDescriptor =
ap.getConglomerateDescriptor();
JoinStrategy trulyTheBestJoinStrategy = ap.getJoinStrategy();
Optimizer optimizer = ap.getOptimizer();
optimizer.trace(Optimizer.CHANGING_ACCESS_PATH_FOR_TABLE,
tableNumber, 0, 0.0, null);
if (SanityManager.DEBUG)
{
SanityManager.ASSERT(
trulyTheBestConglomerateDescriptor != null,
"Should only modify access path after conglomerate has been chosen.");
}
/*
** Make sure user-specified bulk fetch is OK with the chosen join
** strategy.
*/
if (bulkFetch != UNSET)
{
if ( ! trulyTheBestJoinStrategy.bulkFetchOK())
{
throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_WITH_JOIN_TYPE,
trulyTheBestJoinStrategy.getName());
}
// bulkFetch has no meaning for hash join, just ignore it
else if (trulyTheBestJoinStrategy.ignoreBulkFetch())
{
disableBulkFetch();
}
// bug 4431 - ignore bulkfetch property if it's 1 row resultset
else if (isOneRowResultSet())
{
disableBulkFetch();
}
}
// bulkFetch = 1 is the same as no bulk fetch
if (bulkFetch == 1)
{
disableBulkFetch();
}
/* Remove any redundant join clauses. A redundant join clause is one
* where there are other join clauses in the same equivalence class
* after it in the PredicateList.
*/
restrictionList.removeRedundantPredicates();
/*
** Divide up the predicates for different processing phases of the
** best join strategy.
*/
storeRestrictionList = (PredicateList) getNodeFactory().getNode(
C_NodeTypes.PREDICATE_LIST,
getContextManager());
nonStoreRestrictionList = (PredicateList) getNodeFactory().getNode(
C_NodeTypes.PREDICATE_LIST,
getContextManager());
requalificationRestrictionList =
(PredicateList) getNodeFactory().getNode(
C_NodeTypes.PREDICATE_LIST,
getContextManager());
trulyTheBestJoinStrategy.divideUpPredicateLists(
this,
restrictionList,
storeRestrictionList,
nonStoreRestrictionList,
requalificationRestrictionList,
getDataDictionary());
/* Check to see if we are going to do execution-time probing
* of an index using IN-list values. We can tell by looking
* at the restriction list: if there is an IN-list probe
* predicate that is also a start/stop key then we know that
* we're going to do execution-time probing. In that case
* we disable bulk fetching to minimize the number of non-
* matching rows that we read from disk. RESOLVE: Do we
* really need to completely disable bulk fetching here,
* or can we do something else?
*/
for (int i = 0; i < restrictionList.size(); i++)
{
Predicate pred = (Predicate)restrictionList.elementAt(i);
if (pred.isInListProbePredicate() && pred.isStartKey())
{
disableBulkFetch();
multiProbing = true;
break;
}
}
/*
** Consider turning on bulkFetch if it is turned
** off. Only turn it on if it is a not an updatable
** scan and if it isn't a oneRowResultSet, and
** not a subquery, and it is OK to use bulk fetch
** with the chosen join strategy. NOTE: the subquery logic
** could be more sophisticated -- we are taking
** the safe route in avoiding reading extra
** data for something like:
**
** select x from t where x in (select y from t)
**
** In this case we want to stop the subquery
** evaluation as soon as something matches.
*/
if (trulyTheBestJoinStrategy.bulkFetchOK() &&
!(trulyTheBestJoinStrategy.ignoreBulkFetch()) &&
! bulkFetchTurnedOff &&
(bulkFetch == UNSET) &&
!forUpdate() &&
!isOneRowResultSet() &&
getLevel() == 0)
{
bulkFetch = getDefaultBulkFetch();
}
/* Statement is dependent on the chosen conglomerate. */
getCompilerContext().createDependency(
trulyTheBestConglomerateDescriptor);
/* No need to modify access path if conglomerate is the heap */
if ( ! trulyTheBestConglomerateDescriptor.isIndex())
{
/*
** We need a little special logic for SYSSTATEMENTS
** here. SYSSTATEMENTS has a hidden column at the
** end. When someone does a select * we don't want
** to get that column from the store. So we'll always
** generate a partial read bitSet if we are scanning
** SYSSTATEMENTS to ensure we don't get the hidden
** column.
*/
boolean isSysstatements = tableName.equals("SYS","SYSSTATEMENTS");
/* Template must reflect full row.
* Compact RCL down to partial row.
*/
templateColumns = resultColumns;
referencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, isSysstatements, false);
resultColumns = resultColumns.compactColumns(cursorTargetTable, isSysstatements);
return this;
}
/* No need to go to the data page if this is a covering index */
/* Derby-1087: use data page when returning an updatable resultset */
if (ap.getCoveringIndexScan() && (!cursorTargetTable()))
{
/* Massage resultColumns so that it matches the index. */
resultColumns = newResultColumns(resultColumns,
trulyTheBestConglomerateDescriptor,
baseConglomerateDescriptor,