Search in sources :

Example 71 with SequenceIterator

use of org.exist.xquery.value.SequenceIterator in project exist by eXist-db.

the class GeneralComparison method quickNodeSetCompare.

/**
 * Optimized implementation: first checks if a range index is defined on the nodes in the left argument.
 * Otherwise, fall back to {@link #nodeSetCompare(NodeSet, Sequence)}.
 *
 * @param   contextSequence  DOCUMENT ME!
 *
 * @return  DOCUMENT ME!
 *
 * @throws  XPathException  DOCUMENT ME!
 */
protected Sequence quickNodeSetCompare(Sequence contextSequence) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "quickNodeSetCompare");
    }
    final long start = System.currentTimeMillis();
    // get the NodeSet on the left
    final Sequence leftSeq = getLeft().eval(contextSequence);
    if (!leftSeq.isPersistentSet()) {
        return (genericCompare(leftSeq, contextSequence, null));
    }
    final NodeSet nodes = leftSeq.isEmpty() ? NodeSet.EMPTY_SET : (NodeSet) leftSeq;
    // nothing on the left, so nothing to do
    if (!(nodes instanceof VirtualNodeSet) && nodes.isEmpty()) {
        // Well, we might discuss this one ;-)
        hasUsedIndex = true;
        return (Sequence.EMPTY_SEQUENCE);
    }
    // get the Sequence on the right
    final Sequence rightSeq = getRight().eval(contextSequence);
    // nothing on the right, so nothing to do
    if (rightSeq.isEmpty()) {
        // Well, we might discuss this one ;-)
        hasUsedIndex = true;
        return (Sequence.EMPTY_SEQUENCE);
    }
    // get the type of a possible index
    final int indexType = nodes.getIndexType();
    // remember that Type.ITEM means... no index ;-)
    if (indexType != Type.ITEM) {
        if (LOG.isTraceEnabled()) {
            LOG.trace("found an index of type: {}", Type.getTypeName(indexType));
        }
        boolean indexScan = false;
        boolean indexMixed = false;
        QName myContextQName = contextQName;
        if (contextSequence != null) {
            final IndexFlags iflags = checkForQNameIndex(idxflags, context, contextSequence, myContextQName);
            boolean indexFound = false;
            if (!iflags.indexOnQName) {
                // if myContextQName != null and no index is defined on
                // myContextQName, we don't need to scan other QName indexes
                // and can just use the generic range index
                indexFound = myContextQName != null;
                if (iflags.partialIndexOnQName) {
                    indexMixed = true;
                } else {
                    // set myContextQName to null so the index lookup below is not
                    // restricted to that QName
                    myContextQName = null;
                }
            }
            if (!indexFound && (myContextQName == null)) {
                // we need to check them all
                if (iflags.hasIndexOnQNames) {
                    indexScan = true;
                }
            // else use range index defined on path by default
            }
        } else {
            return (nodeSetCompare(nodes, contextSequence));
        }
        // Get the documents from the node set
        final DocumentSet docs = nodes.getDocumentSet();
        // Holds the result
        NodeSet result = null;
        // Iterate through the right hand sequence
        for (final SequenceIterator itRightSeq = Atomize.atomize(rightSeq).iterate(); itRightSeq.hasNext(); ) {
            // Get the index key
            Item key = itRightSeq.nextItem();
            // if key has truncation, convert it to string
            if (truncation != StringTruncationOperator.NONE) {
                if (!Type.subTypeOf(key.getType(), Type.STRING)) {
                    LOG.info("Truncated key. Converted from {} to xs:string", Type.getTypeName(key.getType()));
                    // truncation is only possible on strings
                    key = key.convertTo(Type.STRING);
                }
            } else // TODO : use Type.isSubType() ??? -pb
            if (key.getType() != indexType) {
                // try to convert the key to the index type
                try {
                    key = key.convertTo(indexType);
                } catch (final XPathException xpe) {
                    // Could not convert the key to a suitable type for the index, fallback to nodeSetCompare()
                    if (context.getProfiler().isEnabled()) {
                        context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (" + xpe.getMessage() + ")");
                    }
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Cannot convert key: {} to required index type: {}", Type.getTypeName(key.getType()), Type.getTypeName(indexType));
                    }
                    return (nodeSetCompare(nodes, contextSequence));
                }
            }
            // If key implements org.exist.storage.Indexable, we can use the index
            if (key instanceof Indexable) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Checking if range index can be used for key: {}", key.getStringValue());
                }
                final Collator collator = ((collationArg != null) ? getCollator(contextSequence) : null);
                if (Type.subTypeOf(key.getType(), indexType)) {
                    if (truncation == StringTruncationOperator.NONE) {
                        if (LOG.isTraceEnabled()) {
                            LOG.trace("Using range index for key: {}", key.getStringValue());
                        }
                        // key without truncation, find key
                        context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() + "' to find key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
                        NodeSet ns;
                        if (indexScan) {
                            ns = context.getBroker().getValueIndex().findAll(context.getWatchDog(), relation, docs, nodes, NodeSet.ANCESTOR, (Indexable) key);
                        } else {
                            ns = context.getBroker().getValueIndex().find(context.getWatchDog(), relation, docs, nodes, NodeSet.ANCESTOR, myContextQName, (Indexable) key, indexMixed);
                        }
                        hasUsedIndex = true;
                        if (result == null) {
                            result = ns;
                        } else {
                            result = result.union(ns);
                        }
                    } else {
                        // key with truncation, match key
                        if (LOG.isTraceEnabled()) {
                            context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() + "' to match key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
                        }
                        if (LOG.isTraceEnabled()) {
                            LOG.trace("Using range index for key: {}", key.getStringValue());
                        }
                        try {
                            NodeSet ns;
                            final String matchString = key.getStringValue();
                            final int matchType = getMatchType(truncation);
                            if (indexScan) {
                                ns = context.getBroker().getValueIndex().matchAll(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, matchString, matchType, 0, true, collator, truncation);
                            } else {
                                ns = context.getBroker().getValueIndex().match(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, matchString, myContextQName, matchType, collator, truncation);
                            }
                            hasUsedIndex = true;
                            if (result == null) {
                                result = ns;
                            } else {
                                result = result.union(ns);
                            }
                        } catch (final EXistException e) {
                            throw (new XPathException(this, e));
                        }
                    }
                } else {
                    // our key does is not of the correct type
                    if (context.getProfiler().isEnabled()) {
                        context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is of type: " + Type.getTypeName(key.getType()) + ") whereas index is of type '" + Type.getTypeName(indexType) + "'");
                    }
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Cannot use range index: key is of type: {}) whereas index is of type '{}", Type.getTypeName(key.getType()), Type.getTypeName(indexType));
                    }
                    return (nodeSetCompare(nodes, contextSequence));
                }
            } else {
                // our key does not implement org.exist.storage.Indexable
                if (context.getProfiler().isEnabled()) {
                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is not an indexable type: " + key.getClass().getName());
                }
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Cannot use key which is of type '{}", key.getClass().getName());
                }
                return (nodeSetCompare(nodes, contextSequence));
            }
        }
        if (context.getProfiler().traceFunctions()) {
            context.getProfiler().traceIndexUsage(context, PerformanceStats.RANGE_IDX_TYPE, this, PerformanceStats.BASIC_INDEX, System.currentTimeMillis() - start);
        }
        return (result);
    } else {
        if (LOG.isTraceEnabled()) {
            LOG.trace("No suitable index found for key: {}", rightSeq.getStringValue());
        }
        // no range index defined on the nodes in this sequence, so fallback to nodeSetCompare
        if (context.getProfiler().isEnabled()) {
            context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "falling back to nodeSetCompare (no index available)");
        }
        return (nodeSetCompare(nodes, contextSequence));
    }
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) QName(org.exist.dom.QName) Sequence(org.exist.xquery.value.Sequence) EXistException(org.exist.EXistException) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) Collator(com.ibm.icu.text.Collator) Item(org.exist.xquery.value.Item) ContextItem(org.exist.dom.persistent.ContextItem) SequenceIterator(org.exist.xquery.value.SequenceIterator) Indexable(org.exist.storage.Indexable) DocumentSet(org.exist.dom.persistent.DocumentSet)

