Search in sources :

Example 1 with NodeSet

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

the class XQueryTrigger method finish.

private void finish(int event, DBBroker broker, Txn transaction, XmldbURI src, XmldbURI dst, boolean isCollection) {
    // get the query
    final Source query = getQuerySource(broker);
    if (query == null) {
        return;
    }
    // avoid infinite recursion by allowing just one trigger per thread
    if (!TriggerStatePerThread.verifyUniqueTriggerPerThreadBeforeFinish(this, src)) {
        return;
    }
    final XQueryContext context = new XQueryContext(broker.getBrokerPool());
    CompiledXQuery compiledQuery = null;
    try {
        // compile the XQuery
        compiledQuery = service.compile(context, query);
        // declare external variables
        context.declareVariable(bindingPrefix + "type", EVENT_TYPE_FINISH);
        context.declareVariable(bindingPrefix + "event", new StringValue(eventToString(event)));
        if (isCollection) {
            context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src));
        } else {
            context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src.removeLastSegment()));
        }
        context.declareVariable(bindingPrefix + "uri", new AnyURIValue(src));
        if (dst == null) {
            context.declareVariable(bindingPrefix + "new-uri", Sequence.EMPTY_SEQUENCE);
        } else {
            context.declareVariable(bindingPrefix + "new-uri", new AnyURIValue(dst));
        }
        // For backward compatibility
        context.declareVariable(bindingPrefix + "eventType", EVENT_TYPE_FINISH);
        context.declareVariable(bindingPrefix + "triggerEvent", new StringValue(eventToString(event)));
        if (isCollection) {
            context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src));
        } else {
            context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src.removeLastSegment()));
            context.declareVariable(bindingPrefix + "documentName", new AnyURIValue(src));
        }
        // declare user defined parameters as external variables
        for (Object o : userDefinedVariables.keySet()) {
            final String varName = (String) o;
            final String varValue = userDefinedVariables.getProperty(varName);
            context.declareVariable(bindingPrefix + varName, new StringValue(varValue));
        }
    } catch (final XPathException | IOException | PermissionDeniedException e) {
        // Should never be reached
        LOG.error(e);
    }
    // execute the XQuery
    try {
        // TODO : should we provide another contextSet ?
        final NodeSet contextSet = NodeSet.EMPTY_SET;
        service.execute(broker, compiledQuery, contextSet);
    // TODO : should we have a special processing ?
    } catch (final XPathException e) {
        // Should never be reached
        LOG.error("Error during trigger finish", e);
    } catch (final PermissionDeniedException e) {
        // Should never be reached
        LOG.error(e);
    }
    TriggerStatePerThread.setTriggerRunningState(TriggerStatePerThread.NO_TRIGGER_RUNNING, this, null);
    TriggerStatePerThread.setTransaction(null);
    LOG.debug("Trigger fired for finish");
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) AnyURIValue(org.exist.xquery.value.AnyURIValue) PermissionDeniedException(org.exist.security.PermissionDeniedException) IOException(java.io.IOException) StringValue(org.exist.xquery.value.StringValue) StringSource(org.exist.source.StringSource) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource)

Example 2 with NodeSet

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

the class XQueryTrigger method prepare.

