Search in sources :

Example 1 with AliasMap

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

the class RecordQueryPlan method structuralEquals.

/**
 * Determine if two plans are structurally equal. This differs from the semantic equality defined in
 * {@link RelationalExpression}. For instance this method would return false
 * for two given plans {@code UNION(p1, p2)} and {@code UNION(p2, p1)} of two different sub-plans {@code p1} and
 * {@code p2}. In contrast to that these plans are considered semantically equal.
 * @param other object to compare this object with
 * @param equivalenceMap alias map to indicate aliases that should be considered as equal when {@code other} is
 *        compared to {@code this}. For instance {@code q1.x = 1} is only structurally equal with {@code q2.x = 1}
 *        if there is a mapping {@code q1 -> q2} in the alias map passed in
 * @return {@code true} if {@code this} is structurally equal to {@code other}, {@code false} otherwise
 */
@API(API.Status.EXPERIMENTAL)
default boolean structuralEquals(@Nullable final Object other, @Nonnull final AliasMap equivalenceMap) {
    if (this == other) {
        return true;
    }
    if (other == null || getClass() != other.getClass()) {
        return false;
    }
    final RelationalExpression otherExpression = (RelationalExpression) other;
    // We know this and otherExpression are of the same class. canCorrelate() needs to match as well.
    Verify.verify(canCorrelate() == otherExpression.canCorrelate());
    final List<Quantifier.Physical> quantifiers = Quantifiers.narrow(Quantifier.Physical.class, getQuantifiers());
    final List<Quantifier.Physical> otherQuantifiers = Quantifiers.narrow(Quantifier.Physical.class, otherExpression.getQuantifiers());
    if (quantifiers.size() != otherQuantifiers.size()) {
        return false;
    }
    final Iterable<AliasMap> boundCorrelatedReferencesIterable = enumerateUnboundCorrelatedTo(equivalenceMap, otherExpression);
    for (final AliasMap boundCorrelatedReferencesMap : boundCorrelatedReferencesIterable) {
        final AliasMap.Builder boundCorrelatedToBuilder = boundCorrelatedReferencesMap.derived();
        AliasMap boundCorrelatedToMap = AliasMap.emptyMap();
        int i;
        for (i = 0; i < quantifiers.size(); i++) {
            boundCorrelatedToMap = boundCorrelatedToBuilder.build();
            final Quantifier.Physical quantifier = quantifiers.get(i);
            final Quantifier.Physical otherQuantifier = otherQuantifiers.get(i);
            if (quantifier.structuralHashCode() != otherQuantifier.structuralHashCode()) {
                break;
            }
            if (!quantifier.structuralEquals(otherQuantifier)) {
                break;
            }
            if (canCorrelate()) {
                boundCorrelatedToBuilder.put(quantifier.getAlias(), otherQuantifier.getAlias());
            }
        }
        if (i == quantifiers.size() && (equalsWithoutChildren(otherExpression, boundCorrelatedToMap))) {
            return true;
        }
    }
    return false;
}
Also used : RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) API(com.apple.foundationdb.annotation.API)

Example 2 with AliasMap

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

the class RecordQuerySetPlan method tryPushValues.

@Nonnull
@SuppressWarnings("java:S135")
default Set<CorrelationIdentifier> tryPushValues(@Nonnull final List<TranslateValueFunction> dependentFunctions, @Nonnull final List<? extends Quantifier> quantifiers, @Nonnull final Iterable<? extends Value> values) {
    Verify.verify(!dependentFunctions.isEmpty());
    Verify.verify(dependentFunctions.size() == quantifiers.size());
    final Set<CorrelationIdentifier> candidatesAliases = quantifiers.stream().map(Quantifier::getAlias).collect(Collectors.toSet());
    final CorrelationIdentifier newBaseAlias = CorrelationIdentifier.uniqueID();
    final QuantifiedColumnValue newBaseColumnValue = QuantifiedColumnValue.of(newBaseAlias, 0);
    for (final Value value : values) {
        final AliasMap equivalencesMap = AliasMap.identitiesFor(ImmutableSet.of(newBaseAlias));
        @Nullable Value previousPushedValue = null;
        for (int i = 0; i < dependentFunctions.size(); i++) {
            final TranslateValueFunction dependentFunction = dependentFunctions.get(i);
            final Quantifier quantifier = quantifiers.get(i);
            if (!candidatesAliases.contains(quantifier.getAlias())) {
                continue;
            }
            final Optional<Value> pushedValueOptional = dependentFunction.translateValue(value, newBaseColumnValue);
            if (!pushedValueOptional.isPresent()) {
                candidatesAliases.remove(quantifier.getAlias());
                continue;
            }
            if (previousPushedValue == null) {
                previousPushedValue = pushedValueOptional.get();
            } else {
                if (!previousPushedValue.semanticEquals(pushedValueOptional.get(), equivalencesMap)) {
                    // something is really wrong as we cannot establish a proper genuine derivation path
                    return ImmutableSet.of();
                }
            }
        }
    }
    return ImmutableSet.copyOf(candidatesAliases);
}
Also used : QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Nullable(javax.annotation.Nullable) Nonnull(javax.annotation.Nonnull)

