Search in sources :

Example 6 with Ordering

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

the class OrderingProperty method deriveForIntersectionFromOrderings.

public static Optional<Ordering> deriveForIntersectionFromOrderings(@Nonnull final List<Optional<Ordering>> orderingOptionals, @Nonnull final RequestedOrdering requestedOrdering, @Nonnull final BinaryOperator<SetMultimap<KeyExpression, Comparisons.Comparison>> combineFn) {
    final Optional<SetMultimap<KeyExpression, Comparisons.Comparison>> commonEqualityBoundKeysMapOptional = Ordering.combineEqualityBoundKeys(orderingOptionals, combineFn);
    if (commonEqualityBoundKeysMapOptional.isEmpty()) {
        return Optional.empty();
    }
    final var commonEqualityBoundKeysMap = commonEqualityBoundKeysMapOptional.get();
    final Optional<List<KeyPart>> commonOrderingKeysOptional = Ordering.commonOrderingKeys(orderingOptionals, requestedOrdering);
    if (commonOrderingKeysOptional.isEmpty()) {
        return Optional.empty();
    }
    final var commonOrderingKeys = commonOrderingKeysOptional.get().stream().filter(keyPart -> !commonEqualityBoundKeysMap.containsKey(keyPart.getNormalizedKeyExpression())).collect(ImmutableList.toImmutableList());
    final boolean allAreDistinct = orderingOptionals.stream().anyMatch(orderingOptional -> orderingOptional.map(Ordering::isDistinct).orElse(false));
    return Optional.of(new Ordering(commonEqualityBoundKeysMap, commonOrderingKeys, allAreDistinct));
}
Also used : RecordQueryIntersectionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIntersectionPlan) PlannerProperty(com.apple.foundationdb.record.query.plan.temp.PlannerProperty) HashMultimap(com.google.common.collect.HashMultimap) Pair(org.apache.commons.lang3.tuple.Pair) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) RecordQueryUnorderedUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedUnionPlan) PrimaryScanExpression(com.apple.foundationdb.record.query.plan.temp.expressions.PrimaryScanExpression) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) RecordQueryPredicatesFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPredicatesFilterPlan) Collectors(java.util.stream.Collectors) BinaryOperator(java.util.function.BinaryOperator) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) List(java.util.List) Stream(java.util.stream.Stream) RecordQueryInUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) RecordQueryInJoinPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInJoinPlan) PlanContext(com.apple.foundationdb.record.query.plan.temp.PlanContext) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) CORRELATION(com.apple.foundationdb.record.Bindings.Internal.CORRELATION) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Iterables(com.google.common.collect.Iterables) ValuePredicate(com.apple.foundationdb.record.query.predicates.ValuePredicate) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) LogicalSortExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalSortExpression) Key(com.apple.foundationdb.record.metadata.Key) ImmutableList(com.google.common.collect.ImmutableList) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) SetMultimap(com.google.common.collect.SetMultimap) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) ValueIndexExpansionVisitor(com.apple.foundationdb.record.query.plan.temp.ValueIndexExpansionVisitor) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) SetMultimap(com.google.common.collect.SetMultimap) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList)

Example 7 with Ordering

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

the class ImplementInJoinRule method onMatch.