private void prepare(int event, DBBroker broker, Txn transaction, XmldbURI src, XmldbURI dst, boolean isCollection) throws TriggerException {
    // get the query
    final Source query = getQuerySource(broker);
    if (query == null) {
        return;
    }
    // avoid infinite recursion by allowing just one trigger per thread
    if (!TriggerStatePerThread.verifyUniqueTriggerPerThreadBeforePrepare(this, src)) {
        return;
    }
    TriggerStatePerThread.setTransaction(transaction);
    final XQueryContext context = new XQueryContext(broker.getBrokerPool());
    // TODO : further initialisations ?
    CompiledXQuery compiledQuery;
    try {
        // compile the XQuery
        compiledQuery = service.compile(context, query);
        // declare external variables
        context.declareVariable(bindingPrefix + "type", EVENT_TYPE_PREPARE);
        context.declareVariable(bindingPrefix + "event", new StringValue(eventToString(event)));
        if (isCollection) {
            context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src));
        } else {
            context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src.removeLastSegment()));
        }
        context.declareVariable(bindingPrefix + "uri", new AnyURIValue(src));
        if (dst == null) {
            context.declareVariable(bindingPrefix + "new-uri", Sequence.EMPTY_SEQUENCE);
        } else {
            context.declareVariable(bindingPrefix + "new-uri", new AnyURIValue(dst));
        }
        // For backward compatibility
        context.declareVariable(bindingPrefix + "eventType", EVENT_TYPE_PREPARE);
        context.declareVariable(bindingPrefix + "triggerEvent", new StringValue(eventToString(event)));
        if (isCollection) {
            context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src));
        } else {
            context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src.removeLastSegment()));
            context.declareVariable(bindingPrefix + "documentName", new AnyURIValue(src));
        }
        // declare user defined parameters as external variables
        for (Object o : userDefinedVariables.keySet()) {
            final String varName = (String) o;
            final String varValue = userDefinedVariables.getProperty(varName);
            context.declareVariable(bindingPrefix + varName, new StringValue(varValue));
        }
    } catch (final XPathException | IOException | PermissionDeniedException e) {
        TriggerStatePerThread.setTriggerRunningState(TriggerStatePerThread.NO_TRIGGER_RUNNING, this, null);
        TriggerStatePerThread.setTransaction(null);
        throw new TriggerException(PREPARE_EXCEPTION_MESSAGE, e);
    }
    // execute the XQuery
    try {
        // TODO : should we provide another contextSet ?
        final NodeSet contextSet = NodeSet.EMPTY_SET;
        service.execute(broker, compiledQuery, contextSet);
        // TODO : should we have a special processing ?
        LOG.debug("Trigger fired for prepare");
    } catch (final XPathException | PermissionDeniedException e) {
        TriggerStatePerThread.setTriggerRunningState(TriggerStatePerThread.NO_TRIGGER_RUNNING, this, null);
        TriggerStatePerThread.setTransaction(null);
        throw new TriggerException(PREPARE_EXCEPTION_MESSAGE, e);
    }
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) AnyURIValue(org.exist.xquery.value.AnyURIValue) IOException(java.io.IOException) StringSource(org.exist.source.StringSource) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource) PermissionDeniedException(org.exist.security.PermissionDeniedException) StringValue(org.exist.xquery.value.StringValue)

Example 3 with NodeSet

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

the class Predicate method selectByPosition.

/**
 * @param outerSequence the outer sequence
 * @param contextSequence the context sequence
 * @param mode the mode
 * @param innerSeq the inner sequence
 *
 * @return The result of the positional evaluation of the predicate.
 *
 * @throws XPathException if an error occurs
 */
