use of com.apple.foundationdb.record.query.plan.temp.Compensation in project fdb-record-layer by FoundationDB.
the class SelectExpression method compensate.
@Override
@SuppressWarnings({ "java:S135", "java:S1066" })
public Compensation compensate(@Nonnull final PartialMatch partialMatch, @Nonnull final Map<CorrelationIdentifier, ComparisonRange> boundParameterPrefixMap) {
final Map<QueryPredicate, QueryPredicate> toBeReappliedPredicatesMap = Maps.newIdentityHashMap();
final MatchInfo matchInfo = partialMatch.getMatchInfo();
final PredicateMap predicateMap = matchInfo.getPredicateMap();
//
// The partial match we are called with here has child matches that have compensations on their own.
// Given a pair of these matches that we reach along two for each quantifiers (forming a join) we have to
// apply both compensations. The compensation class has a union method to combine two compensations in an
// optimal way. We need to fold over all those compensations to form one child compensation. The tree that
// is formed by partial matches therefore collapses into a chain of compensations.
//
final List<? extends Quantifier> quantifiers = getQuantifiers();
final Compensation childCompensation = quantifiers.stream().filter(quantifier -> quantifier instanceof Quantifier.ForEach).flatMap(quantifier -> matchInfo.getChildPartialMatch(quantifier).map(childPartialMatch -> childPartialMatch.compensate(boundParameterPrefixMap)).map(Stream::of).orElse(Stream.empty())).reduce(Compensation.noCompensation(), Compensation::union);
//
// The fact that we matched the partial match handed in must mean that the child compensation is not impossible.
//
Verify.verify(!childCompensation.isImpossible());
//
for (final QueryPredicate predicate : getPredicates()) {
final Optional<PredicateMapping> predicateMappingOptional = predicateMap.getMappingOptional(predicate);
Verify.verify(predicateMappingOptional.isPresent());
final PredicateMapping predicateMapping = predicateMappingOptional.get();
final Optional<QueryPredicate> reappliedPredicateOptional = predicateMapping.reapplyPredicateFunction().reapplyPredicateMaybe(matchInfo, boundParameterPrefixMap);
reappliedPredicateOptional.ifPresent(reappliedPredicate -> toBeReappliedPredicatesMap.put(predicate, reappliedPredicate));
}
return Compensation.ofChildCompensationAndPredicateMap(childCompensation, toBeReappliedPredicatesMap, computeMappedQuantifiers(partialMatch), computeUnmatchedForEachQuantifiers(partialMatch));
}
use of com.apple.foundationdb.record.query.plan.temp.Compensation in project fdb-record-layer by FoundationDB.
the class AbstractDataAccessRule method createIntersectionAndCompensation.
/**
* Private helper method to plan an intersection and subsequently compensate it using the partial match structures
* kept for all participating data accesses.
* Planning the data access and its compensation for a given match is a two-step approach as we compute
* the compensation for intersections by intersecting the {@link Compensation} for the single data accesses first
* before using the resulting {@link Compensation} to compute the compensating expression for the entire
* intersection.
* @param commonPrimaryKeyParts normalized common primary key
* @param matchToExpressionMap a map from match to single data access expression
* @param partition a partition (i.e. a list of {@link PartialMatch}es that the caller would like to compute
* and intersected data access for
* @param requestedOrderings a set of ordering that have been requested by consuming expressions/plan operators
* @return a optional containing a new {@link RelationalExpression} that represents the data access and its
* compensation, {@code Optional.empty()} if this method was unable to compute the intersection expression
*/
@Nonnull
private static List<RelationalExpression> createIntersectionAndCompensation(@Nonnull final List<KeyExpression> commonPrimaryKeyParts, @Nonnull final Map<PartialMatch, RelationalExpression> matchToExpressionMap, @Nonnull final List<PartialMatch> partition, @Nonnull final Set<RequestedOrdering> requestedOrderings) {
final var expressionsBuilder = ImmutableList.<RelationalExpression>builder();
final var orderingPartialOrder = intersectionOrdering(partition);
final ImmutableSet<BoundKeyPart> equalityBoundKeyParts = partition.stream().map(partialMatch -> partialMatch.getMatchInfo().getBoundKeyParts()).flatMap(boundOrderingKeyParts -> boundOrderingKeyParts.stream().filter(boundOrderingKey -> boundOrderingKey.getComparisonRangeType() == ComparisonRange.Type.EQUALITY)).collect(ImmutableSet.toImmutableSet());
for (final var requestedOrdering : requestedOrderings) {
final var satisfyingOrderingPartsOptional = Ordering.satisfiesKeyPartsOrdering(orderingPartialOrder, requestedOrdering.getOrderingKeyParts(), BoundKeyPart::getKeyPart);
final var comparisonKeyOptional = satisfyingOrderingPartsOptional.map(parts -> parts.stream().filter(part -> !equalityBoundKeyParts.contains(part)).collect(ImmutableList.toImmutableList())).flatMap(parts -> comparisonKey(commonPrimaryKeyParts, equalityBoundKeyParts, parts));
if (comparisonKeyOptional.isEmpty()) {
continue;
}
final KeyExpression comparisonKey = comparisonKeyOptional.get();
final var compensation = partition.stream().map(partialMatch -> partialMatch.compensate(partialMatch.getBoundParameterPrefixMap())).reduce(Compensation.impossibleCompensation(), Compensation::intersect);
final ImmutableList<RelationalExpression> scans = partition.stream().map(partialMatch -> Objects.requireNonNull(matchToExpressionMap.get(partialMatch))).collect(ImmutableList.toImmutableList());
final var logicalIntersectionExpression = LogicalIntersectionExpression.from(scans, comparisonKey);
final var compensatedIntersection = compensation.isNeeded() ? compensation.apply(GroupExpressionRef.of(logicalIntersectionExpression)) : logicalIntersectionExpression;
expressionsBuilder.add(compensatedIntersection);
}
return expressionsBuilder.build();
}
Aggregations