Search in sources :

Example 36 with DocumentSet

use of org.exist.dom.persistent.DocumentSet in project exist by eXist-db.

the class NativeStructuralIndexWorkerTest method getDocIdRanges_contiguousIds_followed_by_single.

@Test
public void getDocIdRanges_contiguousIds_followed_by_single() {
    final NativeStructuralIndexWorker indexWorker = new NativeStructuralIndexWorker(null);
    final DocumentSet docs = documentIdSet(Arrays.asList(11, 12, 13, 14, 15, 6574));
    final List<NativeStructuralIndexWorker.Range> ranges = indexWorker.getDocIdRanges(docs);
    assertEquals(2, ranges.size());
    assertEquals(11, ranges.get(0).start);
    assertEquals(15, ranges.get(0).end);
    assertEquals(6574, ranges.get(1).start);
    assertEquals(6574, ranges.get(1).end);
}
Also used : DocumentSet(org.exist.dom.persistent.DocumentSet) Test(org.junit.Test)

Example 37 with DocumentSet

use of org.exist.dom.persistent.DocumentSet in project exist by eXist-db.

the class Lookup method eval.

@Override
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (!canOptimize && fallback != null) {
        return fallback.eval(contextSequence, contextItem);
    }
    if (contextItem != null)
        contextSequence = contextItem.toSequence();
    if (contextSequence != null && !contextSequence.isPersistentSet()) {
        // in-memory docs won't have an index
        if (fallback == null) {
            return Sequence.EMPTY_SEQUENCE;
        } else {
            return fallback.eval(contextSequence, contextItem);
        }
    }
    NodeSet result;
    if (preselectResult == null) {
        long start = System.currentTimeMillis();
        Sequence input = getArgument(0).eval(contextSequence);
        if (!(input instanceof VirtualNodeSet) && input.isEmpty())
            result = NodeSet.EMPTY_SET;
        else {
            RangeIndexWorker index = (RangeIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(RangeIndex.ID);
            AtomicValue[] keys = getKeys(contextSequence);
            if (keys.length == 0) {
                return NodeSet.EMPTY_SET;
            }
            List<QName> qnames = null;
            if (contextQName != null) {
                qnames = new ArrayList<>(1);
                qnames.add(contextQName);
            }
            final RangeIndex.Operator operator = getOperator();
            // throw an exception if substring match operation is applied to collated index
            if (usesCollation && !operator.supportsCollation()) {
                throw new XPathException(this, RangeIndexModule.EXXQDYFT0001, "Index defines a collation which cannot be " + "used with the '" + operator + "' operation.");
            }
            try {
                NodeSet inNodes = input.toNodeSet();
                DocumentSet docs = inNodes.getDocumentSet();
                result = index.query(getExpressionId(), docs, inNodes, qnames, keys, operator, NodeSet.ANCESTOR);
            } catch (IOException e) {
                throw new XPathException(this, e.getMessage());
            }
        }
        if (context.getProfiler().traceFunctions()) {
            context.getProfiler().traceIndexUsage(context, "new-range", this, PerformanceStats.BASIC_INDEX, System.currentTimeMillis() - start);
        }
    // LOG.info("eval plain took " + (System.currentTimeMillis() - start));
    } else {
        // long start = System.currentTimeMillis();
        contextStep.setPreloadedData(preselectResult.getDocumentSet(), preselectResult);
        result = getArgument(0).eval(contextSequence).toNodeSet();
    // LOG.info("eval took " + (System.currentTimeMillis() - start));
    }
    return result;
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) QName(org.exist.dom.QName) IOException(java.io.IOException) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) RangeIndexWorker(org.exist.indexing.range.RangeIndexWorker) DocumentSet(org.exist.dom.persistent.DocumentSet) RangeIndex(org.exist.indexing.range.RangeIndex)

Example 38 with DocumentSet

use of org.exist.dom.persistent.DocumentSet in project exist by eXist-db.

the class Lookup method preSelect.