@SuppressWarnings("java:S135")
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final var context = call.getContext();
    final var bindings = call.getBindings();
    final var requestedOrderingsOptional = call.getInterestingProperty(OrderingAttribute.ORDERING);
    if (requestedOrderingsOptional.isEmpty()) {
        return;
    }
    final var requestedOrderings = requestedOrderingsOptional.get();
    final var selectExpression = bindings.get(root);
    if (!selectExpression.getPredicates().isEmpty()) {
        return;
    }
    final var explodeQuantifiers = bindings.get(explodeQuantifiersMatcher);
    if (explodeQuantifiers.isEmpty()) {
        return;
    }
    final var explodeAliasToQuantifierMap = Quantifiers.aliasToQuantifierMap(explodeQuantifiers);
    final var explodeAliases = explodeAliasToQuantifierMap.keySet();
    final var innerQuantifierOptional = findInnerQuantifier(selectExpression, explodeQuantifiers, explodeAliases);
    if (innerQuantifierOptional.isEmpty()) {
        return;
    }
    final var innerQuantifier = innerQuantifierOptional.get();
    final List<? extends Value> resultValues = selectExpression.getResultValues();
    if (resultValues.stream().anyMatch(resultValue -> !(resultValue instanceof QuantifiedColumnValue) || !((QuantifiedColumnValue) resultValue).getAlias().equals(innerQuantifier.getAlias()))) {
        return;
    }
    final var explodeExpressions = bindings.getAll(explodeExpressionMatcher);
    final var quantifierToExplodeBiMap = computeQuantifierToExplodeMap(explodeQuantifiers, explodeExpressions.stream().collect(LinkedIdentitySet.toLinkedIdentitySet()));
    final Map<Ordering, ImmutableList<RecordQueryPlan>> groupedByOrdering = innerQuantifier.getRangesOver().getMembers().stream().flatMap(relationalExpression -> relationalExpression.narrowMaybe(RecordQueryPlan.class).stream()).flatMap(plan -> {
        final Optional<Ordering> orderingForLegOptional = OrderingProperty.evaluate(plan, context);
        return orderingForLegOptional.stream().map(ordering -> Pair.of(ordering, plan));
    }).collect(Collectors.groupingBy(Pair::getLeft, Collectors.mapping(Pair::getRight, ImmutableList.toImmutableList())));
    for (final Map.Entry<Ordering, ImmutableList<RecordQueryPlan>> providedOrderingEntry : groupedByOrdering.entrySet()) {
        final var providedOrdering = providedOrderingEntry.getKey();
        for (final RequestedOrdering requestedOrdering : requestedOrderings) {
            final ImmutableList<InSource> sources = getInSourcesForRequestedOrdering(explodeAliasToQuantifierMap, explodeAliases, quantifierToExplodeBiMap, providedOrdering, requestedOrdering);
            if (sources.isEmpty()) {
                continue;
            }
            final var reverseSources = Lists.reverse(sources);
            GroupExpressionRef<RecordQueryPlan> newInnerPlanReference = GroupExpressionRef.from(providedOrderingEntry.getValue());
            for (final InSource inSource : reverseSources) {
                final var inJoinPlan = inSource.toInJoinPlan(Quantifier.physical(newInnerPlanReference));
                newInnerPlanReference = GroupExpressionRef.of(inJoinPlan);
            }
            call.yield(newInnerPlanReference);
        }
    }
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) OrderingAttribute(com.apple.foundationdb.record.query.plan.temp.OrderingAttribute) LinkedIdentitySet(com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) HashMultimap(com.google.common.collect.HashMultimap) Pair(org.apache.commons.lang3.tuple.Pair) RelationalExpressionMatchers.selectExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.selectExpression) Map(java.util.Map) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) Set(java.util.Set) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) Value(com.apple.foundationdb.record.query.predicates.Value) List(java.util.List) RecordQueryInUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) OrderingProperty(com.apple.foundationdb.record.query.plan.temp.properties.OrderingProperty) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) CORRELATION(com.apple.foundationdb.record.Bindings.Internal.CORRELATION) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) CollectionMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.CollectionMatcher) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) Quantifiers(com.apple.foundationdb.record.query.plan.temp.Quantifiers) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RelationalExpressionMatchers.explodeExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.explodeExpression) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier(com.apple.foundationdb.record.query.plan.temp.rules.PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) InValuesSource(com.apple.foundationdb.record.query.plan.plans.InValuesSource) MultiMatcher.some(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.some) Nonnull(javax.annotation.Nonnull) SortedInValuesSource(com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) SortedInParameterSource(com.apple.foundationdb.record.query.plan.plans.SortedInParameterSource) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) ExplodeExpression(com.apple.foundationdb.record.query.plan.temp.expressions.ExplodeExpression) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Optional(java.util.Optional) ImmutableList(com.google.common.collect.ImmutableList) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) Map(java.util.Map) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) Pair(org.apache.commons.lang3.tuple.Pair)

Example 8 with Ordering

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

the class RemoveSortRule method onMatch.

