use of com.apple.foundationdb.record.query.expressions.AndComponent in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method normalizeAndOrForInAsOr.
private QueryComponent normalizeAndOrForInAsOr(@Nonnull QueryComponent component) {
if (!(component instanceof AndComponent)) {
return component;
}
final AndComponent and = (AndComponent) component;
OrComponent singleOrChild = null;
final List<QueryComponent> otherChildren = new ArrayList<>();
for (QueryComponent child : and.getChildren()) {
if (child instanceof OrComponent) {
if (singleOrChild == null) {
singleOrChild = (OrComponent) child;
} else {
return and;
}
} else if (Query.isSingleFieldComparison(child)) {
otherChildren.add(child);
} else {
return and;
}
}
if (singleOrChild == null) {
return and;
}
// We have exactly one OR child and the others are single field comparisons
return OrComponent.from(distributeAnd(otherChildren, singleOrChild.getChildren()));
}
use of com.apple.foundationdb.record.query.expressions.AndComponent in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method planIndex.
@Nullable
private ScoredPlan planIndex(@Nonnull PlanContext planContext, @Nonnull QueryComponent filter, @Nullable Index index, @Nonnull KeyExpression indexExpr, @Nonnull List<ScoredPlan> intersectionCandidates) {
final KeyExpression sort = planContext.query.getSort();
final boolean sortReverse = planContext.query.isSortReverse();
final CandidateScan candidateScan = new CandidateScan(planContext, index, sortReverse);
ScoredPlan p = null;
if (index != null) {
if (indexTypes.getRankTypes().contains(index.getType())) {
GroupingKeyExpression grouping = (GroupingKeyExpression) indexExpr;
p = planRank(candidateScan, index, grouping, filter);
// Plan as just value index.
indexExpr = grouping.getWholeKey();
} else if (indexTypes.getTextTypes().contains(index.getType())) {
p = planText(candidateScan, index, filter, sort);
if (p != null) {
p = planRemoveDuplicates(planContext, p);
}
if (p != null) {
p = computeIndexFilters(planContext, p);
}
return p;
} else if (indexTypes.getLuceneTypes().contains(index.getType())) {
p = planLucene(candidateScan, index, filter, sort);
if (p != null) {
p = planRemoveDuplicates(planContext, p);
}
if (p != null) {
p = computeIndexFilters(planContext, p);
}
return p;
} else if (!indexTypes.getValueTypes().contains(index.getType())) {
return null;
}
}
if (p == null) {
p = planCandidateScan(candidateScan, indexExpr, filter, sort);
}
if (p == null) {
// we can't match the filter, but maybe the sort
p = planSortOnly(candidateScan, indexExpr, sort);
if (p != null) {
final List<QueryComponent> unsatisfiedFilters = filter instanceof AndComponent ? ((AndComponent) filter).getChildren() : Collections.singletonList(filter);
p = new ScoredPlan(0, p.plan, unsatisfiedFilters, p.createsDuplicates);
}
}
if (p != null) {
if (getConfiguration().shouldOptimizeForIndexFilters()) {
// partition index filters
if (index == null) {
// if we scan without an index all filters become index filters as we don't need a fetch
// to evaluate these filters
p = p.withFilters(p.combineNonSargables(), Collections.emptyList());
} else {
p = computeIndexFilters(planContext, p);
}
}
}
if (p != null) {
p = planRemoveDuplicates(planContext, p);
if (p != null && p.getNumNonSargables() > 0) {
PlanOrderingKey planOrderingKey = PlanOrderingKey.forPlan(metaData, p.plan, planContext.commonPrimaryKey);
if (planOrderingKey != null && (sort != null || planOrderingKey.isPrimaryKeyOrdered())) {
// If there is a sort, all chosen plans should be ordered by it and so compatible.
// Otherwise, by requiring pkey order, we miss out on the possible intersection of
// X < 10 AND X < 5, which should have been handled already. We gain simplicity
// in not trying X < 10 AND Y = 5 AND Z = 'foo', where we would need to throw
// some out as we fail to align them all.
p.planOrderingKey = planOrderingKey;
intersectionCandidates.add(p);
}
}
}
return p;
}
use of com.apple.foundationdb.record.query.expressions.AndComponent in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method mergeRecordTypeAndComponent.
@Nonnull
protected static QueryComponent mergeRecordTypeAndComponent(@Nonnull String recordType, @Nullable QueryComponent component) {
if (component == null) {
return new RecordTypeKeyComparison(recordType);
}
List<QueryComponent> components = new ArrayList<>();
components.add(new RecordTypeKeyComparison(recordType));
if (component instanceof AndComponent) {
components.addAll(((AndComponent) component).getChildren());
} else {
components.add(component);
}
return Query.and(components);
}
use of com.apple.foundationdb.record.query.expressions.AndComponent in project fdb-record-layer by FoundationDB.
the class IndexAggregateFunctionCall method extractFieldPaths.
/**
* Helper method to extract a set of key expressions that are bound through some comparison in the
* query component passed in.
* @param queryComponent the query component
* @param predicate a predicate used for filtering each encountered {@link FieldWithComparison}
* @return a set of {@link KeyExpression}s where each element is a key expression of a field (i.e. a
* {@link com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression}) or a simple nesting field
* (i.e. a {@link com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression}) that is bound
* through some comparison
*/
@Nonnull
public static Set<KeyExpression> extractFieldPaths(@Nonnull QueryComponent queryComponent, @Nonnull final Predicate<FieldWithComparison> predicate) {
if (queryComponent instanceof BaseField) {
final BaseField baseField = (BaseField) queryComponent;
if (baseField instanceof NestedField) {
final NestedField nestedField = (NestedField) baseField;
final Set<KeyExpression> nestedExpressions = extractFieldPaths(nestedField.getChild(), predicate);
return nestedExpressions.stream().map(nestedExpression -> Key.Expressions.field(nestedField.getFieldName()).nest(nestedExpression)).collect(ImmutableSet.toImmutableSet());
}
if (baseField instanceof FieldWithComparison) {
final FieldWithComparison fieldWithComparison = (FieldWithComparison) baseField;
if (predicate.test(fieldWithComparison)) {
return ImmutableSet.of(Key.Expressions.field(fieldWithComparison.getFieldName()));
}
}
return ImmutableSet.of();
} else if (queryComponent instanceof AndComponent) {
final Set<KeyExpression> boundFields = Sets.newHashSet();
final AndComponent andComponent = (AndComponent) queryComponent;
andComponent.getChildren().forEach(child -> boundFields.addAll(extractEqualityBoundFields(child)));
return boundFields;
}
return ImmutableSet.of();
}
use of com.apple.foundationdb.record.query.expressions.AndComponent in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method planRank.
@Nullable
private ScoredPlan planRank(@Nonnull CandidateScan candidateScan, @Nonnull Index index, @Nonnull GroupingKeyExpression indexExpr, @Nonnull QueryComponent filter) {
if (filter instanceof QueryRecordFunctionWithComparison) {
final QueryRecordFunctionWithComparison filterComparison = (QueryRecordFunctionWithComparison) filter;
final RankComparisons.RankComparison rankComparison = candidateScan.planContext.rankComparisons.getPlanComparison(filterComparison);
if (rankComparison != null && rankComparison.getIndex() == index && RankComparisons.matchesSort(indexExpr, candidateScan.planContext.query.getSort())) {
final ScanComparisons scanComparisons = rankComparison.getScanComparisons();
final RecordQueryPlan scan = rankScan(candidateScan, filterComparison, scanComparisons);
final boolean createsDuplicates = RankComparisons.createsDuplicates(index, indexExpr);
return new ScoredPlan(scan, Collections.emptyList(), Collections.emptyList(), 1, createsDuplicates, Collections.singleton(rankComparison));
}
} else if (filter instanceof AndComponent) {
return planRankWithAnd(candidateScan, index, indexExpr, (AndComponent) filter);
}
return null;
}
Aggregations