Search in sources :

Example 11 with StructuralIndex

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);
    }
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) StructuralIndex(org.exist.indexing.StructuralIndex) QName(org.exist.dom.QName) Sequence(org.exist.xquery.value.Sequence)

Aggregations

StructuralIndex (org.exist.indexing.StructuralIndex)11 InMemoryNodeSet (org.exist.dom.memtree.InMemoryNodeSet)8 IOException (java.io.IOException)2 StreamFilter (javax.xml.stream.StreamFilter)2 XMLStreamException (javax.xml.stream.XMLStreamException)2 QName (org.exist.dom.QName)2 NodeId (org.exist.numbering.NodeId)2 NodeSet (org.exist.dom.persistent.NodeSet)1 NodeSelector (org.exist.xquery.NodeSelector)1 Sequence (org.exist.xquery.value.Sequence)1 NodeList (org.w3c.dom.NodeList)1