Search in sources :

Example 1 with Compensation

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));
}
Also used : ValuePredicate(com.apple.foundationdb.record.query.predicates.ValuePredicate) RelationalExpressionWithPredicates(com.apple.foundationdb.record.query.plan.temp.RelationalExpressionWithPredicates) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) ValueComparisonRangePredicate(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate) Function(java.util.function.Function) PredicateMap(com.apple.foundationdb.record.query.plan.temp.PredicateMap) Multimaps(com.google.common.collect.Multimaps) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) HashMultimap(com.google.common.collect.HashMultimap) ImmutableList(com.google.common.collect.ImmutableList) ComparisonRange(com.apple.foundationdb.record.query.plan.temp.ComparisonRange) IterableHelpers(com.apple.foundationdb.record.query.plan.temp.IterableHelpers) Map(java.util.Map) Compensation(com.apple.foundationdb.record.query.plan.temp.Compensation) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) Placeholder(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate.Placeholder) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) Nonnull(javax.annotation.Nonnull) PredicateMapping(com.apple.foundationdb.record.query.plan.temp.PredicateMultiMap.PredicateMapping) Verify(com.google.common.base.Verify) ImmutableSet(com.google.common.collect.ImmutableSet) Equivalence(com.google.common.base.Equivalence) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Set(java.util.Set) InternalPlannerGraphRewritable(com.apple.foundationdb.record.query.plan.temp.explain.InternalPlannerGraphRewritable) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) EnumeratingIterable(com.apple.foundationdb.record.query.combinatorics.EnumeratingIterable) Streams(com.google.common.collect.Streams) AndPredicate(com.apple.foundationdb.record.query.predicates.AndPredicate) Maps(com.google.common.collect.Maps) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Objects(java.util.Objects) Value(com.apple.foundationdb.record.query.predicates.Value) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) Stream(java.util.stream.Stream) Sargable(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate.Sargable) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) CrossProduct(com.apple.foundationdb.record.query.combinatorics.CrossProduct) MatchInfo(com.apple.foundationdb.record.query.plan.temp.MatchInfo) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) PlannerGraph(com.apple.foundationdb.record.query.plan.temp.explain.PlannerGraph) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) MatchInfo(com.apple.foundationdb.record.query.plan.temp.MatchInfo) Compensation(com.apple.foundationdb.record.query.plan.temp.Compensation) PredicateMap(com.apple.foundationdb.record.query.plan.temp.PredicateMap) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) PredicateMapping(com.apple.foundationdb.record.query.plan.temp.PredicateMultiMap.PredicateMapping)

Example 2 with Compensation

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();
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) OrderingAttribute(com.apple.foundationdb.record.query.plan.temp.OrderingAttribute) CascadesPlanner(com.apple.foundationdb.record.query.plan.temp.CascadesPlanner) LinkedIdentitySet(com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) ComparisonRange(com.apple.foundationdb.record.query.plan.temp.ComparisonRange) Map(java.util.Map) IndexScanExpression(com.apple.foundationdb.record.query.plan.temp.expressions.IndexScanExpression) MatchCandidate(com.apple.foundationdb.record.query.plan.temp.MatchCandidate) PrimaryScanExpression(com.apple.foundationdb.record.query.plan.temp.expressions.PrimaryScanExpression) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) MatchPartition(com.apple.foundationdb.record.query.plan.temp.MatchPartition) Set(java.util.Set) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) ReferencedFieldsAttribute(com.apple.foundationdb.record.query.plan.temp.ReferencedFieldsAttribute) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) BoundKeyPart(com.apple.foundationdb.record.query.plan.temp.BoundKeyPart) List(java.util.List) Stream(java.util.stream.Stream) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) MatchInfo(com.apple.foundationdb.record.query.plan.temp.MatchInfo) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) IntStream(java.util.stream.IntStream) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) Function(java.util.function.Function) Key(com.apple.foundationdb.record.metadata.Key) LinkedHashMap(java.util.LinkedHashMap) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) Compensation(com.apple.foundationdb.record.query.plan.temp.Compensation) StreamSupport(java.util.stream.StreamSupport) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ChooseK(com.apple.foundationdb.record.query.combinatorics.ChooseK) LogicalIntersectionExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalIntersectionExpression) Iterator(java.util.Iterator) LogicalDistinctExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalDistinctExpression) PartialOrder(com.apple.foundationdb.record.query.combinatorics.PartialOrder) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) Maps(com.google.common.collect.Maps) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) PrimaryScanMatchCandidate(com.apple.foundationdb.record.query.plan.temp.PrimaryScanMatchCandidate) Comparator(java.util.Comparator) ValueIndexScanMatchCandidate(com.apple.foundationdb.record.query.plan.temp.ValueIndexScanMatchCandidate) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Compensation(com.apple.foundationdb.record.query.plan.temp.Compensation) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) BoundKeyPart(com.apple.foundationdb.record.query.plan.temp.BoundKeyPart) Nonnull(javax.annotation.Nonnull)

Aggregations

API (com.apple.foundationdb.annotation.API)2 ComparisonRange (com.apple.foundationdb.record.query.plan.temp.ComparisonRange)2 Compensation (com.apple.foundationdb.record.query.plan.temp.Compensation)2 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)2 MatchInfo (com.apple.foundationdb.record.query.plan.temp.MatchInfo)2 PartialMatch (com.apple.foundationdb.record.query.plan.temp.PartialMatch)2 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)2 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)2 QueryPredicate (com.apple.foundationdb.record.query.predicates.QueryPredicate)2 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)1 Key (com.apple.foundationdb.record.metadata.Key)1 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)1 ChooseK (com.apple.foundationdb.record.query.combinatorics.ChooseK)1 CrossProduct (com.apple.foundationdb.record.query.combinatorics.CrossProduct)1 EnumeratingIterable (com.apple.foundationdb.record.query.combinatorics.EnumeratingIterable)1 PartialOrder (com.apple.foundationdb.record.query.combinatorics.PartialOrder)1 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)1