Example 3 with AliasMap

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

the class SelectExpression method subsumedBy.

@Nonnull
@Override
public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candidateExpression, @Nonnull final AliasMap aliasMap, @Nonnull final IdentityBiMap<Quantifier, PartialMatch> partialMatchMap) {
    // TODO This method should be simplified by adding some structure to it.
    final Collection<MatchInfo> matchInfos = PartialMatch.matchesFromMap(partialMatchMap);
    Verify.verify(this != candidateExpression);
    if (getClass() != candidateExpression.getClass()) {
        return ImmutableList.of();
    }
    final SelectExpression otherSelectExpression = (SelectExpression) candidateExpression;
    // merge parameter maps -- early out if a binding clashes
    final ImmutableList<Map<CorrelationIdentifier, ComparisonRange>> parameterBindingMaps = matchInfos.stream().map(MatchInfo::getParameterBindingMap).collect(ImmutableList.toImmutableList());
    final Optional<Map<CorrelationIdentifier, ComparisonRange>> mergedParameterBindingMapOptional = MatchInfo.tryMergeParameterBindings(parameterBindingMaps);
    if (!mergedParameterBindingMapOptional.isPresent()) {
        return ImmutableList.of();
    }
    final Map<CorrelationIdentifier, ComparisonRange> mergedParameterBindingMap = mergedParameterBindingMapOptional.get();
    final ImmutableSet.Builder<CorrelationIdentifier> matchedCorrelatedToBuilder = ImmutableSet.builder();
    // for-each quantifiers. Also keep track of all aliases the matched quantifiers are correlated to.
    for (final Quantifier quantifier : getQuantifiers()) {
        if (partialMatchMap.containsKeyUnwrapped(quantifier)) {
            if (quantifier instanceof Quantifier.ForEach) {
                // current quantifier is matched
                final PartialMatch childPartialMatch = Objects.requireNonNull(partialMatchMap.getUnwrapped(quantifier));
                if (!childPartialMatch.getQueryExpression().computeUnmatchedForEachQuantifiers(childPartialMatch).isEmpty()) {
                    return ImmutableList.of();
                }
            }
            matchedCorrelatedToBuilder.addAll(quantifier.getCorrelatedTo());
        }
    }
    for (final Value resultValue : getResultValues()) {
        matchedCorrelatedToBuilder.addAll(resultValue.getCorrelatedTo());
    }
    final ImmutableSet<CorrelationIdentifier> matchedCorrelatedTo = matchedCorrelatedToBuilder.build();
    if (getQuantifiers().stream().anyMatch(quantifier -> quantifier instanceof Quantifier.ForEach && !partialMatchMap.containsKeyUnwrapped(quantifier))) {
        return ImmutableList.of();
    }
    final boolean allNonMatchedQuantifiersIndependent = getQuantifiers().stream().filter(quantifier -> !partialMatchMap.containsKeyUnwrapped(quantifier)).noneMatch(quantifier -> matchedCorrelatedTo.contains(quantifier.getAlias()));
    if (!allNonMatchedQuantifiersIndependent) {
        return ImmutableList.of();
    }
    // Loop through all for each quantifiers on the other side to ensure that they are all matched.
    // If any are not matched we cannot establish a match at all.
    final boolean allOtherForEachQuantifiersMatched = otherSelectExpression.getQuantifiers().stream().filter(quantifier -> quantifier instanceof Quantifier.ForEach).allMatch(quantifier -> aliasMap.containsTarget(quantifier.getAlias()));
    // would help us here to make sure the additional non-matched quantifier is not eliminating records.
    if (!allOtherForEachQuantifiersMatched) {
        return ImmutableList.of();
    }
    // 
    // Map predicates on the query side to predicates on the candidate side. Record parameter bindings and/or
    // compensations for each mapped predicate.
    // A predicate on this side (the query side) can cause us to filter out rows, a mapped predicate (for that
    // predicate) can only filter out fewer rows which is correct and can be compensated for. The important part
    // is that we must not have predicates on the other (candidate) side at the end of this mapping process which
    // would mean that the candidate eliminates records that the query side may not eliminate. If we detect that
    // case we MUST not create a match.
    // 
    final ImmutableList.Builder<Iterable<PredicateMapping>> predicateMappingsBuilder = ImmutableList.builder();
    // 
    if (getPredicates().isEmpty()) {
        final boolean allNonFiltering = otherSelectExpression.getPredicates().stream().allMatch(queryPredicate -> queryPredicate instanceof Placeholder || queryPredicate.isTautology());
        if (allNonFiltering) {
            return MatchInfo.tryMerge(partialMatchMap, mergedParameterBindingMap, PredicateMap.empty()).map(ImmutableList::of).orElse(ImmutableList.of());
        } else {
            return ImmutableList.of();
        }
    }
    for (final QueryPredicate predicate : getPredicates()) {
        final Set<PredicateMapping> impliedMappingsForPredicate = predicate.findImpliedMappings(aliasMap, otherSelectExpression.getPredicates());
        predicateMappingsBuilder.add(impliedMappingsForPredicate);
    }
    // 
    // We now have a multimap from predicates on the query side to predicates on the candidate side. In the trivial
    // case this multimap only contains singular mappings for a query predicate. If it doesn't we need to enumerate
    // through their cross product exhaustively. Each complete and non-contradictory element of that cross product
    // can lead to a match.
    // 
    final EnumeratingIterable<PredicateMapping> crossedMappings = CrossProduct.crossProduct(predicateMappingsBuilder.build());
    return IterableHelpers.flatMap(crossedMappings, predicateMappings -> {
        final Set<QueryPredicate> unmappedOtherPredicates = Sets.newIdentityHashSet();
        unmappedOtherPredicates.addAll(otherSelectExpression.getPredicates());
        final Map<CorrelationIdentifier, ComparisonRange> parameterBindingMap = Maps.newHashMap();
        final PredicateMap.Builder predicateMapBuilder = PredicateMap.builder();
        for (final PredicateMapping predicateMapping : predicateMappings) {
            predicateMapBuilder.put(predicateMapping.getQueryPredicate(), predicateMapping);
            unmappedOtherPredicates.remove(predicateMapping.getCandidatePredicate());
            final Optional<CorrelationIdentifier> parameterAliasOptional = predicateMapping.getParameterAliasOptional();
            final Optional<ComparisonRange> comparisonRangeOptional = predicateMapping.getComparisonRangeOptional();
            if (parameterAliasOptional.isPresent() && comparisonRangeOptional.isPresent()) {
                parameterBindingMap.put(parameterAliasOptional.get(), comparisonRangeOptional.get());
            }
        }
        // 
        // Last chance for unmapped predicates - if there is a placeholder or a tautology on the other side that is still
        // unmapped, we can (and should) remove it from the unmapped other set now. The reasoning is that this predicate is
        // not filtering so it does not cause records to be filtered that are not filtered on the query side.
        // 
        unmappedOtherPredicates.removeIf(queryPredicate -> queryPredicate instanceof Placeholder || queryPredicate.isTautology());
        if (!unmappedOtherPredicates.isEmpty()) {
            return ImmutableList.of();
        }
        final Optional<? extends PredicateMap> predicateMapOptional = predicateMapBuilder.buildMaybe();
        return predicateMapOptional.map(predicateMap -> {
            final Optional<Map<CorrelationIdentifier, ComparisonRange>> allParameterBindingMapOptional = MatchInfo.tryMergeParameterBindings(ImmutableList.of(mergedParameterBindingMap, parameterBindingMap));
            return allParameterBindingMapOptional.flatMap(allParameterBindingMap -> MatchInfo.tryMerge(partialMatchMap, allParameterBindingMap, predicateMap)).map(ImmutableList::of).orElse(ImmutableList.of());
        }).orElse(ImmutableList.of());
    });
}
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) Placeholder(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate.Placeholder) EnumeratingIterable(com.apple.foundationdb.record.query.combinatorics.EnumeratingIterable) ImmutableList(com.google.common.collect.ImmutableList) PredicateMap(com.apple.foundationdb.record.query.plan.temp.PredicateMap) ImmutableSet(com.google.common.collect.ImmutableSet) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) Optional(java.util.Optional) PredicateMapping(com.apple.foundationdb.record.query.plan.temp.PredicateMultiMap.PredicateMapping) MatchInfo(com.apple.foundationdb.record.query.plan.temp.MatchInfo) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) Value(com.apple.foundationdb.record.query.predicates.Value) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) ComparisonRange(com.apple.foundationdb.record.query.plan.temp.ComparisonRange) PredicateMap(com.apple.foundationdb.record.query.plan.temp.PredicateMap) Map(java.util.Map) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) ImmutableMap(com.google.common.collect.ImmutableMap) Nonnull(javax.annotation.Nonnull)

