Search in sources :

Example 1 with Value

use of com.apple.foundationdb.record.query.predicates.Value 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 2 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class ValueIndexLikeExpansionVisitor method visitExpression.

@Nonnull
@Override
public GraphExpansion visitExpression(@Nonnull FieldKeyExpression fieldKeyExpression) {
    final String fieldName = fieldKeyExpression.getFieldName();
    final KeyExpression.FanType fanType = fieldKeyExpression.getFanType();
    final VisitorState state = getCurrentState();
    final List<String> fieldNamePrefix = state.getFieldNamePrefix();
    final CorrelationIdentifier baseAlias = state.getBaseAlias();
    final List<String> fieldNames = ImmutableList.<String>builder().addAll(fieldNamePrefix).add(fieldName).build();
    final Value value;
    final Placeholder predicate;
    switch(fanType) {
        case FanOut:
            // explode this field and prefixes of this field
            final Quantifier childBase = fieldKeyExpression.explodeField(baseAlias, fieldNamePrefix);
            value = state.registerValue(QuantifiedObjectValue.of(childBase.getAlias()));
            final GraphExpansion childExpansion;
            if (state.isKey()) {
                predicate = value.asPlaceholder(newParameterAlias());
                childExpansion = GraphExpansion.ofPlaceholder(value, predicate);
            } else {
                childExpansion = GraphExpansion.ofResultValue(value);
            }
            final SelectExpression selectExpression = childExpansion.buildSelectWithBase(childBase);
            final Quantifier childQuantifier = Quantifier.forEach(GroupExpressionRef.of(selectExpression));
            final GraphExpansion.Sealed sealedChildExpansion = childExpansion.seal();
            return sealedChildExpansion.derivedWithQuantifier(childQuantifier);
        case None:
            value = state.registerValue(new FieldValue(QuantifiedColumnValue.of(baseAlias, 0), fieldNames));
            if (state.isKey()) {
                predicate = value.asPlaceholder(newParameterAlias());
                return GraphExpansion.ofPlaceholder(value, predicate);
            }
            return GraphExpansion.ofResultValue(value);
        // TODO collect/concatenate function
        case Concatenate:
        default:
    }
    throw new UnsupportedOperationException();
}
Also used : Placeholder(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate.Placeholder) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) VisitorState(com.apple.foundationdb.record.query.plan.temp.ValueIndexLikeExpansionVisitor.VisitorState) QuantifiedObjectValue(com.apple.foundationdb.record.query.predicates.QuantifiedObjectValue) Value(com.apple.foundationdb.record.query.predicates.Value) EmptyValue(com.apple.foundationdb.record.query.predicates.EmptyValue) KeyExpressionWithValue(com.apple.foundationdb.record.metadata.expressions.KeyExpressionWithValue) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Nonnull(javax.annotation.Nonnull)

Example 3 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class ImplementInUnionRule method onMatch.

