Search in sources :

Example 1 with ExecutionMode

use of org.exist.xquery.Predicate.ExecutionMode in project exist by eXist-db.

the class Predicate method evalPredicate.

public Sequence evalPredicate(final Sequence outerSequence, final Sequence contextSequence, final int mode) 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);
        }
    }
    Sequence result;
    final Expression inner = steps.size() == 1 ? getSubExpression(0) : this;
    if (inner == null) {
        result = Sequence.EMPTY_SEQUENCE;
    } else {
        if (executionMode == UNKNOWN) {
            executionMode = BOOLEAN;
        }
        final Tuple2<ExecutionMode, Sequence> recomputed = recomputeExecutionMode(contextSequence, inner);
        final ExecutionMode recomputedExecutionMode = recomputed._1;
        Sequence innerSeq = recomputed._2;
        switch(recomputedExecutionMode) {
            case NODE:
                if (context.getProfiler().isEnabled()) {
                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "Node selection");
                }
                result = selectByNodeSet(contextSequence);
                break;
            case BOOLEAN:
                if (context.getProfiler().isEnabled()) {
                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "Boolean evaluation");
                }
                result = evalBoolean(contextSequence, inner, mode);
                break;
            case POSITIONAL:
                if (context.getProfiler().isEnabled()) {
                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "Positional evaluation");
                }
                // In case it hasn't been evaluated above
                if (innerSeq == null) {
                    // for a positional predicate, check if it depends on the context item
                    // if not, do not pass the context sequence to avoid cardinality errors
                    context.setContextSequencePosition(0, contextSequence);
                    innerSeq = inner.eval(Dependency.dependsOn(inner.getDependencies(), Dependency.CONTEXT_ITEM) ? contextSequence : null);
                }
                // We must check for empty sequences here to avoid an NPE
                if (innerSeq.isEmpty()) {
                    result = Sequence.EMPTY_SEQUENCE;
                } else if (innerSeq.getCardinality().isSubCardinalityOrEqualOf(Cardinality.EXACTLY_ONE)) {
                    result = selectByPosition(outerSequence, contextSequence, mode, innerSeq);
                } else {
                    throw new XPathException(this, ErrorCodes.FORG0006, "Effective boolean value is not defined for a sequence of two or more items starting with a " + Type.getTypeName(innerSeq.itemAt(0).getType()) + " value");
                }
                break;
            default:
                throw new IllegalArgumentException("Unsupported execution mode: '" + recomputedExecutionMode + "'");
        }
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : ExecutionMode(org.exist.xquery.Predicate.ExecutionMode) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence)

Example 2 with ExecutionMode

use of org.exist.xquery.Predicate.ExecutionMode in project exist by eXist-db.

the class Predicate method recomputeExecutionMode.

private Tuple2<ExecutionMode, Sequence> recomputeExecutionMode(final Sequence contextSequence, final Expression inner) throws XPathException {
    ExecutionMode recomputedExecutionMode = executionMode;
    Sequence innerSeq = null;
    // Atomic context sequences :
    if (Type.subTypeOf(contextSequence.getItemType(), Type.ATOMIC)) {
        // the inner sequence
        if (executionMode == NODE && !(contextSequence instanceof VirtualNodeSet)) {
            // (1,2,2,4)[.]
            if (Type.subTypeOfUnion(contextSequence.getItemType(), Type.NUMBER)) {
                recomputedExecutionMode = POSITIONAL;
            } else {
                recomputedExecutionMode = BOOLEAN;
            }
        }
        // If there is no dependency on the context item, try a positional promotion
        if (executionMode == BOOLEAN && !Dependency.dependsOn(inner, Dependency.CONTEXT_ITEM) && // computation should now be better
        !((inner instanceof GeneralComparison) && ((GeneralComparison) inner).invalidNodeEvaluation)) {
            innerSeq = inner.eval(contextSequence);
            // Only if we have an actual *singleton* of numeric items
            if (innerSeq.hasOne() && Type.subTypeOfUnion(innerSeq.getItemType(), Type.NUMBER)) {
                recomputedExecutionMode = POSITIONAL;
            }
        }
    } else if (executionMode == NODE && !contextSequence.isPersistentSet()) {
        recomputedExecutionMode = BOOLEAN;
    } else {
        if (executionMode == BOOLEAN && !Dependency.dependsOn(inner, Dependency.CONTEXT_ITEM)) {
            /*
                 *
                 * WARNING : this sequence will be evaluated with
                 * preloadable nodesets !
                 */
            innerSeq = inner.eval(contextSequence);
            // We are now sure of the inner sequence return type
            if (Type.subTypeOf(innerSeq.getItemType(), Type.NODE) && innerSeq.isPersistentSet()) {
                recomputedExecutionMode = NODE;
            // Try to promote a boolean evaluation to a positional one
            // Only if we have an actual *singleton* of numeric items
            } else if (innerSeq.hasOne() && Type.subTypeOfUnion(innerSeq.getItemType(), Type.NUMBER)) {
                recomputedExecutionMode = POSITIONAL;
            }
        }
    }
    return Tuple(recomputedExecutionMode, innerSeq);
}
Also used : ExecutionMode(org.exist.xquery.Predicate.ExecutionMode) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) VirtualNodeSet(org.exist.dom.persistent.VirtualNodeSet)

Aggregations

ExecutionMode (org.exist.xquery.Predicate.ExecutionMode)2 Sequence (org.exist.xquery.value.Sequence)2 ValueSequence (org.exist.xquery.value.ValueSequence)2 VirtualNodeSet (org.exist.dom.persistent.VirtualNodeSet)1