use of org.exist.storage.NativeValueIndex 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.storage.NativeValueIndex in project exist by eXist-db.
the class QNameIndexLookup method eval.
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (contextSequence == null || contextSequence.isEmpty()) {
// if the context sequence is empty, we create a default context
final RootNode rootNode = new RootNode(context);
contextSequence = rootNode.eval(null, null);
}
final Sequence[] args = getArguments(null, null);
final Item item = args[0].itemAt(0);
final QNameValue qval;
try {
// attempt to convert the first argument to a QName
qval = (QNameValue) item.convertTo(Type.QNAME);
} catch (final XPathException e) {
// wrong type: generate a diagnostic error
throw new XPathException(this, Messages.formatMessage(Error.FUNC_PARAM_TYPE, new Object[] { "1", getSignature().toString(), null, Type.getTypeName(Type.QNAME), Type.getTypeName(item.getType()) }));
}
QName qname = qval.getQName();
if (args.length == 3 && !(args[2].itemAt(0).toJavaObject(boolean.class))) {
qname = new QName(qname.getLocalPart(), qname.getNamespaceURI(), qname.getPrefix(), ElementValue.ATTRIBUTE);
}
final AtomicValue comparisonCriterion = args[1].itemAt(0).atomize();
final NativeValueIndex valueIndex = context.getBroker().getValueIndex();
final Sequence result = valueIndex.find(context.getWatchDog(), Comparison.EQ, contextSequence.getDocumentSet(), null, NodeSet.ANCESTOR, qname, comparisonCriterion);
return result;
}
Aggregations