use of org.exist.dom.persistent.NodeSet 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;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class FunNot method eval.
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 (contextItem != null) {
contextSequence = contextItem.toSequence();
}
Sequence result;
final Expression arg = getArgument(0);
// the remaining set
if (Type.subTypeOf(arg.returnsType(), Type.NODE) && (contextSequence == null || contextSequence.isPersistentSet()) && !Dependency.dependsOn(arg, Dependency.CONTEXT_ITEM)) {
if (contextSequence == null || contextSequence.isEmpty()) {
// TODO: special treatment if the context sequence is empty:
// within a predicate, we just return the empty sequence
// otherwise evaluate the argument and return a boolean result
// if (inPredicate && !inWhereClause)
// result = Sequence.EMPTY_SEQUENCE;
// else
result = evalBoolean(contextSequence, contextItem, arg);
} else {
result = contextSequence.toNodeSet().copy();
if (inPredicate) {
for (final SequenceIterator i = result.iterate(); i.hasNext(); ) {
final NodeProxy item = (NodeProxy) i.nextItem();
// item.addContextNode(getExpressionId(), item);
if (contextId != Expression.NO_CONTEXT_ID) {
item.addContextNode(contextId, item);
} else {
item.addContextNode(getExpressionId(), item);
}
}
}
// evaluate argument expression
final Sequence argSeq = arg.eval(result);
NodeSet argSet;
if (contextId != Expression.NO_CONTEXT_ID) {
argSet = argSeq.toNodeSet().getContextNodes(contextId);
} else {
argSet = argSeq.toNodeSet().getContextNodes(getExpressionId());
}
result = ((NodeSet) result).except(argSet);
}
// case 2: simply invert the boolean value
} else {
return evalBoolean(contextSequence, contextItem, arg);
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class LocalXPathQueryService method query.
@Override
public ResourceSet query(final XMLResource res, final String query, final String sortBy) throws XMLDBException {
final Node n = ((LocalXMLResource) res).root;
return withDb((broker, transaction) -> {
if (n != null && n instanceof org.exist.dom.memtree.NodeImpl) {
final XmldbURI[] docs = new XmldbURI[] { getCollectionUri(broker, transaction, res.getParentCollection()) };
return doQuery(broker, transaction, query, docs, (org.exist.dom.memtree.NodeImpl) n, sortBy);
}
final NodeProxy node = ((LocalXMLResource) res).getNode(broker, transaction);
if (node == null) {
// resource is a document
// TODO : use dedicated function in XmldbURI
final XmldbURI[] docs = new XmldbURI[] { getCollectionUri(broker, transaction, res.getParentCollection()).append(res.getDocumentId()) };
return doQuery(broker, transaction, query, docs, null, sortBy);
} else {
final NodeSet set = new ExtArrayNodeSet(1);
set.add(node);
final XmldbURI[] docs = new XmldbURI[] { node.getOwnerDocument().getURI() };
return doQuery(broker, transaction, query, docs, set, sortBy);
}
});
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class LocalXPathQueryService method execute.
@Override
public ResourceSet execute(final XMLResource res, final CompiledExpression expression) throws XMLDBException {
return withDb((broker, transaction) -> {
final NodeProxy node = ((LocalXMLResource) res).getNode(broker, transaction);
if (node == null) {
// resource is a document
final XmldbURI[] docs = new XmldbURI[] { getCollectionUri(broker, transaction, res.getParentCollection()).append(res.getDocumentId()) };
return execute(broker, transaction, docs, null, expression, null);
} else {
final NodeSet set = new ExtArrayNodeSet(1);
set.add(node);
final XmldbURI[] docs = new XmldbURI[] { node.getOwnerDocument().getURI() };
return execute(broker, transaction, docs, set, expression, null);
}
});
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class IndexKeyDocuments method eval.
public Sequence eval(Sequence[] args, Sequence contextSequence) 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;
if (args[0].isEmpty()) {
result = Sequence.EMPTY_SEQUENCE;
} else {
final NodeSet nodes = args[0].toNodeSet();
final DocumentSet docs = nodes.getDocumentSet();
if (this.getArgumentCount() == 3) {
final IndexWorker indexWorker = context.getBroker().getIndexController().getWorkerByIndexName(args[2].itemAt(0).getStringValue());
// IndexWorker indexWorker = context.getBroker().getBrokerPool().getIndexManager().getIndexByName(args[2].itemAt(0).getStringValue()).getWorker();
if (indexWorker == null) {
throw new XPathException(this, "Unknown index: " + args[2].itemAt(0).getStringValue());
}
final Map<String, Object> hints = new HashMap<>();
if (indexWorker instanceof OrderedValuesIndex) {
hints.put(OrderedValuesIndex.START_VALUE, args[1]);
} else {
logger.warn("{} isn't an instance of org.exist.indexing.OrderedIndexWorker. Start value '{}' ignored.", indexWorker.getClass().getName(), args[1]);
}
final Occurrences[] occur = indexWorker.scanIndex(context, docs, nodes, hints);
if (occur.length == 0) {
result = Sequence.EMPTY_SEQUENCE;
} else {
result = new IntegerValue(occur[0].getDocuments());
}
} else {
final ValueOccurrences[] occur = context.getBroker().getValueIndex().scanIndexKeys(docs, nodes, (Indexable) args[1]);
if (occur.length == 0) {
result = Sequence.EMPTY_SEQUENCE;
} else {
result = new IntegerValue(occur[0].getDocuments());
}
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
Aggregations