@Override
public NodeSet preSelect(Sequence contextSequence, boolean useContext) throws XPathException {
    if (!canOptimize) {
        return ((Optimizable) fallback).preSelect(contextSequence, useContext);
    }
    if (contextSequence != null && !contextSequence.isPersistentSet())
        // in-memory docs won't have an index
        return NodeSet.EMPTY_SET;
    // throw an exception if substring match operation is applied to collated index
    final RangeIndex.Operator operator = getOperator();
    if (usesCollation && !operator.supportsCollation()) {
        throw new XPathException(this, RangeIndexModule.EXXQDYFT0001, "Index defines a collation which cannot be " + "used with the '" + operator + "' operation.");
    }
    long start = System.currentTimeMillis();
    // the expression can be called multiple times, so we need to clear the previous preselectResult
    preselectResult = null;
    RangeIndexWorker index = (RangeIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(RangeIndex.ID);
    DocumentSet docs = contextSequence.getDocumentSet();
    AtomicValue[] keys = getKeys(contextSequence);
    if (keys.length == 0) {
        return NodeSet.EMPTY_SET;
    }
    List<QName> qnames = null;
    if (contextQName != null) {
        qnames = new ArrayList<>(1);
        qnames.add(contextQName);
    }
    try {
        preselectResult = index.query(getExpressionId(), docs, contextSequence.toNodeSet(), qnames, keys, operator, NodeSet.DESCENDANT);
    } catch (XPathException | IOException e) {
        throw new XPathException(this, "Error while querying full text index: " + e.getMessage(), e);
    }
    // " and took " + (System.currentTimeMillis() - start));
    if (context.getProfiler().traceFunctions()) {
        context.getProfiler().traceIndexUsage(context, "new-range", this, PerformanceStats.OPTIMIZED_INDEX, System.currentTimeMillis() - start);
    }
    if (preselectResult == null) {
        preselectResult = NodeSet.EMPTY_SET;
    }
    return preselectResult;
}
Also used : QName(org.exist.dom.QName) IOException(java.io.IOException) RangeIndexWorker(org.exist.indexing.range.RangeIndexWorker) DocumentSet(org.exist.dom.persistent.DocumentSet) RangeIndex(org.exist.indexing.range.RangeIndex)

Example 39 with DocumentSet

use of org.exist.dom.persistent.DocumentSet in project exist by eXist-db.

the class FunIdRef method eval.

/**
 * @see org.exist.xquery.Expression#eval(Sequence, 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 (getArgumentCount() < 1) {
        throw new XPathException(this, ErrorCodes.XPST0017, "function id requires one argument");
    }
    if (contextItem != null) {
        contextSequence = contextItem.toSequence();
    }
    Sequence result;
    boolean processInMem = false;
    final Expression arg = getArgument(0);
    final Sequence idrefval = arg.eval(contextSequence);
    if (idrefval.isEmpty()) {
        result = Sequence.EMPTY_SEQUENCE;
    } else {
        String nextId;
        DocumentSet docs = null;
        if (getArgumentCount() == 2) {
            // second argument should be a node, whose owner document will be
            // searched for the id
            final Sequence nodes = getArgument(1).eval(contextSequence);
            if (nodes.isEmpty()) {
                throw new XPathException(this, ErrorCodes.XPDY0002, "no node or context item for fn:idref");
            }
            if (!Type.subTypeOf(nodes.itemAt(0).getType(), Type.NODE)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "fn:idref() argument is not a node");
            }
            NodeValue node = (NodeValue) nodes.itemAt(0);
            if (node.getImplementationType() == NodeValue.IN_MEMORY_NODE) // TODO : how to enforce this ?
            // If $node, or the context item if the second argument is omitted,
            // is a node in a tree whose root is not a document node [err:FODC0001] is raised                    processInMem = true;
            {
                processInMem = true;
            } else {
                MutableDocumentSet ndocs = new DefaultDocumentSet();
                ndocs.add(((NodeProxy) node).getOwnerDocument());
                docs = ndocs;
            }
            contextSequence = node;
        } else if (contextSequence == null) {
            throw new XPathException(this, ErrorCodes.XPDY0002, "no context item specified");
        } else if (!Type.subTypeOf(contextSequence.getItemType(), Type.NODE)) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "context item is not a node");
        } else {
            if (contextSequence.isPersistentSet()) {
                docs = contextSequence.toNodeSet().getDocumentSet();
            } else {
                processInMem = true;
            }
        }
        if (processInMem) {
            result = new ValueSequence();
        } else {
            result = new ExtArrayNodeSet();
        }
        for (final SequenceIterator i = idrefval.iterate(); i.hasNext(); ) {
            nextId = i.nextItem().getStringValue();
            if (nextId.isEmpty()) {
                continue;
            }
            if (XMLNames.isNCName(nextId)) {
                if (processInMem) {
                    getIdRef(result, contextSequence, nextId);
                } else {
                    getIdRef((NodeSet) result, docs, nextId);
                }
            }
        }
    }
    result.removeDuplicates();
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : NodeValue(org.exist.xquery.value.NodeValue) MutableDocumentSet(org.exist.dom.persistent.MutableDocumentSet) DefaultDocumentSet(org.exist.dom.persistent.DefaultDocumentSet) ExtArrayNodeSet(org.exist.dom.persistent.ExtArrayNodeSet) SequenceIterator(org.exist.xquery.value.SequenceIterator) XPathException(org.exist.xquery.XPathException) Expression(org.exist.xquery.Expression) ValueSequence(org.exist.xquery.value.ValueSequence) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) DefaultDocumentSet(org.exist.dom.persistent.DefaultDocumentSet) DocumentSet(org.exist.dom.persistent.DocumentSet) MutableDocumentSet(org.exist.dom.persistent.MutableDocumentSet)

Example 40 with DocumentSet

use of org.exist.dom.persistent.DocumentSet in project exist by eXist-db.

the class FunMatches method evalWithIndex.

/**
 * @param contextSequence the context sequence
 * @param contextItem the context item
 * @param input the value of the $input arg
 * @return The resulting sequence
 * @throws XPathException if an error occurs
 */
private Sequence evalWithIndex(final Sequence contextSequence, final Item contextItem, final Sequence input) 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());
        }
    }
    final int flags;
    if (getSignature().getArgumentCount() == 3) {
        final String flagsArg = getArgument(2).eval(contextSequence, contextItem).getStringValue();
        flags = parseFlags(this, flagsArg);
    } else {
        flags = 0;
    }
    final boolean caseSensitive = !hasCaseInsensitive(flags);
    Sequence result = null;
    final String pattern;
    if (isCalledAs("matches-regex")) {
        pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
    } else {
        final boolean literal = hasLiteral(flags);
        if (literal) {
            // no need to change anything
            pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
        } else {
            final boolean ignoreWhitespace = hasIgnoreWhitespace(flags);
            final boolean caseBlind = !caseSensitive;
            pattern = translateRegexp(this, getArgument(1).eval(contextSequence, contextItem).getStringValue(), ignoreWhitespace, caseBlind);
        }
    }
    final NodeSet nodes = input.toNodeSet();
    // get the type of a possible index
    final int indexType = nodes.getIndexType();
    if (LOG.isTraceEnabled()) {
        LOG.trace("found an index of type: {}", Type.getTypeName(indexType));
    }
    if (Type.subTypeOf(indexType, Type.STRING)) {
        boolean indexScan = false;
        if (contextSequence != null) {
            final GeneralComparison.IndexFlags iflags = GeneralComparison.checkForQNameIndex(idxflags, context, contextSequence, contextQName);
            boolean indexFound = false;
            if (!iflags.indexOnQName()) {
                // if contextQName != null and no index is defined on
                // contextQName, we don't need to scan other QName indexes
                // and can just use the generic range index
                indexFound = contextQName != null;
                // set contextQName to null so the index lookup below is not
                // restricted to that QName
                contextQName = null;
            }
            if (!indexFound && contextQName == null) {
                // we need to check them all
                if (iflags.hasIndexOnQNames()) {
                    indexScan = true;
                }
            // else use range index defined on path by default
            }
        } else {
            result = evalFallback(nodes, pattern, flags, indexType);
        }
        if (result == null) {
            final DocumentSet docs = nodes.getDocumentSet();
            try {
                final NativeValueIndex index = context.getBroker().getValueIndex();
                hasUsedIndex = true;
                // TODO : check index' case compatibility with flags' one ? -pb
                if (context.isProfilingEnabled()) {
                    context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "Using value index '" + index.toString() + "'", "Regex: " + pattern);
                }
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Using range index for fn:matches expression: {}", pattern);
                }
                if (indexScan) {
                    result = index.matchAll(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, pattern, DBBroker.MATCH_REGEXP, flags, caseSensitive);
                } else {
                    result = index.match(context.getWatchDog(), docs, nodes, NodeSet.ANCESTOR, pattern, contextQName, DBBroker.MATCH_REGEXP, flags, caseSensitive);
                }
            } catch (final EXistException e) {
                throw new XPathException(this, e);
            }
        }
    } else {
        result = evalFallback(nodes, pattern, flags, indexType);
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : ExtArrayNodeSet(org.exist.dom.persistent.ExtArrayNodeSet) NodeSet(org.exist.dom.persistent.NodeSet) NativeValueIndex(org.exist.storage.NativeValueIndex) Sequence(org.exist.xquery.value.Sequence) DocumentSet(org.exist.dom.persistent.DocumentSet) EXistException(org.exist.EXistException)

Aggregations

DocumentSet (org.exist.dom.persistent.DocumentSet)50 QName (org.exist.dom.QName)20 DefaultDocumentSet (org.exist.dom.persistent.DefaultDocumentSet)18 Sequence (org.exist.xquery.value.Sequence)18 MutableDocumentSet (org.exist.dom.persistent.MutableDocumentSet)16 NodeSet (org.exist.dom.persistent.NodeSet)14 DBBroker (org.exist.storage.DBBroker)14 BrokerPool (org.exist.storage.BrokerPool)13 CompiledXQuery (org.exist.xquery.CompiledXQuery)12 XQuery (org.exist.xquery.XQuery)12 IOException (java.io.IOException)9 Txn (org.exist.storage.txn.Txn)9 TransactionManager (org.exist.storage.txn.TransactionManager)8 Test (org.junit.Test)7 DocumentImpl (org.exist.dom.persistent.DocumentImpl)6 InputSource (org.xml.sax.InputSource)6 StringReader (java.io.StringReader)5 LuceneIndexWorker (org.exist.indexing.lucene.LuceneIndexWorker)5 XPathException (org.exist.xquery.XPathException)5 VirtualNodeSet (org.exist.dom.persistent.VirtualNodeSet)4