Example 4 with AliasMap

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

the class FindingMatcher 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 predicate is called for each pair of
 * elements (for a match attempt). If the match predicate returns {@code true} the pair is recorded
 * as a matching pair. We attempt to find a matching pair (one element from this side; one from the
 * other side) for each element identified by {@link #getAliases()}. For each individual new such pair that is found,
 * we continue in the matching attempt. Once a set of bindings is established for all aliases
 * in {@link #getAliases} this method then includes that {@link AliasMap} in the computable of {@link AliasMap}s that
 * form the result and proceeds to consume further permutations from the iterator that is passed in in order to
 * establish other matches between this and other.
 * @param iterator an enumerating iterable for the permutations on this side
 * @param otherOrdered one permutation (that is not violating dependencies, constraints, etc.) of the other side
 * @return an {@link Iterator} of match results (of type {@link AliasMap})
 */
@SuppressWarnings("java:S135")
@Nonnull
public Iterator<AliasMap> enumerate(@Nonnull final EnumeratingIterator<CorrelationIdentifier> iterator, @Nonnull final List<CorrelationIdentifier> otherOrdered) {
    final Set<CorrelationIdentifier> aliases = getAliases();
    final AliasMap boundAliasesMap = getBoundAliasesMap();
    if (otherOrdered.isEmpty()) {
        return ImmutableList.of(boundAliasesMap).iterator();
    }
    int size = otherOrdered.size();
    return new AbstractIterator<AliasMap>() {

        @Override
        protected AliasMap computeNext() {
            while (iterator.hasNext()) {
                final List<CorrelationIdentifier> ordered = iterator.next();
                final AliasMap.Builder aliasMapBuilder = AliasMap.builder(aliases.size());
                int i;
                for (i = 0; i < size; i++) {
                    final AliasMap aliasMap = aliasMapBuilder.build();
                    final CorrelationIdentifier alias = ordered.get(i);
                    final CorrelationIdentifier otherAlias = otherOrdered.get(i);
                    final Optional<AliasMap> dependsOnMapOptional = mapDependenciesToOther(aliasMap, alias, otherAlias);
                    if (!dependsOnMapOptional.isPresent()) {
                        break;
                    }
                    final AliasMap dependsOnMap = dependsOnMapOptional.get();
                    final T entity = Objects.requireNonNull(getAliasToElementMap().get(alias));
                    final T otherEntity = Objects.requireNonNull(getOtherAliasToElementMap().get(otherAlias));
                    if (!matchPredicate.test(entity, otherEntity, boundAliasesMap.combine(dependsOnMap))) {
                        break;
                    }
                    // 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);
                }
                if (i == size) {
                    iterator.skip(i - 1);
                    return boundAliasesMap.derived(ordered.size()).zip(ordered, otherOrdered, i).build();
                } else {
                    // we can skip all permutations where the i-th value is bound the way it currently is
                    iterator.skip(i);
                }
            }
            return endOfData();
        }
    };
}
Also used : CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) AbstractIterator(com.google.common.collect.AbstractIterator) Nonnull(javax.annotation.Nonnull)

Example 5 with AliasMap

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

the class SelectExpression method partitionPredicates.

private static List<? extends QueryPredicate> partitionPredicates(final List<? extends QueryPredicate> predicates) {
    final ImmutableList<QueryPredicate> flattenedAndPredicates = predicates.stream().flatMap(predicate -> flattenAndPredicate(predicate).stream()).collect(ImmutableList.toImmutableList());
    // partition predicates in value-based predicates and non-value-based predicates
    final ImmutableList.Builder<PredicateWithValue> predicateWithValuesBuilder = ImmutableList.builder();
    final ImmutableList.Builder<QueryPredicate> resultPredicatesBuilder = ImmutableList.builder();
    for (final QueryPredicate flattenedAndPredicate : flattenedAndPredicates) {
        if (flattenedAndPredicate instanceof PredicateWithValue) {
            predicateWithValuesBuilder.add((PredicateWithValue) flattenedAndPredicate);
        } else {
            resultPredicatesBuilder.add(flattenedAndPredicate);
        }
    }
    final ImmutableList<PredicateWithValue> predicateWithValues = predicateWithValuesBuilder.build();
    final AliasMap boundIdentitiesMap = AliasMap.identitiesFor(flattenedAndPredicates.stream().flatMap(predicate -> predicate.getCorrelatedTo().stream()).collect(ImmutableSet.toImmutableSet()));
    final BoundEquivalence boundEquivalence = new BoundEquivalence(boundIdentitiesMap);
    final HashMultimap<Equivalence.Wrapper<Value>, PredicateWithValue> partitionedPredicatesWithValues = predicateWithValues.stream().collect(Multimaps.toMultimap(predicate -> boundEquivalence.wrap(predicate.getValue()), Function.identity(), HashMultimap::create));
    partitionedPredicatesWithValues.asMap().forEach((valueWrapper, predicatesOnValue) -> {
        final Value value = Objects.requireNonNull(valueWrapper.get());
        ComparisonRange resultRange = ComparisonRange.EMPTY;
        for (final PredicateWithValue predicateOnValue : predicatesOnValue) {
            if (predicateOnValue instanceof ValuePredicate) {
                final Comparisons.Comparison comparison = ((ValuePredicate) predicateOnValue).getComparison();
                final ComparisonRange.MergeResult mergeResult = resultRange.merge(comparison);
                resultRange = mergeResult.getComparisonRange();
                mergeResult.getResidualComparisons().forEach(residualComparison -> resultPredicatesBuilder.add(value.withComparison(residualComparison)));
            } else if (predicateOnValue instanceof Sargable) {
                final Sargable valueComparisonRangePredicate = (Sargable) predicateOnValue;
                final ComparisonRange comparisonRange = valueComparisonRangePredicate.getComparisonRange();
                final ComparisonRange.MergeResult mergeResult = resultRange.merge(comparisonRange);
                resultRange = mergeResult.getComparisonRange();
                mergeResult.getResidualComparisons().forEach(residualComparison -> resultPredicatesBuilder.add(value.withComparison(residualComparison)));
            } else {
                resultPredicatesBuilder.add(predicateOnValue);
            }
        }
        if (!resultRange.isEmpty()) {
            resultPredicatesBuilder.add(ValueComparisonRangePredicate.sargable(value, resultRange));
        }
    });
    return resultPredicatesBuilder.build();
}
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) Sargable(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate.Sargable) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) ImmutableList(com.google.common.collect.ImmutableList) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) AliasMap(com.apple.foundationdb.record.query.plan.temp.AliasMap) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) ValuePredicate(com.apple.foundationdb.record.query.predicates.ValuePredicate) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) Value(com.apple.foundationdb.record.query.predicates.Value) ComparisonRange(com.apple.foundationdb.record.query.plan.temp.ComparisonRange)