Example 72 with SequenceIterator

use of org.exist.xquery.value.SequenceIterator in project exist by eXist-db.

the class OpSimpleMap method eval.

@Override
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (contextItem != null) {
        contextSequence = contextItem.toSequence();
    }
    final Sequence leftSeq = left.eval(contextSequence);
    if (leftSeq.isEmpty()) {
        return Sequence.EMPTY_SEQUENCE;
    }
    final ValueSequence result = new ValueSequence();
    int pos = 0;
    for (final SequenceIterator i = leftSeq.iterate(); i.hasNext(); pos++) {
        context.setContextSequencePosition(pos, leftSeq);
        final Sequence rightSeq = right.eval(i.nextItem().toSequence());
        result.addAll(rightSeq);
    }
    return result;
}
Also used : SequenceIterator(org.exist.xquery.value.SequenceIterator) ValueSequence(org.exist.xquery.value.ValueSequence) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence)

Example 73 with SequenceIterator

use of org.exist.xquery.value.SequenceIterator in project exist by eXist-db.

the class DynamicCommentConstructor method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.Expression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
     */
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
        if (contextItem != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
        }
    }
    if (newDocumentContext) {
        context.pushDocumentContext();
    }
    Sequence result;
    try {
        final Sequence contentSeq = content.eval(contextSequence, contextItem);
        if (contentSeq.isEmpty()) {
            result = Sequence.EMPTY_SEQUENCE;
        } else {
            final MemTreeBuilder builder = context.getDocumentBuilder();
            context.proceed(this, builder);
            final StringBuilder buf = new StringBuilder();
            for (final SequenceIterator i = Atomize.atomize(contentSeq).iterate(); i.hasNext(); ) {
                context.proceed(this, builder);
                final Item next = i.nextItem();
                if (buf.length() > 0) {
                    buf.append(' ');
                }
                buf.append(next.toString());
            }
            if (buf.indexOf("--") != Constants.STRING_NOT_FOUND || buf.toString().endsWith("-")) {
                throw new XPathException(this, ErrorCodes.XQDY0072, "'" + buf.toString() + "' is not a valid comment");
            }
            final int nodeNr = builder.comment(buf.toString());
            result = builder.getDocument().getNode(nodeNr);
        }
    } finally {
        if (newDocumentContext) {
            context.popDocumentContext();
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : Item(org.exist.xquery.value.Item) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) SequenceIterator(org.exist.xquery.value.SequenceIterator) Sequence(org.exist.xquery.value.Sequence)

Example 74 with SequenceIterator

use of org.exist.xquery.value.SequenceIterator in project exist by eXist-db.

the class DynamicTextConstructor method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.Expression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
     */
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
        if (contextItem != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
        }
    }
    if (newDocumentContext) {
        context.pushDocumentContext();
    }
    Sequence result;
    try {
        final Sequence contentSeq = content.eval(contextSequence, contextItem);
        if (contentSeq.isEmpty()) {
            result = Sequence.EMPTY_SEQUENCE;
        } else {
            final MemTreeBuilder builder = context.getDocumentBuilder();
            context.proceed(this, builder);
            final StringBuilder buf = new StringBuilder();
            for (final SequenceIterator i = Atomize.atomize(contentSeq).iterate(); i.hasNext(); ) {
                context.proceed(this, builder);
                final Item next = i.nextItem();
                if (buf.length() > 0) {
                    buf.append(' ');
                }
                buf.append(next.toString());
            }
            // such a text node will be deleted or merged with another text node.
            if (!newDocumentContext && buf.length() == 0) {
                result = Sequence.EMPTY_SEQUENCE;
            } else {
                final int nodeNr = builder.characters(buf);
                result = builder.getDocument().getNode(nodeNr);
            }
        }
    } finally {
        if (newDocumentContext) {
            context.popDocumentContext();
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : Item(org.exist.xquery.value.Item) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) SequenceIterator(org.exist.xquery.value.SequenceIterator) Sequence(org.exist.xquery.value.Sequence)

Example 75 with SequenceIterator

use of org.exist.xquery.value.SequenceIterator in project exist by eXist-db.

the class Shared method getStreamSource.

/**
 *  Get stream source for specified resource, containing InputStream and
 * location. Used by @see Jaxv.
 * @param s The sequence
 * @param context xquery context
 * @return Streamsources
 * @throws XPathException An error occurred.
 * @throws IOException An I/O error occurred.
 */
public static StreamSource[] getStreamSource(Sequence s, XQueryContext context) throws XPathException, IOException {
    final ArrayList<StreamSource> sources = new ArrayList<>();
    final SequenceIterator i = s.iterate();
    while (i.hasNext()) {
        final Item next = i.nextItem();
        final StreamSource streamsource = getStreamSource(next, context);
        sources.add(streamsource);
    }
    StreamSource[] returnSources = new StreamSource[sources.size()];
    returnSources = sources.toArray(returnSources);
    return returnSources;
}
Also used : Item(org.exist.xquery.value.Item) ValidationReportItem(org.exist.validation.ValidationReportItem) SequenceIterator(org.exist.xquery.value.SequenceIterator) StreamSource(javax.xml.transform.stream.StreamSource) ArrayList(java.util.ArrayList)

Aggregations

SequenceIterator (org.exist.xquery.value.SequenceIterator)75 Sequence (org.exist.xquery.value.Sequence)40 Item (org.exist.xquery.value.Item)35 XPathException (org.exist.xquery.XPathException)19 ValueSequence (org.exist.xquery.value.ValueSequence)16 Test (org.junit.Test)16 SAXException (org.xml.sax.SAXException)11 XQuery (org.exist.xquery.XQuery)10 Collator (com.ibm.icu.text.Collator)9 AtomicValue (org.exist.xquery.value.AtomicValue)9 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)8 DBBroker (org.exist.storage.DBBroker)8 NumericValue (org.exist.xquery.value.NumericValue)8 Properties (java.util.Properties)7 StringWriter (java.io.StringWriter)6 EXistException (org.exist.EXistException)6 NodeProxy (org.exist.dom.persistent.NodeProxy)6 NodeSet (org.exist.dom.persistent.NodeSet)6 BrokerPool (org.exist.storage.BrokerPool)6 IOException (java.io.IOException)5