private Sequence selectByPosition(final Sequence outerSequence, final Sequence contextSequence, final int mode, final Sequence innerSeq) throws XPathException {
    if (outerSequence != null && !outerSequence.isEmpty() && Type.subTypeOf(contextSequence.getItemType(), Type.NODE) && contextSequence.isPersistentSet() && outerSequence.isPersistentSet()) {
        final Sequence result = new NewArrayNodeSet();
        final NodeSet contextSet = contextSequence.toNodeSet();
        switch(mode) {
            case Constants.CHILD_AXIS:
            case Constants.ATTRIBUTE_AXIS:
            case Constants.DESCENDANT_AXIS:
            case Constants.DESCENDANT_SELF_AXIS:
            case Constants.DESCENDANT_ATTRIBUTE_AXIS:
                {
                    final NodeSet outerNodeSet = outerSequence.toNodeSet();
                    // TODO: in some cases, especially with in-memory nodes,
                    // outerSequence.toNodeSet() will generate a document
                    // which will be different from the one(s) in contextSet
                    // ancestors will thus be empty :-(
                    // A special treatment of VirtualNodeSet does not seem to be
                    // required anymore
                    final Sequence ancestors = outerNodeSet.selectAncestors(contextSet, true, getExpressionId());
                    if (contextSet.getDocumentSet().intersection(outerNodeSet.getDocumentSet()).getDocumentCount() == 0) {
                        LOG.info("contextSet and outerNodeSet don't share any document");
                    }
                    final NewArrayNodeSet temp = new NewArrayNodeSet();
                    for (final SequenceIterator i = ancestors.iterate(); i.hasNext(); ) {
                        NodeProxy p = (NodeProxy) i.nextItem();
                        ContextItem contextNode = p.getContext();
                        temp.reset();
                        while (contextNode != null) {
                            if (contextNode.getContextId() == getExpressionId()) {
                                temp.add(contextNode.getNode());
                            }
                            contextNode = contextNode.getNextDirect();
                        }
                        p.clearContext(getExpressionId());
                        // TODO : understand why we sort here...
                        temp.sortInDocumentOrder();
                        for (final SequenceIterator j = innerSeq.iterate(); j.hasNext(); ) {
                            final NumericValue v = (NumericValue) j.nextItem();
                            // Non integers return... nothing, not even an error !
                            if (!v.hasFractionalPart() && !v.isZero()) {
                                // ... whereas we don't want a sorted array here
                                // TODO : rename this method as getInDocumentOrder ? -pb
                                p = temp.get(v.getInt() - 1);
                                if (p != null) {
                                    result.add(p);
                                }
                            // TODO : does null make sense here ? Well... sometimes ;-)
                            }
                        }
                    }
                    break;
                }
            default:
                for (final SequenceIterator i = outerSequence.iterate(); i.hasNext(); ) {
                    NodeProxy p = (NodeProxy) i.nextItem();
                    Sequence temp;
                    boolean reverseAxis = true;
                    switch(mode) {
                        case Constants.ANCESTOR_AXIS:
                            temp = contextSet.selectAncestors(p, false, Expression.IGNORE_CONTEXT);
                            break;
                        case Constants.ANCESTOR_SELF_AXIS:
                            temp = contextSet.selectAncestors(p, true, Expression.IGNORE_CONTEXT);
                            break;
                        case Constants.PARENT_AXIS:
                            // TODO : understand why the contextSet is not involved
                            // here
                            // NodeProxy.getParent returns a *theoretical* parent
                            // which is *not* guaranteed to be in the context set !
                            temp = p.getParents(Expression.NO_CONTEXT_ID);
                            break;
                        case Constants.PRECEDING_AXIS:
                            temp = contextSet.selectPreceding(p, Expression.IGNORE_CONTEXT);
                            break;
                        case Constants.PRECEDING_SIBLING_AXIS:
                            temp = contextSet.selectPrecedingSiblings(p, Expression.IGNORE_CONTEXT);
                            break;
                        case Constants.FOLLOWING_SIBLING_AXIS:
                            temp = contextSet.selectFollowingSiblings(p, Expression.IGNORE_CONTEXT);
                            reverseAxis = false;
                            break;
                        case Constants.FOLLOWING_AXIS:
                            temp = contextSet.selectFollowing(p, Expression.IGNORE_CONTEXT);
                            reverseAxis = false;
                            break;
                        case Constants.SELF_AXIS:
                            temp = p;
                            reverseAxis = false;
                            break;
                        default:
                            throw new IllegalArgumentException("Tried to test unknown axis");
                    }
                    if (!temp.isEmpty()) {
                        for (final SequenceIterator j = innerSeq.iterate(); j.hasNext(); ) {
                            final NumericValue v = (NumericValue) j.nextItem();
                            // Non integers return... nothing, not even an error !
                            if (!v.hasFractionalPart() && !v.isZero()) {
                                final int pos = (reverseAxis ? temp.getItemCount() - v.getInt() : v.getInt() - 1);
                                // Other positions are ignored
                                if (pos >= 0 && pos < temp.getItemCount()) {
                                    final NodeProxy t = (NodeProxy) temp.itemAt(pos);
                                    // for the current context: filter out those
                                    // context items not selected by the positional predicate
                                    ContextItem ctx = t.getContext();
                                    t.clearContext(Expression.IGNORE_CONTEXT);
                                    while (ctx != null) {
                                        if (ctx.getContextId() == outerContextId) {
                                            if (ctx.getNode().getNodeId().equals(p.getNodeId())) {
                                                t.addContextNode(outerContextId, ctx.getNode());
                                            }
                                        } else {
                                            t.addContextNode(ctx.getContextId(), ctx.getNode());
                                        }
                                        ctx = ctx.getNextDirect();
                                    }
                                    result.add(t);
                                }
                            }
                        }
                    }
                }
        }
        return result;
    } else {
        final boolean reverseAxis = Type.subTypeOf(contextSequence.getItemType(), Type.NODE) && (mode == Constants.ANCESTOR_AXIS || mode == Constants.ANCESTOR_SELF_AXIS || mode == Constants.PARENT_AXIS || mode == Constants.PRECEDING_AXIS || mode == Constants.PRECEDING_SIBLING_AXIS);
        final Set<NumericValue> set = new TreeSet<>();
        final ValueSequence result = new ValueSequence();
        for (final SequenceIterator i = innerSeq.iterate(); i.hasNext(); ) {
            final NumericValue v = (NumericValue) i.nextItem();
            // Non integers return... nothing, not even an error !
            if (!v.hasFractionalPart() && !v.isZero()) {
                final int pos = (reverseAxis ? contextSequence.getItemCount() - v.getInt() : v.getInt() - 1);
                // Other positions are ignored
                if (pos >= 0 && pos < contextSequence.getItemCount() && !set.contains(v)) {
                    result.add(contextSequence.itemAt(pos));
                    set.add(v);
                }
            }
        }
        return result;
    }
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) ContextItem(org.exist.dom.persistent.ContextItem) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) NodeProxy(org.exist.dom.persistent.NodeProxy) SequenceIterator(org.exist.xquery.value.SequenceIterator) TreeSet(java.util.TreeSet) ValueSequence(org.exist.xquery.value.ValueSequence) NumericValue(org.exist.xquery.value.NumericValue)

