use of org.apache.jackrabbit.oak.spi.query.QueryIndex in project jackrabbit-oak by apache.
the class SelectorImpl method getPlan.
@Override
public String getPlan(NodeState rootState) {
StringBuilder buff = new StringBuilder();
buff.append(toString());
buff.append(" /* ");
QueryIndex index = getIndex();
if (index != null) {
if (index instanceof AdvancedQueryIndex) {
AdvancedQueryIndex adv = (AdvancedQueryIndex) index;
IndexPlan p = plan.getIndexPlan();
buff.append(adv.getPlanDescription(p, rootState));
} else {
buff.append(index.getPlan(createFilter(true), rootState));
}
} else {
buff.append("no-index");
}
if (!selectorConstraints.isEmpty()) {
buff.append(" where ").append(new AndImpl(selectorConstraints).toString());
}
buff.append(" */");
return buff.toString();
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex in project jackrabbit-oak by apache.
the class SelectorImpl method execute.
@Override
public void execute(NodeState rootState) {
QueryIndex index = plan.getIndex();
if (index == null) {
cursor = Cursors.newPathCursor(new ArrayList<String>(), query.getSettings());
return;
}
IndexPlan p = plan.getIndexPlan();
if (p != null) {
p.setFilter(createFilter(false));
AdvancedQueryIndex adv = (AdvancedQueryIndex) index;
cursor = adv.query(p, rootState);
} else {
cursor = index.query(createFilter(false), rootState);
}
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex in project jackrabbit-oak by apache.
the class LuceneIndexTest method indexNodeLockHandling.
@Test
public void indexNodeLockHandling() throws Exception {
tracker = new IndexTracker();
// Create 2 indexes. /oak:index/lucene and /test/oak:index/lucene
// The way LuceneIndexLookup works is. It collect child first and then
// parent
NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
NodeBuilder nb = newLuceneIndexDefinitionV2(index, "lucene", of(TYPENAME_STRING));
nb.setProperty(LuceneIndexConstants.FULL_TEXT_ENABLED, false);
nb.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"), STRINGS));
index = builder.child("test").child(INDEX_DEFINITIONS_NAME);
NodeBuilder nb2 = newLuceneIndexDefinitionV2(index, "lucene", of(TYPENAME_STRING));
nb2.setProperty(LuceneIndexConstants.FULL_TEXT_ENABLED, false);
nb2.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo"), STRINGS));
NodeState before = builder.getNodeState();
builder.child("test").setProperty("foo", "fox is jumping");
NodeState after = builder.getNodeState();
NodeState indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY);
tracker.update(indexed);
QueryIndex.AdvancedQueryIndex queryIndex = new LucenePropertyIndex(tracker);
FilterImpl filter = createFilter(NT_BASE);
filter.restrictPath("/test", Filter.PathRestriction.EXACT);
filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
builder = indexed.builder();
NodeBuilder dir = builder.child("oak:index").child("lucene").child(":data");
// Mutate the blob to fail on access i.e. create corrupt index
List<Blob> blobs = new ArrayList<Blob>();
Blob b = dir.child("segments_1").getProperty(JCR_DATA).getValue(Type.BINARY, 0);
FailingBlob fb = new FailingBlob(IOUtils.toByteArray(b.getNewStream()));
blobs.add(fb);
dir.child("segments_1").setProperty(JCR_DATA, blobs, BINARIES);
indexed = builder.getNodeState();
tracker.update(indexed);
List<IndexPlan> list = queryIndex.getPlans(filter, null, indexed);
assertEquals("There must be only one plan", 1, list.size());
IndexPlan plan = list.get(0);
assertEquals("Didn't get the expected plan", "/test/oak:index/lucene", plan.getPlanName());
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex in project jackrabbit-oak by apache.
the class QueryImpl method getBestSelectorExecutionPlan.
private SelectorExecutionPlan getBestSelectorExecutionPlan(NodeState rootState, FilterImpl filter, QueryIndexProvider indexProvider, boolean traversalEnabled) {
QueryIndex bestIndex = null;
if (LOG.isDebugEnabled()) {
logDebug("cost using filter " + filter);
}
double bestCost = Double.POSITIVE_INFINITY;
IndexPlan bestPlan = null;
// Sort the indexes according to their minimum cost to be able to skip the remaining indexes if the cost of the
// current index is below the minimum cost of the next index.
List<? extends QueryIndex> queryIndexes = MINIMAL_COST_ORDERING.sortedCopy(indexProvider.getQueryIndexes(rootState));
List<OrderEntry> sortOrder = getSortOrder(filter);
for (int i = 0; i < queryIndexes.size(); i++) {
QueryIndex index = queryIndexes.get(i);
double minCost = index.getMinimumCost();
if (minCost > bestCost) {
// Stop looking if the minimum cost is higher than the current best cost
break;
}
double cost;
String indexName = index.getIndexName();
IndexPlan indexPlan = null;
if (index instanceof AdvancedQueryIndex) {
AdvancedQueryIndex advIndex = (AdvancedQueryIndex) index;
long maxEntryCount = limit;
if (offset > 0) {
if (offset + limit < 0) {
// long overflow
maxEntryCount = Long.MAX_VALUE;
} else {
maxEntryCount = offset + limit;
}
}
List<IndexPlan> ipList = advIndex.getPlans(filter, sortOrder, rootState);
cost = Double.POSITIVE_INFINITY;
for (IndexPlan p : ipList) {
long entryCount = p.getEstimatedEntryCount();
if (p.getSupportsPathRestriction()) {
entryCount = scaleEntryCount(rootState, filter, entryCount);
}
if (sortOrder == null || p.getSortOrder() != null) {
// if the query is unordered, or
// if the query contains "order by" and the index can sort on that,
// then we don't need to read all entries from the index
entryCount = Math.min(maxEntryCount, entryCount);
}
double c = p.getCostPerExecution() + entryCount * p.getCostPerEntry();
if (LOG.isDebugEnabled()) {
String plan = advIndex.getPlanDescription(p, rootState);
String msg = String.format("cost for [%s] of type (%s) with plan [%s] is %1.2f", p.getPlanName(), indexName, plan, c);
logDebug(msg);
}
if (c < cost) {
cost = c;
indexPlan = p;
}
}
if (indexPlan != null && indexPlan.getPlanName() != null) {
indexName += "[" + indexPlan.getPlanName() + "]";
}
} else {
cost = index.getCost(filter, rootState);
}
if (LOG.isDebugEnabled()) {
logDebug("cost for " + indexName + " is " + cost);
}
if (cost < 0) {
LOG.error("cost below 0 for " + indexName + " is " + cost);
}
if (cost < bestCost) {
bestCost = cost;
bestIndex = index;
bestPlan = indexPlan;
}
}
potentiallySlowTraversalQuery = bestIndex == null;
if (traversalEnabled) {
TraversingIndex traversal = new TraversingIndex();
double cost = traversal.getCost(filter, rootState);
if (LOG.isDebugEnabled()) {
logDebug("cost for " + traversal.getIndexName() + " is " + cost);
}
if (cost < bestCost || bestCost == Double.POSITIVE_INFINITY) {
bestCost = cost;
bestPlan = null;
bestIndex = traversal;
if (potentiallySlowTraversalQuery) {
potentiallySlowTraversalQuery = traversal.isPotentiallySlow(filter, rootState);
}
}
}
return new SelectorExecutionPlan(filter.getSelector(), bestIndex, bestPlan, bestCost);
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex in project jackrabbit-oak by apache.
the class SelectorImpl method getIndexCostInfo.
@Override
public String getIndexCostInfo(NodeState rootState) {
StringBuilder buff = new StringBuilder();
buff.append(quoteJson(selectorName)).append(": ");
QueryIndex index = getIndex();
if (index != null) {
if (index instanceof AdvancedQueryIndex) {
IndexPlan p = plan.getIndexPlan();
buff.append("{ perEntry: ").append(p.getCostPerEntry());
buff.append(", perExecution: ").append(p.getCostPerExecution());
buff.append(", count: ").append(p.getEstimatedEntryCount());
buff.append(" }");
} else {
buff.append(index.getCost(createFilter(true), rootState));
}
}
return buff.toString();
}
Aggregations