@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final LogicalSortExpression sortExpression = call.get(root);
    final RecordQueryPlan innerPlan = call.get(innerPlanMatcher);
    final KeyExpression sortKeyExpression = sortExpression.getSort();
    if (sortKeyExpression == null) {
        call.yield(call.ref(innerPlan));
        return;
    }
    final Optional<Ordering> orderingOptional = OrderingProperty.evaluate(innerPlan, call.getContext());
    if (orderingOptional.isEmpty()) {
        return;
    }
    final Ordering ordering = orderingOptional.get();
    final Set<KeyExpression> equalityBoundKeys = ordering.getEqualityBoundKeys();
    int equalityBoundUnsorted = equalityBoundKeys.size();
    final List<KeyPart> orderingKeys = ordering.getOrderingKeyParts();
    final Iterator<KeyPart> orderingKeysIterator = orderingKeys.iterator();
    final List<KeyExpression> normalizedSortExpressions = sortKeyExpression.normalizeKeyForPositions();
    for (final KeyExpression normalizedSortExpression : normalizedSortExpressions) {
        if (equalityBoundKeys.contains(normalizedSortExpression)) {
            equalityBoundUnsorted--;
            continue;
        }
        if (!orderingKeysIterator.hasNext()) {
            return;
        }
        final KeyPart currentOrderingKeyPart = orderingKeysIterator.next();
        if (!normalizedSortExpression.equals(currentOrderingKeyPart.getNormalizedKeyExpression())) {
            return;
        }
    }
    final boolean strictOrdered = // If we have exhausted the ordering info's keys, too, then its constituents are strictly ordered.
    !orderingKeysIterator.hasNext() || // Also a unique index if have gone through declared fields.
    strictlyOrderedIfUnique(innerPlan, call.getContext()::getIndexByName, normalizedSortExpressions.size() + equalityBoundUnsorted);
    call.yield(call.ref(strictOrdered ? innerPlan.strictlySorted() : innerPlan));
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) LogicalSortExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalSortExpression)

Example 9 with Ordering

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

the class ImplementDistinctUnionRule method onMatch.