@SuppressWarnings({ "unchecked", "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 commonPrimaryKey = context.getCommonPrimaryKey();
    if (commonPrimaryKey == null) {
        return;
    }
    final var selectExpression = bindings.get(root);
    if (!selectExpression.getPredicates().isEmpty()) {
        return;
    }
    final var explodeQuantifiers = bindings.get(explodeQuantifiersMatcher);
    if (explodeQuantifiers.isEmpty()) {
        return;
    }
    final var explodeAliases = Quantifiers.aliases(explodeQuantifiers);
    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 var explodeToQuantifierBiMap = quantifierToExplodeBiMap.inverse();
    final var sourcesBuilder = ImmutableList.<InSource>builder();
    for (final var explodeExpression : explodeExpressions) {
        final var explodeQuantifier = Objects.requireNonNull(explodeToQuantifierBiMap.getUnwrapped(explodeExpression));
        final List<? extends Value> explodeResultValues = explodeExpression.getResultValues();
        if (explodeResultValues.size() != 1) {
            return;
        }
        final Value explodeValue = Iterables.getOnlyElement(explodeResultValues);
        // 
        // Create the source for the in-union plan
        // 
        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;
            }
        } else if (explodeValue instanceof QuantifiedColumnValue) {
            inSource = new InParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId());
        } else {
            return;
        }
        sourcesBuilder.add(inSource);
    }
    final var inSources = sourcesBuilder.build();
    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())));
    final int attemptFailedInJoinAsUnionMaxSize = call.getContext().getPlannerConfiguration().getAttemptFailedInJoinAsUnionMaxSize();
    for (final Map.Entry<Ordering, ImmutableList<RecordQueryPlan>> providedOrderingEntry : groupedByOrdering.entrySet()) {
        for (final RequestedOrdering requestedOrdering : requestedOrderings) {
            final var providedOrdering = providedOrderingEntry.getKey();
            final var matchingKeyExpressionsBuilder = ImmutableSet.<KeyExpression>builder();
            for (Map.Entry<KeyExpression, Comparisons.Comparison> expressionComparisonEntry : providedOrdering.getEqualityBoundKeyMap().entries()) {
                final Comparisons.Comparison comparison = expressionComparisonEntry.getValue();
                if (comparison.getType() == Comparisons.Type.EQUALS && comparison instanceof Comparisons.ParameterComparison) {
                    final Comparisons.ParameterComparison parameterComparison = (Comparisons.ParameterComparison) comparison;
                    if (parameterComparison.isCorrelation() && explodeAliases.containsAll(parameterComparison.getCorrelatedTo())) {
                        matchingKeyExpressionsBuilder.add(expressionComparisonEntry.getKey());
                    }
                }
            }
            // Compute a comparison key that satisfies the requested ordering
            final Optional<Ordering> combinedOrderingOptional = orderingForInUnion(providedOrdering, requestedOrdering, matchingKeyExpressionsBuilder.build());
            if (combinedOrderingOptional.isEmpty()) {
                continue;
            }
            final Ordering combinedOrdering = combinedOrderingOptional.get();
            final List<KeyPart> orderingKeyParts = combinedOrdering.getOrderingKeyParts();
            final List<KeyExpression> orderingKeys = orderingKeyParts.stream().map(KeyPart::getNormalizedKeyExpression).collect(ImmutableList.toImmutableList());
            // 
            // 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);
            final GroupExpressionRef<RecordQueryPlan> newInnerPlanReference = GroupExpressionRef.from(providedOrderingEntry.getValue());
            final Quantifier.Physical newInnerQuantifier = Quantifier.physical(newInnerPlanReference);
            call.yield(call.ref(new RecordQueryInUnionPlan(newInnerQuantifier, inSources, comparisonKey, RecordQueryUnionPlanBase.isReversed(ImmutableList.of(newInnerQuantifier)), attemptFailedInJoinAsUnionMaxSize)));
        }
    }
}
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) RecordQueryUnionPlanBase(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlanBase) 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) 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) 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) Iterators(com.google.common.collect.Iterators) RelationalExpressionMatchers.explodeExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.explodeExpression) Key(com.apple.foundationdb.record.metadata.Key) 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) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) SetMultimap(com.google.common.collect.SetMultimap) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) 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) ImmutableList(com.google.common.collect.ImmutableList) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) 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) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) RecordQueryInUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan) 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) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier(com.apple.foundationdb.record.query.plan.temp.rules.PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) Map(java.util.Map) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap)

Example 4 with Value

use of com.apple.foundationdb.record.query.predicates.Value 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 5 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class PushFilterThroughFetchRule method pushLeafPredicate.

@Nullable
private QueryPredicate pushLeafPredicate(@Nonnull RecordQueryFetchFromPartialRecordPlan fetchPlan, @Nonnull CorrelationIdentifier newInnerAlias, @Nonnull final QueryPredicate leafPredicate) {
    if (leafPredicate instanceof QueryComponentPredicate) {
        // We cannot push these predicates. They always contain nesteds.
        return null;
    }
    if (!(leafPredicate instanceof PredicateWithValue)) {
        // appears to be pushable as is.
        return leafPredicate;
    }
    final PredicateWithValue predicateWithValue = (PredicateWithValue) leafPredicate;
    final Value value = predicateWithValue.getValue();
    final Optional<Value> pushedValueOptional = fetchPlan.pushValue(value, newInnerAlias);
    // We must return null to prevent pushing of this conjunct.
    return pushedValueOptional.map(predicateWithValue::withValue).orElse(null);
}
Also used : QueryComponentPredicate(com.apple.foundationdb.record.query.predicates.QueryComponentPredicate) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) PredicateWithValue(com.apple.foundationdb.record.query.predicates.PredicateWithValue) Value(com.apple.foundationdb.record.query.predicates.Value) Nullable(javax.annotation.Nullable)

Aggregations

Value (com.apple.foundationdb.record.query.predicates.Value)15 Nonnull (javax.annotation.Nonnull)12 ImmutableList (com.google.common.collect.ImmutableList)9 QuantifiedColumnValue (com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue)8 List (java.util.List)7 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)6 Set (java.util.Set)6 API (com.apple.foundationdb.annotation.API)5 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)5 ImmutableSet (com.google.common.collect.ImmutableSet)5 Collection (java.util.Collection)5 Optional (java.util.Optional)5 Collectors (java.util.stream.Collectors)5 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)4 RecordQueryFetchFromPartialRecordPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan)3 IdentityBiMap (com.apple.foundationdb.record.query.plan.temp.IdentityBiMap)3 SelectExpression (com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression)3 FieldValue (com.apple.foundationdb.record.query.predicates.FieldValue)3 HashMultimap (com.google.common.collect.HashMultimap)3 Sets (com.google.common.collect.Sets)3