use of org.exist.indexing.StructuralIndex in project exist by eXist-db.
the class Optimize method eval.
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (contextItem != null) {
contextSequence = contextItem.toSequence();
}
boolean useCached = false;
boolean optimize = false;
NodeSet originalContext = null;
if (contextSequence == null || contextSequence.isPersistentSet()) {
// don't try to optimize in-memory node sets!
// contextSequence will be overwritten
originalContext = contextSequence == null ? null : contextSequence.toNodeSet();
if (cachedContext != null && cachedContext == originalContext) {
useCached = !originalContext.hasChanged(cachedTimestamp);
}
if (contextVar != null) {
contextSequence = contextVar.eval(contextSequence);
}
// in the current context
if (useCached) {
optimize = cachedOptimize;
} else {
if (optimizables != null && optimizables.length > 0) {
for (Optimizable optimizable : optimizables) {
if (optimizable.canOptimize(contextSequence)) {
optimize = true;
} else {
optimize = false;
break;
}
}
}
}
}
if (optimize) {
cachedContext = originalContext;
cachedTimestamp = originalContext == null ? 0 : originalContext.getState();
cachedOptimize = true;
NodeSet ancestors;
NodeSet result = null;
for (int current = 0; current < optimizables.length; current++) {
NodeSet selection = optimizables[current].preSelect(contextSequence, current > 0);
if (LOG.isTraceEnabled()) {
LOG.trace("exist:optimize: pre-selection: {}", selection.getLength());
}
// be re-evaluated to filter out wrong matches
if (selection.isEmpty()) {
ancestors = selection;
} else if (contextStep == null || current > 0) {
ancestors = selection.selectAncestorDescendant(contextSequence.toNodeSet(), NodeSet.ANCESTOR, true, contextId, true);
} else {
// NodeSelector selector;
final long start = System.currentTimeMillis();
// selector = new AncestorSelector(selection, contextId, true, false);
final StructuralIndex index = context.getBroker().getStructuralIndex();
final QName ancestorQN = contextStep.getTest().getName();
if (optimizables[current].optimizeOnSelf()) {
ancestors = index.findAncestorsByTagName(ancestorQN.getNameType(), ancestorQN, Constants.SELF_AXIS, selection.getDocumentSet(), selection, contextId);
} else {
ancestors = index.findAncestorsByTagName(ancestorQN.getNameType(), ancestorQN, optimizables[current].optimizeOnChild() ? Constants.PARENT_AXIS : Constants.ANCESTOR_SELF_AXIS, selection.getDocumentSet(), selection, contextId);
}
if (LOG.isTraceEnabled()) {
LOG.trace("Ancestor selection took {}", System.currentTimeMillis() - start);
LOG.trace("Found: {}", ancestors.getLength());
}
}
result = ancestors;
contextSequence = result;
}
if (contextStep == null) {
return innerExpr.eval(result);
} else {
contextStep.setPreloadedData(result.getDocumentSet(), result);
if (LOG.isTraceEnabled()) {
LOG.trace("exist:optimize: context after optimize: {}", result.getLength());
}
final long start = System.currentTimeMillis();
if (originalContext != null) {
contextSequence = originalContext.filterDocuments(result);
} else {
contextSequence = null;
}
final Sequence seq = innerExpr.eval(contextSequence);
if (LOG.isTraceEnabled()) {
LOG.trace("exist:optimize: inner expr took {}; found: {}", System.currentTimeMillis() - start, seq.getItemCount());
}
return seq;
}
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("exist:optimize: Cannot optimize expression.");
}
if (originalContext != null) {
contextSequence = originalContext;
}
return innerExpr.eval(contextSequence, contextItem);
}
}
Aggregations