OptimizablePredicateList predList,
RowOrdering rowOrdering)
throws StandardException
{
String userSpecifiedIndexName = getUserSpecifiedIndexName();
AccessPath ap = getCurrentAccessPath();
ConglomerateDescriptor currentConglomerateDescriptor =
ap.getConglomerateDescriptor();
optimizer.trace(Optimizer.CALLING_NEXT_ACCESS_PATH,
((predList == null) ? 0 : predList.size()),
0, 0.0, getExposedName());
/*
** Remove the ordering of the current conglomerate descriptor,
** if any.
*/
rowOrdering.removeOptimizable(getTableNumber());
// RESOLVE: This will have to be modified to step through the
// join strategies as well as the conglomerates.
if (userSpecifiedIndexName != null)
{
/*
** User specified an index name, so we should look at only one
** index. If there is a current conglomerate descriptor, and there
** are no more join strategies, we've already looked at the index,
** so go back to null.
*/
if (currentConglomerateDescriptor != null)
{
if ( ! super.nextAccessPath(optimizer,
predList,
rowOrdering) )
{
currentConglomerateDescriptor = null;
}
}
else
{
optimizer.trace(Optimizer.LOOKING_FOR_SPECIFIED_INDEX,
tableNumber, 0, 0.0, userSpecifiedIndexName);
if (StringUtil.SQLToUpperCase(userSpecifiedIndexName).equals("NULL"))
{
/* Special case - user-specified table scan */
currentConglomerateDescriptor =
tableDescriptor.getConglomerateDescriptor(
tableDescriptor.getHeapConglomerateId()
);
}
else
{
/* User-specified index name */
getConglomDescs();
for (int index = 0; index < conglomDescs.length; index++)
{
currentConglomerateDescriptor = conglomDescs[index];
String conglomerateName =
currentConglomerateDescriptor.getConglomerateName();
if (conglomerateName != null)
{
/* Have we found the desired index? */
if (conglomerateName.equals(userSpecifiedIndexName))
{
break;
}
}
}
/* We should always find a match */
if (SanityManager.DEBUG)
{
if (currentConglomerateDescriptor == null)
{
SanityManager.THROWASSERT(
"Expected to find match for forced index " +
userSpecifiedIndexName);
}
}
}
if ( ! super.nextAccessPath(optimizer,
predList,
rowOrdering))
{
if (SanityManager.DEBUG)
{
SanityManager.THROWASSERT("No join strategy found");
}
}
}
}
else
{
if (currentConglomerateDescriptor != null)
{
/*
** Once we have a conglomerate descriptor, cycle through
** the join strategies (done in parent).
*/
if ( ! super.nextAccessPath(optimizer,
predList,
rowOrdering))
{
/*
** When we're out of join strategies, go to the next
** conglomerate descriptor.
*/
currentConglomerateDescriptor = getNextConglom(currentConglomerateDescriptor);
/*
** New conglomerate, so step through join strategies
** again.
*/
resetJoinStrategies(optimizer);
if ( ! super.nextAccessPath(optimizer,
predList,
rowOrdering))
{
if (SanityManager.DEBUG)
{
SanityManager.THROWASSERT("No join strategy found");
}
}
}
}
else
{
/* Get the first conglomerate descriptor */
currentConglomerateDescriptor = getFirstConglom();
if ( ! super.nextAccessPath(optimizer,
predList,
rowOrdering))
{
if (SanityManager.DEBUG)
{
SanityManager.THROWASSERT("No join strategy found");
}
}
}
}
if (currentConglomerateDescriptor == null)
{
optimizer.trace(Optimizer.NO_MORE_CONGLOMERATES, tableNumber, 0, 0.0, null);
}
else
{
currentConglomerateDescriptor.setColumnNames(columnNames);
optimizer.trace(Optimizer.CONSIDERING_CONGLOMERATE, tableNumber, 0, 0.0,
currentConglomerateDescriptor);
}
/*
** Tell the rowOrdering that what the ordering of this conglomerate is
*/
if (currentConglomerateDescriptor != null)
{
if ( ! currentConglomerateDescriptor.isIndex())
{
/* If we are scanning the heap, but there
* is a full match on a unique key, then
* we can say that the table IS NOT unordered.
* (We can't currently say what the ordering is
* though.)
*/
if (! isOneRowResultSet(predList))
{
optimizer.trace(Optimizer.ADDING_UNORDERED_OPTIMIZABLE,
((predList == null) ? 0 : predList.size()),
0, 0.0, null);
rowOrdering.addUnorderedOptimizable(this);
}
else
{
optimizer.trace(Optimizer.SCANNING_HEAP_FULL_MATCH_ON_UNIQUE_KEY,
0, 0, 0.0, null);
}
}
else
{
IndexRowGenerator irg =
currentConglomerateDescriptor.getIndexDescriptor();
int[] baseColumnPositions = irg.baseColumnPositions();
boolean[] isAscending = irg.isAscending();
for (int i = 0; i < baseColumnPositions.length; i++)
{
/*
** Don't add the column to the ordering if it's already
** an ordered column. This can happen in the following
** case:
**
** create index ti on t(x, y);
** select * from t where x = 1 order by y;
**
** Column x is always ordered, so we want to avoid the
** sort when using index ti. This is accomplished by
** making column y appear as the first ordered column
** in the list.
*/
if ( ! rowOrdering.orderedOnColumn(isAscending[i] ?
RowOrdering.ASCENDING :
RowOrdering.DESCENDING,
getTableNumber(),
baseColumnPositions[i]))
{
rowOrdering.nextOrderPosition(isAscending[i] ?
RowOrdering.ASCENDING :
RowOrdering.DESCENDING);
rowOrdering.addOrderedColumn(isAscending[i] ?
RowOrdering.ASCENDING :
RowOrdering.DESCENDING,
getTableNumber(),
baseColumnPositions[i]);
}
}
}
}
ap.setConglomerateDescriptor(currentConglomerateDescriptor);
return currentConglomerateDescriptor != null;
}