@Override
@SuppressWarnings("java:S135")
public void onMatch(@Nonnull PlannerRuleCall call) {
    final PlanContext context = call.getContext();
    final Optional<Set<RequestedOrdering>> requiredOrderingsOptional = call.getInterestingProperty(OrderingAttribute.ORDERING);
    if (requiredOrderingsOptional.isEmpty()) {
        return;
    }
    final Set<RequestedOrdering> requestedOrderings = requiredOrderingsOptional.get();
    final KeyExpression commonPrimaryKey = context.getCommonPrimaryKey();
    if (commonPrimaryKey == null) {
        return;
    }
    final List<KeyExpression> commonPrimaryKeyParts = commonPrimaryKey.normalizeKeyForPositions();
    final PlannerBindings bindings = call.getBindings();
    final Quantifier.ForEach unionForEachQuantifier = bindings.get(unionForEachQuantifierMatcher);
    final List<? extends Collection<? extends RecordQueryPlan>> plansByQuantifier = bindings.getAll(unionLegPlansMatcher);
    // group each leg's plans by their provided ordering
    final ImmutableList<Set<Map.Entry<Ordering, ImmutableList<RecordQueryPlan>>>> plansByQuantifierOrdering = plansByQuantifier.stream().map(plansForQuantifier -> {
        final Map<Ordering, ImmutableList<RecordQueryPlan>> groupedBySortedness = plansForQuantifier.stream().flatMap(plan -> {
            final Optional<Ordering> orderingForLegOptional = OrderingProperty.evaluate(plan, context);
            return orderingForLegOptional.stream().map(ordering -> Pair.of(ordering, plan));
        }).collect(Collectors.groupingBy(Pair::getLeft, Collectors.mapping(Pair::getRight, ImmutableList.toImmutableList())));
        return groupedBySortedness.entrySet();
    }).collect(ImmutableList.toImmutableList());
    for (final List<Map.Entry<Ordering, ImmutableList<RecordQueryPlan>>> entries : CrossProduct.crossProduct(plansByQuantifierOrdering)) {
        final ImmutableList<Optional<Ordering>> orderingOptionals = entries.stream().map(entry -> Optional.of(entry.getKey())).collect(ImmutableList.toImmutableList());
        for (final RequestedOrdering requestedOrdering : requestedOrderings) {
            final Optional<Ordering> combinedOrderingOptional = OrderingProperty.deriveForUnionFromOrderings(orderingOptionals, requestedOrdering, Ordering::intersectEqualityBoundKeys);
            pushInterestingOrders(call, unionForEachQuantifier, orderingOptionals, requestedOrdering);
            if (combinedOrderingOptional.isEmpty()) {
                // 
                continue;
            }
            final Ordering ordering = combinedOrderingOptional.get();
            final Set<KeyExpression> equalityBoundKeys = ordering.getEqualityBoundKeys();
            final List<KeyPart> orderingKeyParts = ordering.getOrderingKeyParts();
            final List<KeyExpression> orderingKeys = orderingKeyParts.stream().map(KeyPart::getNormalizedKeyExpression).collect(ImmutableList.toImmutableList());
            // make sure the common primary key parts are either bound through equality or they are part of the ordering
            if (!isPrimaryKeyCompatibleWithOrdering(commonPrimaryKeyParts, orderingKeys, equalityBoundKeys)) {
                continue;
            }
            // 
            // At this point we know we can implement the distinct union over the partitions of compatibly ordered plans
            // 
            final KeyExpression comparisonKey = orderingKeys.size() == 1 ? Iterables.getOnlyElement(orderingKeys) : Key.Expressions.concat(orderingKeys);
            // 
            // create new references
            // 
            final ImmutableList<Quantifier.Physical> newQuantifiers = entries.stream().map(Map.Entry::getValue).map(GroupExpressionRef::from).map(Quantifier::physical).collect(ImmutableList.toImmutableList());
            call.yield(call.ref(RecordQueryUnionPlan.fromQuantifiers(newQuantifiers, comparisonKey, true)));
        }
    }
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) ReferenceMatchers.references(com.apple.foundationdb.record.query.plan.temp.matchers.ReferenceMatchers.references) OrderingAttribute(com.apple.foundationdb.record.query.plan.temp.OrderingAttribute) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) CollectionMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.CollectionMatcher) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Key(com.apple.foundationdb.record.metadata.Key) ImmutableList(com.google.common.collect.ImmutableList) Pair(org.apache.commons.lang3.tuple.Pair) Map(java.util.Map) MultiMatcher.some(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.some) RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) Nonnull(javax.annotation.Nonnull) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) LogicalDistinctExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalDistinctExpression) Collection(java.util.Collection) Set(java.util.Set) MultiMatcher.all(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.all) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) RelationalExpressionMatchers.logicalUnionExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.logicalUnionExpression) Collectors(java.util.stream.Collectors) LogicalUnionExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalUnionExpression) List(java.util.List) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) CrossProduct(com.apple.foundationdb.record.query.combinatorics.CrossProduct) OrderingProperty(com.apple.foundationdb.record.query.plan.temp.properties.OrderingProperty) PlanContext(com.apple.foundationdb.record.query.plan.temp.PlanContext) Optional(java.util.Optional) RelationalExpressionMatchers.logicalDistinctExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.logicalDistinctExpression) API(com.apple.foundationdb.annotation.API) QuantifierMatchers.forEachQuantifierOverRef(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifierOverRef) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) RecordQueryPlanMatchers(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableList(com.google.common.collect.ImmutableList) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Pair(org.apache.commons.lang3.tuple.Pair) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Optional(java.util.Optional) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) PlanContext(com.apple.foundationdb.record.query.plan.temp.PlanContext) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) Map(java.util.Map)

Example 10 with Ordering

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

the class ImplementInJoinRule method getInSourcesForRequestedOrdering.

