use of com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan in project fdb-record-layer by FoundationDB.
the class RecordQueryPlanner method handleNonSargables.
@Nonnull
private ScoredPlan handleNonSargables(@Nonnull ScoredPlan bestPlan, @Nonnull List<ScoredPlan> intersectionCandidates, @Nonnull PlanContext planContext) {
if (planContext.commonPrimaryKey != null && !intersectionCandidates.isEmpty()) {
KeyExpression comparisonKey = planContext.commonPrimaryKey;
final KeyExpression sort = planContext.query.getSort();
comparisonKey = getKeyForMerge(sort, comparisonKey);
ScoredPlan intersectionPlan = planIntersection(intersectionCandidates, comparisonKey);
if (intersectionPlan != null) {
if (intersectionPlan.unsatisfiedFilters.isEmpty()) {
return intersectionPlan;
} else if (bestPlan.getNumNonSargables() > intersectionPlan.getNumNonSargables()) {
bestPlan = intersectionPlan;
}
}
}
if (bestPlan.getNumNonSargables() > 0) {
final RecordQueryPlan filtered = new RecordQueryFilterPlan(bestPlan.plan, planContext.rankComparisons.planComparisonSubstitutes(bestPlan.combineNonSargables()));
// TODO: further optimization requires knowing which filters are satisfied
return new ScoredPlan(filtered, Collections.emptyList(), Collections.emptyList(), bestPlan.score, bestPlan.createsDuplicates, bestPlan.includedRankComparisons);
} else {
return bestPlan;
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan in project fdb-record-layer by FoundationDB.
the class FieldWithComparisonCountProperty method evaluateAtExpression.
@Nonnull
@Override
public Integer evaluateAtExpression(@Nonnull RelationalExpression expression, @Nonnull List<Integer> childResults) {
int total = 0;
if (expression instanceof RecordQueryFilterPlan) {
QueryComponent filter = ((RecordQueryFilterPlan) expression).getConjunctedFilter();
total = getFieldWithComparisonCount(filter);
}
for (Integer childCount : childResults) {
if (childCount != null) {
total += childCount;
}
}
return total;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan in project fdb-record-layer by FoundationDB.
the class UnionVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull final RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryUnionPlanBase) {
RecordQueryUnionPlanBase unionPlan = (RecordQueryUnionPlanBase) recordQueryPlan;
final Set<KeyExpression> requiredFields = unionPlan.getRequiredFields();
boolean shouldPullOutFilter = false;
QueryComponent filter = null;
if (unionPlan.getChildren().stream().allMatch(child -> child instanceof RecordQueryFilterPlan)) {
filter = ((RecordQueryFilterPlan) unionPlan.getChildren().get(0)).getConjunctedFilter();
// needed for lambda expression
final QueryComponent finalFilter = filter;
shouldPullOutFilter = unionPlan.getChildren().stream().allMatch(plan -> ((RecordQueryFilterPlan) plan).getConjunctedFilter().equals(finalFilter));
}
List<ExpressionRef<RecordQueryPlan>> newChildren = new ArrayList<>(unionPlan.getChildren().size());
for (RecordQueryPlan plan : unionPlan.getChildren()) {
if (shouldPullOutFilter) {
// Check if the plan under the filter can have its index fetch removed.
if (!(plan instanceof RecordQueryFilterPlan)) {
throw new RecordCoreException("serious logic error: thought this was a filter plan but it wasn't");
}
plan = ((RecordQueryFilterPlan) plan).getChild();
}
@Nullable RecordQueryPlan newPlan = removeIndexFetch(plan, requiredFields);
if (newPlan == null) {
// can't remove index fetch, so give up
return recordQueryPlan;
}
newChildren.add(GroupExpressionRef.of(newPlan));
}
RecordQueryPlan newUnionPlan = new RecordQueryFetchFromPartialRecordPlan(unionPlan.withChildrenReferences(newChildren), TranslateValueFunction.unableToTranslate());
if (shouldPullOutFilter) {
return new RecordQueryFilterPlan(newUnionPlan, filter);
} else {
return newUnionPlan;
}
}
return recordQueryPlan;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan in project fdb-record-layer by FoundationDB.
the class FilterVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryFilterPlan) {
final RecordQueryFilterPlan filterPlan = (RecordQueryFilterPlan) recordQueryPlan;
final List<QueryComponent> filters = filterPlan.getFilters();
final AvailableFields availableFields = availableFields(((RecordQueryFilterPlan) recordQueryPlan).getInnerPlan());
// Partition the filters according to whether they can be evaluated using just the fields from the index or
// if they need a full record.
final List<QueryComponent> indexFilters = Lists.newArrayListWithCapacity(filters.size());
final List<QueryComponent> residualFilters = Lists.newArrayListWithCapacity(filters.size());
final Set<KeyExpression> allReferencedFields = new HashSet<>();
partitionFilters(filters, availableFields, indexFilters, residualFilters, allReferencedFields);
Verify.verify(indexFilters.size() + residualFilters.size() == filters.size());
if (indexFilters.isEmpty()) {
return recordQueryPlan;
}
@Nullable RecordQueryPlan removedFetchPlan = removeIndexFetch(filterPlan.getChild(), allReferencedFields);
if (removedFetchPlan == null) {
return recordQueryPlan;
}
recordQueryPlan = new RecordQueryFetchFromPartialRecordPlan(new RecordQueryFilterPlan(removedFetchPlan, indexFilters), TranslateValueFunction.unableToTranslate());
if (!residualFilters.isEmpty()) {
recordQueryPlan = new RecordQueryFilterPlan(recordQueryPlan, residualFilters);
}
}
return recordQueryPlan;
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan in project fdb-record-layer by FoundationDB.
the class QueryPlanCursorTest method filter.
@Test
public void filter() throws Exception {
final RecordQueryPlan plan = new RecordQueryFilterPlan(indexPlanEquals("MySimpleRecord$num_value_3_indexed", 2), Query.field("str_value_indexed").equalsValue("even"));
compareSkipsAndCursors(plan);
}
Aggregations