use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan in project fdb-record-layer by FoundationDB.
the class OrderingProperty method deriveForPredicatesFilterFromOrderings.
public static Optional<Ordering> deriveForPredicatesFilterFromOrderings(@Nonnull final List<Optional<Ordering>> orderingOptionals, @Nonnull final RecordQueryPredicatesFilterPlan predicatesFilterPlan) {
final Optional<Ordering> childOrderingOptional = Iterables.getOnlyElement(orderingOptionals);
if (childOrderingOptional.isPresent()) {
final Ordering childOrdering = childOrderingOptional.get();
final SetMultimap<KeyExpression, Comparisons.Comparison> equalityBoundFileKeyExpressions = predicatesFilterPlan.getPredicates().stream().flatMap(queryPredicate -> {
if (!(queryPredicate instanceof ValuePredicate)) {
return Stream.empty();
}
final ValuePredicate valuePredicate = (ValuePredicate) queryPredicate;
if (!valuePredicate.getComparison().getType().isEquality()) {
return Stream.empty();
}
if (!(valuePredicate.getValue() instanceof FieldValue)) {
return Stream.of();
}
return Stream.of(Pair.of((FieldValue) valuePredicate.getValue(), valuePredicate.getComparison()));
}).map(valueComparisonPair -> {
final FieldValue fieldValue = valueComparisonPair.getLeft();
final String fieldName = fieldValue.getFieldName();
KeyExpression keyExpression = Key.Expressions.field(fieldName);
final List<String> fieldPrefix = fieldValue.getFieldPrefix();
for (int i = fieldPrefix.size() - 1; i >= 0; i--) {
keyExpression = Key.Expressions.field(fieldPrefix.get(i)).nest(keyExpression);
}
return Pair.of(keyExpression, valueComparisonPair.getRight());
}).collect(ImmutableSetMultimap.toImmutableSetMultimap(Pair::getLeft, Pair::getRight));
final ImmutableList<KeyPart> resultOrderingKeyParts = childOrdering.getOrderingKeyParts().stream().filter(keyPart -> !equalityBoundFileKeyExpressions.containsKey(keyPart.getNormalizedKeyExpression())).collect(ImmutableList.toImmutableList());
final SetMultimap<KeyExpression, Comparisons.Comparison> resultEqualityBoundKeyMap = HashMultimap.create(childOrdering.getEqualityBoundKeyMap());
equalityBoundFileKeyExpressions.forEach(resultEqualityBoundKeyMap::put);
return Optional.of(new Ordering(resultEqualityBoundKeyMap, resultOrderingKeyParts, childOrdering.isDistinct()));
} else {
return Optional.empty();
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan in project fdb-record-layer by FoundationDB.
the class PushDistinctBelowFilterRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final ExpressionRef<? extends RelationalExpression> inner = call.get(innerRefMatcher);
final Quantifier.Physical qun = call.get(innerQuantifierMatcher);
final RecordQueryPredicatesFilterPlan filterPlan = call.get(filterPlanMatcher);
final RecordQueryUnorderedPrimaryKeyDistinctPlan newDistinctPlan = new RecordQueryUnorderedPrimaryKeyDistinctPlan(Quantifier.physical(inner));
final Quantifier.Physical newQun = Quantifier.physical(call.ref(newDistinctPlan));
final List<QueryPredicate> rebasedPredicates = filterPlan.getPredicates().stream().map(queryPredicate -> queryPredicate.rebase(Quantifiers.translate(qun, newQun))).collect(ImmutableList.toImmutableList());
call.yield(call.ref(new RecordQueryPredicatesFilterPlan(newQun, rebasedPredicates)));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan in project fdb-record-layer by FoundationDB.
the class ImplementFilterRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final Collection<? extends RecordQueryPlan> innerPlans = bindings.get(innerPlansMatcher);
final Quantifier.ForEach innerQuantifier = bindings.get(innerQuantifierMatcher);
final List<? extends QueryPredicate> queryPredicates = bindings.getAll(filterMatcher);
final GroupExpressionRef<? extends RecordQueryPlan> referenceOverPlans = GroupExpressionRef.from(innerPlans);
if (queryPredicates.stream().allMatch(QueryPredicate::isTautology)) {
call.yield(referenceOverPlans);
} else {
call.yield(GroupExpressionRef.of(new RecordQueryPredicatesFilterPlan(Quantifier.physicalBuilder().morphFrom(innerQuantifier).build(referenceOverPlans), queryPredicates)));
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan in project fdb-record-layer by FoundationDB.
the class PushTypeFilterBelowFilterRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final ExpressionRef<? extends RelationalExpression> inner = bindings.get(innerMatcher);
final Quantifier.Physical qun = bindings.get(qunMatcher);
final List<? extends QueryPredicate> predicates = bindings.getAll(predMatcher);
final Collection<String> recordTypes = bindings.get(root).getRecordTypes();
final RecordQueryTypeFilterPlan newTypeFilterPlan = new RecordQueryTypeFilterPlan(Quantifier.physical(inner), recordTypes);
final Quantifier.Physical newQun = Quantifier.physical(call.ref(newTypeFilterPlan));
final List<QueryPredicate> rebasedPredicates = predicates.stream().map(queryPredicate -> queryPredicate.rebase(Quantifiers.translate(qun, newQun))).collect(ImmutableList.toImmutableList());
call.yield(GroupExpressionRef.of(new RecordQueryPredicatesFilterPlan(newQun, rebasedPredicates)));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan in project fdb-record-layer by FoundationDB.
the class PushFilterThroughFetchRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final RecordQueryPredicatesFilterPlan filterPlan = bindings.get(root);
final RecordQueryFetchFromPartialRecordPlan fetchPlan = bindings.get(fetchPlanMatcher);
final Quantifier.Physical quantifierOverFetch = bindings.get(quantifierOverFetchMatcher);
final RecordQueryPlan innerPlan = bindings.get(innerPlanMatcher);
final List<? extends QueryPredicate> queryPredicates = filterPlan.getPredicates();
final ImmutableList.Builder<QueryPredicate> pushedPredicatesBuilder = ImmutableList.builder();
final ImmutableList.Builder<QueryPredicate> residualPredicatesBuilder = ImmutableList.builder();
final CorrelationIdentifier newInnerAlias = CorrelationIdentifier.uniqueID();
for (final QueryPredicate queryPredicate : queryPredicates) {
final Optional<QueryPredicate> pushedPredicateOptional = queryPredicate.replaceLeavesMaybe(leafPredicate -> pushLeafPredicate(fetchPlan, newInnerAlias, leafPredicate));
if (pushedPredicateOptional.isPresent()) {
pushedPredicatesBuilder.add(pushedPredicateOptional.get());
} else {
residualPredicatesBuilder.add(queryPredicate);
}
}
final ImmutableList<QueryPredicate> pushedPredicates = pushedPredicatesBuilder.build();
final ImmutableList<QueryPredicate> residualPredicates = residualPredicatesBuilder.build();
Verify.verify(pushedPredicates.size() + residualPredicates.size() == queryPredicates.size());
// case 1
if (pushedPredicates.isEmpty()) {
return;
}
// for case 2 and case 3 we can at least build a FILTER(inner, pushedPredicates) as that is
// required both for case 2 nd 3
final Quantifier.Physical newInnerQuantifier = Quantifier.physical(GroupExpressionRef.of(innerPlan), newInnerAlias);
final RecordQueryPredicatesFilterPlan pushedFilterPlan = new RecordQueryPredicatesFilterPlan(newInnerQuantifier, pushedPredicates);
final RecordQueryFetchFromPartialRecordPlan newFetchPlan = new RecordQueryFetchFromPartialRecordPlan(pushedFilterPlan, fetchPlan.getPushValueFunction());
if (residualPredicates.isEmpty()) {
// case 2
call.yield(call.ref(newFetchPlan));
} else {
// case 3
// create yet another physical quantifier on top of the fetch
final Quantifier.Physical newQuantifierOverFetch = Quantifier.physical(GroupExpressionRef.of(newFetchPlan));
final AliasMap translationMap = AliasMap.of(quantifierOverFetch.getAlias(), newQuantifierOverFetch.getAlias());
// rebase all residual predicates to use that quantifier's alias
final ImmutableList<QueryPredicate> rebasedResidualPredicates = residualPredicates.stream().map(residualPredicate -> residualPredicate.rebase(translationMap)).collect(ImmutableList.toImmutableList());
call.yield(GroupExpressionRef.of(new RecordQueryPredicatesFilterPlan(newQuantifierOverFetch, rebasedResidualPredicates)));
}
}
Aggregations