@Nonnull
@SuppressWarnings("unchecked")
private ImmutableList<InSource> getInSourcesForRequestedOrdering(@Nonnull final Map<CorrelationIdentifier, Quantifier> explodeAliasToQuantifierMap, @Nonnull final Set<CorrelationIdentifier> explodeAliases, @Nonnull final IdentityBiMap<Quantifier.ForEach, ExplodeExpression> quantifierToExplodeBiMap, @Nonnull final Ordering providedInnerOrdering, @Nonnull final RequestedOrdering requestedOrdering) {
    final var availableExplodeAliases = Sets.newLinkedHashSet(explodeAliases);
    final var requestedOrderingKeyParts = requestedOrdering.getOrderingKeyParts();
    final var sourcesBuilder = ImmutableList.<InSource>builder();
    final var resultOrderingKeyPartsBuilder = ImmutableList.<KeyPart>builder();
    final var innerOrderingKeyParts = providedInnerOrdering.getOrderingKeyParts();
    final var innerEqualityBoundKeyMap = providedInnerOrdering.getEqualityBoundKeyMap();
    final var resultOrderingEqualityBoundKeyMap = HashMultimap.create(innerEqualityBoundKeyMap);
    for (var i = 0; i < requestedOrderingKeyParts.size() && !availableExplodeAliases.isEmpty(); i++) {
        final var requestedOrderingKeyPart = requestedOrderingKeyParts.get(i);
        final var comparisons = innerEqualityBoundKeyMap.get(requestedOrderingKeyPart.getNormalizedKeyExpression());
        if (comparisons.isEmpty()) {
            return ImmutableList.of();
        }
        final var comparisonsCorrelatedTo = comparisons.stream().flatMap(comparison -> comparison.getCorrelatedTo().stream()).collect(ImmutableSet.toImmutableSet());
        if (comparisonsCorrelatedTo.size() > 1) {
            return ImmutableList.of();
        }
        if (Sets.intersection(comparisonsCorrelatedTo, explodeAliases).isEmpty()) {
            // 
            continue;
        }
        final var explodeAlias = Iterables.getOnlyElement(comparisonsCorrelatedTo);
        // 
        if (!availableExplodeAliases.contains(explodeAlias)) {
            return ImmutableList.of();
        }
        // 
        // We need to find the one quantifier over an explode expression that we can use to establish
        // the requested order.
        // 
        final var explodeQuantifier = Objects.requireNonNull(explodeAliasToQuantifierMap.get(explodeAlias));
        final var explodeExpression = Objects.requireNonNull(quantifierToExplodeBiMap.getUnwrapped(explodeQuantifier));
        // 
        // At this point we have a bound key expression that matches the requested order at this position,
        // and we have our hands on a particular explode expression leading us directly do the in source.
        // 
        final var explodeResultValues = explodeExpression.getResultValues();
        if (explodeResultValues.size() != 1) {
            return ImmutableList.of();
        }
        final var explodeValue = Iterables.getOnlyElement(explodeResultValues);
        final InSource inSource;
        if (explodeValue instanceof LiteralValue<?>) {
            final Object literalValue = ((LiteralValue<?>) explodeValue).getLiteralValue();
            if (literalValue instanceof List<?>) {
                inSource = new SortedInValuesSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), (List<Object>) literalValue, requestedOrderingKeyPart.isReverse());
            } else {
                return ImmutableList.of();
            }
        } else if (explodeValue instanceof QuantifiedColumnValue) {
            inSource = new SortedInParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId(), requestedOrderingKeyPart.isReverse());
        } else {
            return ImmutableList.of();
        }
        availableExplodeAliases.remove(explodeAlias);
        sourcesBuilder.add(inSource);
        resultOrderingEqualityBoundKeyMap.removeAll(requestedOrderingKeyPart.getNormalizedKeyExpression());
        resultOrderingKeyPartsBuilder.add(requestedOrderingKeyPart);
    }
    if (availableExplodeAliases.isEmpty()) {
        // 
        // All available explode aliases have been depleted. Create an ordering and check against the requested
        // ordering.
        // 
        resultOrderingKeyPartsBuilder.addAll(innerOrderingKeyParts);
        final var resultOrdering = new Ordering(resultOrderingEqualityBoundKeyMap, resultOrderingKeyPartsBuilder.build(), providedInnerOrdering.isDistinct());
        return Ordering.satisfiesRequestedOrdering(resultOrdering, requestedOrdering) ? sourcesBuilder.build() : ImmutableList.of();
    } else {
        // 
        for (final var explodeAlias : availableExplodeAliases) {
            final var explodeQuantifier = Objects.requireNonNull(explodeAliasToQuantifierMap.get(explodeAlias));
            final var explodeExpression = Objects.requireNonNull(quantifierToExplodeBiMap.getUnwrapped(explodeQuantifier));
            final var explodeResultValues = explodeExpression.getResultValues();
            if (explodeResultValues.size() != 1) {
                return ImmutableList.of();
            }
            final var explodeValue = Iterables.getOnlyElement(explodeResultValues);
            final InSource inSource;
            if (explodeValue instanceof LiteralValue<?>) {
                final Object literalValue = ((LiteralValue<?>) explodeValue).getLiteralValue();
                if (literalValue instanceof List<?>) {
                    inSource = new InValuesSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), (List<Object>) literalValue);
                } else {
                    return ImmutableList.of();
                }
            } else if (explodeValue instanceof QuantifiedColumnValue) {
                inSource = new InParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId());
            } else {
                return ImmutableList.of();
            }
            sourcesBuilder.add(inSource);
        }
    }
    // 
    return sourcesBuilder.build();
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) OrderingAttribute(com.apple.foundationdb.record.query.plan.temp.OrderingAttribute) LinkedIdentitySet(com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) HashMultimap(com.google.common.collect.HashMultimap) Pair(org.apache.commons.lang3.tuple.Pair) RelationalExpressionMatchers.selectExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.selectExpression) Map(java.util.Map) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) Set(java.util.Set) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) Value(com.apple.foundationdb.record.query.predicates.Value) List(java.util.List) RecordQueryInUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) OrderingProperty(com.apple.foundationdb.record.query.plan.temp.properties.OrderingProperty) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) CORRELATION(com.apple.foundationdb.record.Bindings.Internal.CORRELATION) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) CollectionMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.CollectionMatcher) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) Quantifiers(com.apple.foundationdb.record.query.plan.temp.Quantifiers) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RelationalExpressionMatchers.explodeExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.explodeExpression) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier(com.apple.foundationdb.record.query.plan.temp.rules.PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) InValuesSource(com.apple.foundationdb.record.query.plan.plans.InValuesSource) MultiMatcher.some(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.some) Nonnull(javax.annotation.Nonnull) SortedInValuesSource(com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) SortedInParameterSource(com.apple.foundationdb.record.query.plan.plans.SortedInParameterSource) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) ExplodeExpression(com.apple.foundationdb.record.query.plan.temp.expressions.ExplodeExpression) SortedInParameterSource(com.apple.foundationdb.record.query.plan.plans.SortedInParameterSource) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) SortedInParameterSource(com.apple.foundationdb.record.query.plan.plans.SortedInParameterSource) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) InValuesSource(com.apple.foundationdb.record.query.plan.plans.InValuesSource) SortedInValuesSource(com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) SortedInValuesSource(com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource) Nonnull(javax.annotation.Nonnull)

Aggregations

KeyPart (com.apple.foundationdb.record.query.plan.temp.KeyPart)15 Ordering (com.apple.foundationdb.record.query.plan.temp.Ordering)15 RequestedOrdering (com.apple.foundationdb.record.query.plan.temp.RequestedOrdering)14 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)13 ImmutableList (com.google.common.collect.ImmutableList)13 Nonnull (javax.annotation.Nonnull)12 API (com.apple.foundationdb.annotation.API)11 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)11 ImmutableSet (com.google.common.collect.ImmutableSet)11 Iterables (com.google.common.collect.Iterables)11 Collection (java.util.Collection)11 List (java.util.List)11 Optional (java.util.Optional)11 Collectors (java.util.stream.Collectors)11 Pair (org.apache.commons.lang3.tuple.Pair)11 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)10 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)10 Key (com.apple.foundationdb.record.metadata.Key)9 CORRELATION (com.apple.foundationdb.record.Bindings.Internal.CORRELATION)8 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)7