Example 4 with NodeSet

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

the class GeneralComparison method preSelect.

public NodeSet preSelect(Sequence contextSequence, boolean useContext) throws XPathException {
    // the expression can be called multiple times, so we need to clear the previous preselectResult
    preselectResult = null;
    final long start = System.currentTimeMillis();
    final int indexType = Optimize.getQNameIndexType(context, contextSequence, contextQName);
    if (LOG.isTraceEnabled()) {
        LOG.trace("Using QName index on type {}", Type.getTypeName(indexType));
    }
    final Sequence rightSeq = getRight().eval(contextSequence);
    // into preselectResult
    if (rightSeq.getItemCount() > 1) {
        preselectResult = new NewArrayNodeSet();
    }
    // Iterate through each item in 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) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Cannot convert key: {} to required index type: {}", Type.getTypeName(key.getType()), Type.getTypeName(indexType));
                }
                throw (new XPathException(this, "Cannot convert key to required index type"));
            }
        }
        // If key implements org.exist.storage.Indexable, we can use the index
        if (key instanceof Indexable) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("Using QName range index for key: {}", key.getStringValue());
            }
            NodeSet temp;
            final NodeSet contextSet = useContext ? contextSequence.toNodeSet() : null;
            final Collator collator = ((collationArg != null) ? getCollator(contextSequence) : null);
            if (truncation == StringTruncationOperator.NONE) {
                temp = context.getBroker().getValueIndex().find(context.getWatchDog(), relation, contextSequence.getDocumentSet(), contextSet, NodeSet.DESCENDANT, contextQName, (Indexable) key);
                hasUsedIndex = true;
            } else {
                try {
                    final String matchString = key.getStringValue();
                    final int matchType = getMatchType(truncation);
                    temp = context.getBroker().getValueIndex().match(context.getWatchDog(), contextSequence.getDocumentSet(), contextSet, NodeSet.DESCENDANT, matchString, contextQName, matchType, collator, truncation);
                    hasUsedIndex = true;
                } catch (final EXistException e) {
                    throw (new XPathException(this, "Error during index lookup: " + e.getMessage(), e));
                }
            }
            // else replace it.
            if (preselectResult == null) {
                preselectResult = temp;
            } else {
                preselectResult.addAll(temp);
            }
        }
    }
    if (context.getProfiler().traceFunctions()) {
        context.getProfiler().traceIndexUsage(context, PerformanceStats.RANGE_IDX_TYPE, this, PerformanceStats.OPTIMIZED_INDEX, System.currentTimeMillis() - start);
    }
    return ((preselectResult == null) ? NodeSet.EMPTY_SET : preselectResult);
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) Item(org.exist.xquery.value.Item) ContextItem(org.exist.dom.persistent.ContextItem) SequenceIterator(org.exist.xquery.value.SequenceIterator) Indexable(org.exist.storage.Indexable) Sequence(org.exist.xquery.value.Sequence) EXistException(org.exist.EXistException) Collator(com.ibm.icu.text.Collator)