Aggregations

AliasMap (com.apple.foundationdb.record.query.plan.temp.AliasMap)7 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)6 Nonnull (javax.annotation.Nonnull)6 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)5 API (com.apple.foundationdb.annotation.API)4 Value (com.apple.foundationdb.record.query.predicates.Value)4 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)3 PredicateWithValue (com.apple.foundationdb.record.query.predicates.PredicateWithValue)3 QueryPredicate (com.apple.foundationdb.record.query.predicates.QueryPredicate)3 Verify (com.google.common.base.Verify)3 ImmutableList (com.google.common.collect.ImmutableList)3 CrossProduct (com.apple.foundationdb.record.query.combinatorics.CrossProduct)2 EnumeratingIterable (com.apple.foundationdb.record.query.combinatorics.EnumeratingIterable)2 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)2 ComparisonRange (com.apple.foundationdb.record.query.plan.temp.ComparisonRange)2 Compensation (com.apple.foundationdb.record.query.plan.temp.Compensation)2 IdentityBiMap (com.apple.foundationdb.record.query.plan.temp.IdentityBiMap)2 IterableHelpers (com.apple.foundationdb.record.query.plan.temp.IterableHelpers)2 MatchInfo (com.apple.foundationdb.record.query.plan.temp.MatchInfo)2 PartialMatch (com.apple.foundationdb.record.query.plan.temp.PartialMatch)2