use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class IndexKeyOccurrences 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].getOccurrences());
}
} else {
ValueOccurrences[] occur = context.getBroker().getValueIndex().scanIndexKeys(docs, nodes, (Indexable) (args[1].itemAt(0)));
if (occur.length == 0) {
occur = context.getBroker().getValueIndex().scanIndexKeys(docs, nodes, null, (Indexable) (args[1].itemAt(0)));
}
if (occur.length == 0) {
result = Sequence.EMPTY_SEQUENCE;
} else {
result = new IntegerValue(occur[0].getOccurrences());
}
}
}
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 QueryField method eval.
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (contextItem != null)
contextSequence = contextItem.toSequence();
NodeSet result;
if (preselectResult == null) {
long start = System.currentTimeMillis();
String field = getArgument(0).eval(contextSequence).getStringValue();
Item query = getKey(contextSequence, null);
DocumentSet docs = null;
if (contextSequence == null)
docs = context.getStaticallyKnownDocuments();
else
docs = contextSequence.getDocumentSet();
NodeSet contextSet = null;
if (contextSequence != null)
contextSet = contextSequence.toNodeSet();
LuceneIndexWorker index = (LuceneIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(LuceneIndex.ID);
QueryOptions options = parseOptions(this, contextSequence, contextItem, 3);
try {
if (Type.subTypeOf(query.getType(), Type.ELEMENT))
result = index.queryField(getExpressionId(), docs, contextSet, field, (Element) ((NodeValue) query).getNode(), NodeSet.ANCESTOR, options);
else
result = index.queryField(context, getExpressionId(), docs, contextSet, field, query.getStringValue(), NodeSet.ANCESTOR, options);
} catch (IOException e) {
throw new XPathException(this, e.getMessage());
}
if (context.getProfiler().traceFunctions()) {
context.getProfiler().traceIndexUsage(context, "lucene", this, PerformanceStats.BASIC_INDEX, System.currentTimeMillis() - start);
}
} else {
result = preselectResult.selectAncestorDescendant(contextSequence.toNodeSet(), NodeSet.DESCENDANT, true, getContextId(), true);
}
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class Predicate method selectByNodeSet.
/**
* @param contextSequence the context sequence
*
* @return The result of the node set evaluation of the predicate.
*
* @throws XPathException if an error occurs
*/
private Sequence selectByNodeSet(final Sequence contextSequence) throws XPathException {
final NewArrayNodeSet result = new NewArrayNodeSet();
final NodeSet contextSet = contextSequence.toNodeSet();
final boolean contextIsVirtual = contextSet instanceof VirtualNodeSet;
contextSet.setTrackMatches(false);
final NodeSet nodes = super.eval(contextSet, null).toNodeSet();
/*
* if the predicate expression returns results from the cache we can
* also return the cached result.
*/
if (cached != null && cached.isValid(contextSequence, null) && nodes.isCached()) {
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "Using cached results", result);
}
return cached.getResult();
}
DocumentImpl lastDoc = null;
for (final NodeProxy currentNode : nodes) {
int sizeHint = Constants.NO_SIZE_HINT;
if (lastDoc == null || currentNode.getOwnerDocument() != lastDoc) {
lastDoc = currentNode.getOwnerDocument();
sizeHint = nodes.getSizeHint(lastDoc);
}
ContextItem contextItem = currentNode.getContext();
if (contextItem == null) {
throw new XPathException(this, "Internal evaluation error: context is missing for node " + currentNode.getNodeId() + " !");
}
// TODO : review to consider transverse context
while (contextItem != null) {
if (contextItem.getContextId() == getExpressionId()) {
final NodeProxy next = contextItem.getNode();
if (contextIsVirtual || contextSet.contains(next)) {
next.addMatches(currentNode);
result.add(next, sizeHint);
}
}
contextItem = contextItem.getNextDirect();
}
}
if (contextSequence.isCacheable()) {
cached = new CachedResult(contextSequence, null, result);
}
contextSet.setTrackMatches(true);
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class Predicate method evalBoolean.
/**
* Evaluate the inner part of the predicate as a boolean.
*
* @param contextSequence the context sequence
* @param inner the inner expression
*
* @return The result of the boolean evaluation of the predicate.
*
* @throws XPathException if an error occurs
*/
private Sequence evalBoolean(final Sequence contextSequence, final Expression inner, final int mode) throws XPathException {
final Sequence result = new ValueSequence();
int p;
if (contextSequence instanceof NodeSet && ((NodeSet) contextSequence).getProcessInReverseOrder()) {
// This one may be expensive...
p = contextSequence.getItemCount();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p--) {
// 0-based
context.setContextSequencePosition(p - 1, contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.effectiveBooleanValue()) {
result.add(item);
}
}
} else {
// 0-based
p = 0;
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);
// ... but grab some context positions ! -<8-P
if (Type.subTypeOfUnion(inner.returnsType(), Type.NUMBER) && Dependency.dependsOn(inner, Dependency.CONTEXT_ITEM)) {
final Set<NumericValue> positions = new TreeSet<>();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p++) {
context.setContextSequencePosition(p, contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.hasOne()) {
final NumericValue nv = (NumericValue) innerSeq.itemAt(0);
// Non integers return... nothing, not even an error !
if (!nv.hasFractionalPart() && !nv.isZero()) {
positions.add(nv);
}
}
// XXX: else error or nothing?
}
for (final NumericValue pos : positions) {
final int position = (reverseAxis ? contextSequence.getItemCount() - pos.getInt() : pos.getInt() - 1);
// TODO : move this test above ?
if (position <= contextSequence.getItemCount()) {
result.add(contextSequence.itemAt(position));
}
}
} else {
final Set<NumericValue> positions = new TreeSet<>();
for (final SequenceIterator i = contextSequence.iterate(); i.hasNext(); p++) {
context.setContextSequencePosition((reverseAxis ? contextSequence.getItemCount() - p - 1 : p), contextSequence);
final Item item = i.nextItem();
final Sequence innerSeq = inner.eval(contextSequence, item);
if (innerSeq.hasOne() && Type.subTypeOfUnion(innerSeq.getItemType(), Type.NUMBER)) {
// TODO : introduce a check in innerSeq.hasOne() ?
final NumericValue nv = (NumericValue) innerSeq;
// Non integers return... nothing, not even an error !
if (!nv.hasFractionalPart() && !nv.isZero()) {
positions.add(nv);
}
} else if (innerSeq.effectiveBooleanValue()) {
result.add(item);
}
}
for (final NumericValue pos : positions) {
final int position = (reverseAxis ? contextSequence.getItemCount() - pos.getInt() : pos.getInt() - 1);
// TODO : move this test above ?
if (position <= contextSequence.getItemCount()) {
result.add(contextSequence.itemAt(position));
}
}
}
}
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class GeneralComparison method nodeSetCompare.
/**
* Optimized implementation, which can be applied if the left operand returns a node set. In this case, the left expression is executed first. All
* matching context nodes are then passed to the right expression.
*
* @param nodes DOCUMENT ME!
* @param contextSequence DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws XPathException DOCUMENT ME!
*/
protected Sequence nodeSetCompare(NodeSet nodes, Sequence contextSequence) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "nodeSetCompare");
}
if (LOG.isTraceEnabled()) {
LOG.trace("No index: fall back to nodeSetCompare");
}
final long start = System.currentTimeMillis();
final NodeSet result = new NewArrayNodeSet();
final Collator collator = getCollator(contextSequence);
if ((contextSequence != null) && !contextSequence.isEmpty() && !contextSequence.getDocumentSet().contains(nodes.getDocumentSet())) {
for (final NodeProxy item : nodes) {
ContextItem context = item.getContext();
if (context == null) {
throw (new XPathException(this, "Internal error: context node missing"));
}
final AtomicValue lv = item.atomize();
do {
final Sequence rs = getRight().eval(context.getNode().toSequence());
for (final SequenceIterator i2 = Atomize.atomize(rs).iterate(); i2.hasNext(); ) {
final AtomicValue rv = i2.nextItem().atomize();
if (compareAtomic(collator, lv, rv)) {
result.add(item);
}
}
} while ((context = context.getNextDirect()) != null);
}
} else {
for (final NodeProxy item : nodes) {
final AtomicValue lv = item.atomize();
final Sequence rs = getRight().eval(contextSequence);
for (final SequenceIterator i2 = Atomize.atomize(rs).iterate(); i2.hasNext(); ) {
final AtomicValue rv = i2.nextItem().atomize();
if (compareAtomic(collator, lv, rv)) {
result.add(item);
}
}
}
}
if (context.getProfiler().traceFunctions()) {
context.getProfiler().traceIndexUsage(context, PerformanceStats.RANGE_IDX_TYPE, this, PerformanceStats.NO_INDEX, System.currentTimeMillis() - start);
}
return (result);
}
Aggregations