use of com.apple.foundationdb.record.query.plan.temp.AliasMap 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)));
}
}
use of com.apple.foundationdb.record.query.plan.temp.AliasMap in project fdb-record-layer by FoundationDB.
the class ComputingMatcher method enumerate.
/**
* Method to enumerate the permutations on this side against the permutation of the other side in order
* to form matches (bijective mappings between the permutations). The match function is called for each pair of
* elements (for a match attempt). If the match function returns a non-empty {@link Iterable} the pair is recorded
* as a matching pair. We attempt to find a matching pair (one from this side; one from the other side) for each
* element identified by {@link #getAliases()}. For each individual new such pair that is found,
* the method {@link MatchAccumulator#accumulate} is called. Once a set of bindings is established for all aliases
* in {@link #getAliases} this method then calls {@link MatchAccumulator#finish} to produce an iterable of type
* {@code R}.
* @param iterator an enumerating iterable for the permutations on this side
* @param otherPermutation one permutation (that is not violating dependencies, constraints, etc.) of the other side
* @return an {@link Iterator} of match results (of type {@code BoundMatch<R>})
*/
@SuppressWarnings("java:S135")
@Nonnull
public Iterator<BoundMatch<R>> enumerate(@Nonnull final EnumeratingIterator<CorrelationIdentifier> iterator, @Nonnull final List<CorrelationIdentifier> otherPermutation) {
final Set<CorrelationIdentifier> aliases = getAliases();
final AliasMap boundAliasesMap = getBoundAliasesMap();
if (otherPermutation.isEmpty()) {
return ImmutableList.of(BoundMatch.<R>withAliasMap(boundAliasesMap)).iterator();
}
final int size = otherPermutation.size();
return new AbstractIterator<BoundMatch<R>>() {
@Override
protected BoundMatch<R> computeNext() {
while (iterator.hasNext()) {
final List<CorrelationIdentifier> permutation = iterator.next();
final AliasMap.Builder aliasMapBuilder = AliasMap.builder(aliases.size());
final MatchAccumulator<M, R> accumulatedMatchResult = matchAccumulatorSupplier.get();
int i;
for (i = 0; i < size; i++) {
final AliasMap aliasMap = aliasMapBuilder.build();
final CorrelationIdentifier alias = permutation.get(i);
final CorrelationIdentifier otherAlias = otherPermutation.get(i);
final Optional<AliasMap> locallyBoundMapOptional = mapDependenciesToOther(aliasMap, alias, otherAlias);
if (!locallyBoundMapOptional.isPresent()) {
break;
}
final AliasMap locallyBoundMap = locallyBoundMapOptional.get();
final T entity = Objects.requireNonNull(getAliasToElementMap().get(alias));
final T otherEntity = Objects.requireNonNull(getOtherAliasToElementMap().get(otherAlias));
final Iterable<M> matchResults = matchFunction.apply(entity, otherEntity, boundAliasesMap.combine(locallyBoundMap));
if (Iterables.isEmpty(matchResults)) {
break;
}
accumulatedMatchResult.accumulate(matchResults);
// We now amend the equivalences passed in by adding the already known bound aliases left
// of i and make them equivalent as well
aliasMapBuilder.put(alias, otherAlias);
}
final R result = accumulatedMatchResult.finish();
if (i == size) {
iterator.skip(i - 1);
return BoundMatch.withAliasMapAndMatchResult(boundAliasesMap.combine(aliasMapBuilder.build()), result);
} else {
iterator.skip(i);
}
}
return endOfData();
}
};
}
Aggregations