Search in sources :

Example 26 with CorrelationIdentifier

use of com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier in project fdb-record-layer by FoundationDB.

the class RelationalExpressionWithChildren method getCorrelatedTo.

@Nonnull
@Override
@SuppressWarnings("squid:S2201")
default Set<CorrelationIdentifier> getCorrelatedTo() {
    final ImmutableSet.Builder<CorrelationIdentifier> builder = ImmutableSet.builder();
    final List<? extends Quantifier> quantifiers = getQuantifiers();
    final Map<CorrelationIdentifier, ? extends Quantifier> aliasToQuantifierMap = quantifiers.stream().collect(Collectors.toMap(Quantifier::getAlias, Function.identity()));
    // We should check if the graph is sound here, if it is not we should throw an exception. This method
    // will properly return with an empty. There are other algorithms that may not be as defensive and we
    // must protect ourselves from illegal graphs (and bugs).
    final Optional<List<CorrelationIdentifier>> orderedOptional = TopologicalSort.anyTopologicalOrderPermutation(quantifiers.stream().map(Quantifier::getAlias).collect(Collectors.toSet()), alias -> Objects.requireNonNull(aliasToQuantifierMap.get(alias)).getCorrelatedTo());
    orderedOptional.orElseThrow(() -> new IllegalArgumentException("correlations are cyclic"));
    getCorrelatedToWithoutChildren().stream().filter(correlationIdentifier -> !aliasToQuantifierMap.containsKey(correlationIdentifier)).forEach(builder::add);
    for (final Quantifier quantifier : quantifiers) {
        quantifier.getCorrelatedTo().stream().filter(correlationIdentifier -> !canCorrelate() || !aliasToQuantifierMap.containsKey(correlationIdentifier)).forEach(builder::add);
    }
    return builder.build();
}
Also used : LinkedIdentitySet(com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet) ImmutableSet(com.google.common.collect.ImmutableSet) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Set(java.util.Set) Function(java.util.function.Function) Collectors(java.util.stream.Collectors) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Objects(java.util.Objects) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) List(java.util.List) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) Map(java.util.Map) MatchInfo(com.apple.foundationdb.record.query.plan.temp.MatchInfo) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) Nonnull(javax.annotation.Nonnull) TopologicalSort(com.apple.foundationdb.record.query.combinatorics.TopologicalSort) ImmutableSet(com.google.common.collect.ImmutableSet) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) List(java.util.List) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Nonnull(javax.annotation.Nonnull)

Example 27 with CorrelationIdentifier

use of com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier in project fdb-record-layer by FoundationDB.

the class MergeProjectionAndFetchRule method onMatch.

@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final LogicalProjectionExpression projectionExpression = call.get(root);
    // if the fetch is able to push all values we can eliminate the fetch as well
    final RecordQueryFetchFromPartialRecordPlan fetchPlan = call.get(innerPlanMatcher);
    final CorrelationIdentifier newInnerAlias = CorrelationIdentifier.uniqueID();
    final List<? extends Value> resultValues = projectionExpression.getResultValues();
    final boolean allPushable = resultValues.stream().allMatch(value -> fetchPlan.pushValue(value, newInnerAlias).isPresent());
    if (allPushable) {
        // all fields in the projection are already available underneath the fetch
        // we don't need the projection nor the fetch
        call.yield(call.ref(fetchPlan.getChild()));
    }
}
Also used : RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) LogicalProjectionExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalProjectionExpression)

Example 28 with CorrelationIdentifier

use of com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier in project fdb-record-layer by FoundationDB.

the class PushDistinctThroughFetchRule method onMatch.

@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final PlannerBindings bindings = call.getBindings();
    final RecordQueryFetchFromPartialRecordPlan fetchPlan = bindings.get(fetchPlanMatcher);
    final RecordQueryPlan innerPlan = bindings.get(innerPlanMatcher);
    final CorrelationIdentifier newInnerAlias = CorrelationIdentifier.uniqueID();
    final Quantifier.Physical newInnerQuantifier = Quantifier.physical(GroupExpressionRef.of(innerPlan), newInnerAlias);
    final RecordQueryUnorderedPrimaryKeyDistinctPlan pushedDistinctPlan = new RecordQueryUnorderedPrimaryKeyDistinctPlan(newInnerQuantifier);
    final RecordQueryFetchFromPartialRecordPlan newFetchPlan = new RecordQueryFetchFromPartialRecordPlan(pushedDistinctPlan, fetchPlan.getPushValueFunction());
    // case 2
    call.yield(call.ref(newFetchPlan));
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) RecordQueryUnorderedPrimaryKeyDistinctPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedPrimaryKeyDistinctPlan)

Example 29 with CorrelationIdentifier

use of com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier 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)));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TranslateValueFunction(com.apple.foundationdb.record.query.plan.plans.TranslateValueFunction) PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) RecordQueryPlanMatchers.anyPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.anyPlan) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordQueryPlanMatchers.predicatesFilter(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilter) ImmutableList(com.google.common.collect.ImmutableList) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) Verify(com.google.common.base.Verify) QuantifierMatchers.physicalQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.physicalQuantifier) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) RecordQueryPredicatesFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan) QueryComponentPredicate(com.apple.foundationdb.record.query.predicates.QueryComponentPredicate) Value(com.apple.foundationdb.record.query.predicates.Value) List(java.util.List) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) RecordQueryPlanMatchers(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) ImmutableList(com.google.common.collect.ImmutableList) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) RecordQueryPredicatesFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) QuantifierMatchers.physicalQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.physicalQuantifier)

Example 30 with CorrelationIdentifier

use of com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier in project fdb-record-layer by FoundationDB.

the class OrderingProperty method deriveForInJoinFromOrderings.

@SuppressWarnings("java:S135")
public static Optional<Ordering> deriveForInJoinFromOrderings(@Nonnull final List<Optional<Ordering>> orderingOptionals, @Nonnull final RecordQueryInJoinPlan inJoinPlan) {
    final Optional<Ordering> childOrderingOptional = Iterables.getOnlyElement(orderingOptionals);
    if (childOrderingOptional.isPresent()) {
        final var childOrdering = childOrderingOptional.get();
        final var equalityBoundKeyMap = childOrdering.getEqualityBoundKeyMap();
        final var inSource = inJoinPlan.getInSource();
        final CorrelationIdentifier inAlias = inJoinPlan.getInAlias();
        final SetMultimap<KeyExpression, Comparisons.Comparison> resultEqualityBoundKeyMap = HashMultimap.create(equalityBoundKeyMap);
        KeyExpression inKeyExpression = null;
        for (final var entry : equalityBoundKeyMap.entries()) {
            // TODO we only look for the first entry that matches. That is enough for the in-to-join case,
            // however, it is possible that more than one different key expressions are equality-bound
            // by this in. That would constitute to more than one concurrent order which we cannot
            // express at the moment (we need the PartialOrder approach for that).
            final var comparison = entry.getValue();
            final var correlatedTo = comparison.getCorrelatedTo();
            if (correlatedTo.size() != 1) {
                continue;
            }
            if (inAlias.equals(Iterables.getOnlyElement(correlatedTo))) {
                inKeyExpression = entry.getKey();
                resultEqualityBoundKeyMap.removeAll(inKeyExpression);
                break;
            }
        }
        if (inKeyExpression == null || !inSource.isSorted()) {
            // 
            return Optional.of(new Ordering(resultEqualityBoundKeyMap, ImmutableList.of(), false));
        }
        // 
        // Prepend the existing order with the key expression we just found.
        // 
        final var resultOrderingKeyPartsBuilder = ImmutableList.<KeyPart>builder();
        resultOrderingKeyPartsBuilder.add(KeyPart.of(inKeyExpression, inSource.isReverse()));
        resultOrderingKeyPartsBuilder.addAll(childOrdering.getOrderingKeyParts());
        return Optional.of(new Ordering(resultEqualityBoundKeyMap, resultOrderingKeyPartsBuilder.build(), childOrdering.isDistinct()));
    } else {
        return Optional.empty();
    }
}
Also used : CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart)

Aggregations

CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)31 Set (java.util.Set)19 ImmutableSet (com.google.common.collect.ImmutableSet)18 Test (org.junit.jupiter.api.Test)17 List (java.util.List)15 ImmutableList (com.google.common.collect.ImmutableList)14 Nonnull (javax.annotation.Nonnull)11 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)10 API (com.apple.foundationdb.annotation.API)8 AliasMap (com.apple.foundationdb.record.query.plan.temp.AliasMap)8 Value (com.apple.foundationdb.record.query.predicates.Value)7 GroupExpressionRef (com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef)5 MatchInfo (com.apple.foundationdb.record.query.plan.temp.MatchInfo)5 PartialMatch (com.apple.foundationdb.record.query.plan.temp.PartialMatch)5 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)5 QueryPredicate (com.apple.foundationdb.record.query.predicates.QueryPredicate)5 Verify (com.google.common.base.Verify)5 Optional (java.util.Optional)5 RecordQueryFetchFromPartialRecordPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan)4 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)4