use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.
the class QueryImpl method canSortByIndex.
private boolean canSortByIndex() {
boolean canSortByIndex = false;
// TODO add issue about order by optimization for multiple selectors
if (orderings != null && selectors.size() == 1) {
IndexPlan plan = selectors.get(0).getExecutionPlan().getIndexPlan();
if (plan != null) {
List<OrderEntry> list = plan.getSortOrder();
if (list != null && list.size() == orderings.length) {
canSortByIndex = true;
for (int i = 0; i < list.size(); i++) {
OrderEntry e = list.get(i);
OrderingImpl o = orderings[i];
DynamicOperandImpl op = o.getOperand();
if (!(op instanceof PropertyValueImpl)) {
// ordered by a function: currently not supported
canSortByIndex = false;
break;
}
// we only have one selector, so no need to check that
// TODO support joins
String pn = ((PropertyValueImpl) op).getPropertyName();
if (!pn.equals(e.getPropertyName())) {
// ordered by another property
canSortByIndex = false;
break;
}
if (o.isDescending() != (e.getOrder() == Order.DESCENDING)) {
// ordered ascending versus descending
canSortByIndex = false;
break;
}
}
}
}
}
return canSortByIndex;
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.
the class IndexPlannerTest method noApplicableRule.
@Test
public void noApplicableRule() throws Exception {
NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("foo"), "async");
defn.setProperty(createProperty(IndexConstants.DECLARING_NODE_TYPES, of("nt:folder"), STRINGS));
IndexNode node = createIndexNode(new IndexDefinition(root, defn.getNodeState(), "/foo"));
FilterImpl filter = createFilter("nt:base");
filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
IndexPlanner planner = new IndexPlanner(node, "/foo", filter, Collections.<OrderEntry>emptyList());
assertNull(planner.getPlan());
filter = createFilter("nt:folder");
filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
planner = new IndexPlanner(node, "/foo", filter, Collections.<OrderEntry>emptyList());
assertNotNull(planner.getPlan());
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.
the class IndexPlannerTest method planForSortField.
@Test
public void planForSortField() throws Exception {
NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("foo"), "async");
defn.setProperty(createProperty(ORDERED_PROP_NAMES, of("foo"), STRINGS));
IndexNode node = createIndexNode(new IndexDefinition(root, defn.getNodeState(), "/foo"));
IndexPlanner planner = new IndexPlanner(node, "/foo", createFilter("nt:base"), ImmutableList.of(new OrderEntry("foo", Type.LONG, OrderEntry.Order.ASCENDING)));
assertNotNull(planner.getPlan());
assertTrue(pr(planner.getPlan()).isUniquePathsRequired());
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.
the class IndexPlanner method getPlanBuilder.
private IndexPlan.Builder getPlanBuilder() {
log.trace("Evaluating plan with index definition {}", definition);
if (wrongIndex()) {
return null;
}
FullTextExpression ft = filter.getFullTextConstraint();
if (!definition.getVersion().isAtLeast(IndexFormatVersion.V2)) {
log.trace("Index is old format. Not supported");
return null;
}
// Query Fulltext and Index does not support fulltext
if (ft != null && !definition.isFullTextEnabled()) {
return null;
}
IndexingRule indexingRule = getApplicableRule();
if (indexingRule == null) {
return null;
}
// Query Fulltext and indexing rule does not support fulltext
if (ft != null && !indexingRule.isFulltextEnabled()) {
return null;
}
if (!checkForQueryPaths()) {
log.trace("Opting out due mismatch between path restriction {} and query paths {}", filter.getPath(), definition.getQueryPaths());
return null;
}
result = new PlanResult(indexPath, definition, indexingRule);
if (definition.hasFunctionDefined() && filter.getPropertyRestriction(definition.getFunctionName()) != null) {
return getNativeFunctionPlanBuilder(indexingRule.getBaseNodeType());
}
List<String> indexedProps = newArrayListWithCapacity(filter.getPropertyRestrictions().size());
for (PropertyDefinition functionIndex : indexingRule.getFunctionRestrictions()) {
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
String f = functionIndex.function;
if (pr.propertyName.equals(f)) {
indexedProps.add(f);
result.propDefns.put(f, functionIndex);
}
}
}
// Optimization - Go further only if any of the property is configured
// for property index
List<String> facetFields = new LinkedList<String>();
boolean ntBaseRule = NT_BASE.equals(indexingRule.getNodeTypeName());
Map<String, PropertyDefinition> relativePropDefns = new HashMap<>();
if (indexingRule.propertyIndexEnabled) {
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
String name = pr.propertyName;
if (QueryConstants.RESTRICTION_LOCAL_NAME.equals(name)) {
continue;
}
if (name.startsWith(QueryConstants.FUNCTION_RESTRICTION_PREFIX)) {
// function-based indexes were handled before
continue;
}
if (QueryConstants.REP_FACET.equals(pr.propertyName)) {
String value = pr.first.getValue(Type.STRING);
facetFields.add(FacetHelper.parseFacetField(value));
}
PropertyDefinition pd = indexingRule.getConfig(pr.propertyName);
boolean relativeProps = false;
if (pd == null && ntBaseRule) {
// Direct match not possible. Check for relative property definition
// i.e. if no match found for jcr:content/@keyword then check if
// property definition exists for 'keyword'
pd = getSimpleProperty(indexingRule, pr.propertyName);
relativeProps = pd != null;
}
if (pd != null && pd.propertyIndexEnabled()) {
if (pr.isNullRestriction() && !pd.nullCheckEnabled) {
continue;
}
if (!matchesValuePattern(pr, pd)) {
continue;
}
// with some other definitions
if (pd.weight != 0 && !relativeProps) {
indexedProps.add(name);
}
if (relativeProps) {
relativePropDefns.put(name, pd);
} else {
result.propDefns.put(name, pd);
}
}
}
}
boolean evalNodeTypeRestrictions = canEvalNodeTypeRestrictions(indexingRule);
boolean evalPathRestrictions = canEvalPathRestrictions(indexingRule);
boolean canEvalAlFullText = canEvalAllFullText(indexingRule, ft);
boolean canEvalNodeNameRestriction = canEvalNodeNameRestriction(indexingRule);
if (ft != null && !canEvalAlFullText) {
return null;
}
if (indexedProps.isEmpty() && !relativePropDefns.isEmpty() && !canEvalAlFullText) {
indexedProps = planForRelativeProperties(relativePropDefns);
}
// Fulltext expression can also be like jcr:contains(jcr:content/metadata/@format, 'image')
List<OrderEntry> sortOrder = createSortOrder(indexingRule);
boolean canSort = canSortByProperty(sortOrder);
if (!indexedProps.isEmpty() || canSort || ft != null || evalPathRestrictions || evalNodeTypeRestrictions || canEvalNodeNameRestriction) {
int costPerEntryFactor = 1;
costPerEntryFactor += sortOrder.size();
IndexPlan.Builder plan = defaultPlan();
if (!sortOrder.isEmpty()) {
plan.setSortOrder(sortOrder);
}
if (facetFields.size() > 0) {
plan.setAttribute(FacetHelper.ATTR_FACET_FIELDS, facetFields);
}
if (ft == null) {
result.enableNonFullTextConstraints();
}
if (evalNodeTypeRestrictions) {
result.enableNodeTypeEvaluation();
}
if (canEvalNodeNameRestriction) {
result.enableNodeNameRestriction();
}
// Set a index based guess here. Unique would set its own value below
if (useActualEntryCount && !definition.isEntryCountDefined()) {
int maxPossibleNumDocs = getMaxPossibleNumDocs(result.propDefns, filter);
if (maxPossibleNumDocs >= 0) {
plan.setEstimatedEntryCount(maxPossibleNumDocs);
}
}
if (sortOrder.isEmpty() && ft == null) {
boolean uniqueIndexFound = planForSyncIndexes(indexingRule);
if (uniqueIndexFound) {
// For unique index there would be at max 1 entry
plan.setEstimatedEntryCount(1);
}
}
return plan.setCostPerEntry(definition.getCostPerEntry() / costPerEntryFactor);
}
return null;
}
use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.
the class IndexPlannerTest method syncIndex_NotUsedWithSort.
@Test
public void syncIndex_NotUsedWithSort() throws Exception {
IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
defnb.indexRule("nt:base").property("foo").propertyIndex().sync();
defnb.indexRule("nt:base").property("bar").propertyIndex().ordered();
IndexDefinition defn = new IndexDefinition(root, defnb.build(), "/foo");
IndexNode node = createIndexNode(defn, 100);
FilterImpl filter = createFilter("nt:base");
filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
IndexPlanner planner = new IndexPlanner(node, "/foo", filter, ImmutableList.of(new OrderEntry("bar", Type.LONG, OrderEntry.Order.ASCENDING)));
QueryIndex.IndexPlan plan = planner.getPlan();
assertNotNull(plan);
assertEquals(documentsPerValue(100), plan.getEstimatedEntryCount());
PropertyIndexResult hr = pr(plan).getPropertyIndexResult();
assertNull(hr);
}
Aggregations