Example 5 with NodeSet

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

the class GeneralComparison method eval.

/* (non-Javadoc)
     * @see org.exist.xquery.Expression#eval(org.exist.xquery.StaticContext, org.exist.dom.persistent.DocumentSet, 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());
        }
    }
    Sequence result;
    // if the context sequence hasn't changed we can return a cached result
    if ((cached != null) && cached.isValid(contextSequence, contextItem)) {
        LOG.debug("Using cached results");
        if (context.getProfiler().isEnabled()) {
            context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Returned cached result");
        }
        result = cached.getResult();
    } else {
        // we won't have any matches and can return
        if ((preselectResult != null) && preselectResult.isEmpty()) {
            result = Sequence.EMPTY_SEQUENCE;
        } else {
            if ((contextStep == null) || (preselectResult == null)) {
                /*
                     * If we are inside a predicate and one of the arguments is a node set,
                     * we try to speed up the query by returning nodes from the context set.
                     * This works only inside a predicate. The node set will always be the left
                     * operand.
                     */
                if (inPredicate && !invalidNodeEvaluation && !Dependency.dependsOn(this, Dependency.CONTEXT_ITEM) && Type.subTypeOf(getLeft().returnsType(), Type.NODE) && ((contextSequence == null) || contextSequence.isPersistentSet())) {
                    if (contextItem != null) {
                        contextSequence = contextItem.toSequence();
                    }
                    if ((!Dependency.dependsOn(rightOpDeps, Dependency.CONTEXT_ITEM))) {
                        result = quickNodeSetCompare(contextSequence);
                    } else {
                        final NodeSet nodes = (NodeSet) getLeft().eval(contextSequence);
                        result = nodeSetCompare(nodes, contextSequence);
                    }
                } else {
                    result = genericCompare(contextSequence, contextItem);
                }
            } else {
                contextStep.setPreloadedData(preselectResult.getDocumentSet(), preselectResult);
                result = getLeft().eval(contextSequence).toNodeSet();
                // the expression can be called multiple times, so we need to clear the previous preselectResult
                preselectResult = null;
            }
        }
        // can this result be cached? Don't cache if the result depends on local variables.
        final boolean canCache = (contextSequence != null) && contextSequence.isCacheable() && !Dependency.dependsOn(getLeft(), Dependency.CONTEXT_ITEM) && !Dependency.dependsOn(getRight(), Dependency.CONTEXT_ITEM) && !Dependency.dependsOnVar(getLeft()) && !Dependency.dependsOnVar(getRight());
        if (canCache) {
            cached = new CachedResult(contextSequence, contextItem, result);
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    actualReturnType = result.getItemType();
    return (result);
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet) NewArrayNodeSet(org.exist.dom.persistent.NewArrayNodeSet) Sequence(org.exist.xquery.value.Sequence)

Aggregations

NodeSet (org.exist.dom.persistent.NodeSet)49 NodeProxy (org.exist.dom.persistent.NodeProxy)18 Sequence (org.exist.xquery.value.Sequence)18 DocumentSet (org.exist.dom.persistent.DocumentSet)14 NewArrayNodeSet (org.exist.dom.persistent.NewArrayNodeSet)12 QName (org.exist.dom.QName)11 ExtArrayNodeSet (org.exist.dom.persistent.ExtArrayNodeSet)10 VirtualNodeSet (org.exist.dom.persistent.VirtualNodeSet)9 ContextItem (org.exist.dom.persistent.ContextItem)8 IOException (java.io.IOException)7 XPathException (org.exist.xquery.XPathException)7 Collator (com.ibm.icu.text.Collator)4 EXistException (org.exist.EXistException)4 DocumentImpl (org.exist.dom.persistent.DocumentImpl)4 EmptyNodeSet (org.exist.dom.persistent.EmptyNodeSet)4 Indexable (org.exist.storage.Indexable)4 SequenceIterator (org.exist.xquery.value.SequenceIterator)4 StringValue (org.exist.xquery.value.StringValue)4 NodeImpl (org.exist.dom.memtree.NodeImpl)3 Match (org.exist.dom.persistent.Match)3