Search in sources :

Example 1 with QuantifiedColumnValue

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

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

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

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

the class ValueIndexExpansionVisitor method expand.

@Nonnull
@Override
public MatchCandidate expand(@Nonnull final Quantifier.ForEach baseQuantifier, @Nullable final KeyExpression primaryKey, final boolean isReverse) {
    Debugger.updateIndex(ValueComparisonRangePredicate.Placeholder.class, old -> 0);
    final ImmutableList.Builder<GraphExpansion> allExpansionsBuilder = ImmutableList.builder();
    // add the value for the flow of records
    final QuantifiedColumnValue recordValue = QuantifiedColumnValue.of(baseQuantifier.getAlias(), 0);
    allExpansionsBuilder.add(GraphExpansion.ofResultValueAndQuantifier(recordValue, baseQuantifier));
    KeyExpression rootExpression = index.getRootExpression();
    final int keyValueSplitPoint;
    if (rootExpression instanceof KeyWithValueExpression) {
        final KeyWithValueExpression keyWithValueExpression = (KeyWithValueExpression) rootExpression;
        keyValueSplitPoint = keyWithValueExpression.getSplitPoint();
        rootExpression = keyWithValueExpression.getInnerKey();
    } else {
        keyValueSplitPoint = -1;
    }
    final List<Value> keyValues = Lists.newArrayList();
    final List<Value> valueValues = Lists.newArrayList();
    final VisitorState initialState = VisitorState.of(keyValues, valueValues, baseQuantifier.getAlias(), ImmutableList.of(), keyValueSplitPoint, 0);
    final GraphExpansion keyValueExpansion = pop(rootExpression.expand(push(initialState)));
    allExpansionsBuilder.add(keyValueExpansion);
    final int keySize = keyValues.size();
    if (primaryKey != null) {
        // unfortunately we must copy as the returned list is not guaranteed to be mutable which is needed for the
        // trimPrimaryKey() function as it is causing a side-effect
        final List<KeyExpression> trimmedPrimaryKeys = Lists.newArrayList(primaryKey.normalizeKeyForPositions());
        index.trimPrimaryKey(trimmedPrimaryKeys);
        for (int i = 0; i < trimmedPrimaryKeys.size(); i++) {
            final KeyExpression primaryKeyPart = trimmedPrimaryKeys.get(i);
            final VisitorState initialStateForKeyPart = VisitorState.of(keyValues, Lists.newArrayList(), baseQuantifier.getAlias(), ImmutableList.of(), -1, keySize + i);
            final GraphExpansion primaryKeyPartExpansion = pop(primaryKeyPart.expand(push(initialStateForKeyPart)));
            allExpansionsBuilder.add(primaryKeyPartExpansion);
        }
    }
    final GraphExpansion completeExpansion = GraphExpansion.ofOthers(allExpansionsBuilder.build());
    final List<CorrelationIdentifier> parameters = completeExpansion.getPlaceholderAliases();
    final MatchableSortExpression matchableSortExpression = new MatchableSortExpression(parameters, isReverse, completeExpansion.buildSelect());
    return new ValueIndexScanMatchCandidate(index, recordTypes, ExpressionRefTraversal.withRoot(GroupExpressionRef.of(matchableSortExpression)), parameters, recordValue, keyValues, valueValues, fullKey(index, primaryKey));
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ValueComparisonRangePredicate(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate) MatchableSortExpression(com.apple.foundationdb.record.query.plan.temp.expressions.MatchableSortExpression) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) KeyWithValueExpression(com.apple.foundationdb.record.metadata.expressions.KeyWithValueExpression) Nonnull(javax.annotation.Nonnull)

Example 5 with QuantifiedColumnValue

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

the class ValueIndexScanMatchCandidate method pushValueThroughFetch.

@Nonnull
@Override
public Optional<Value> pushValueThroughFetch(@Nonnull Value value, @Nonnull QuantifiedColumnValue indexRecordColumnValue) {
    final Set<Value> quantifiedColumnValues = ImmutableSet.copyOf(value.filter(v -> v instanceof QuantifiedColumnValue));
    // if this is a value that is referring to more than one value from its quantifier or two multiple quantifiers
    if (quantifiedColumnValues.size() != 1) {
        return Optional.empty();
    }
    final QuantifiedColumnValue quantifiedColumnValue = (QuantifiedColumnValue) Iterables.getOnlyElement(quantifiedColumnValues);
    // replace the quantified column value inside the given value with the quantified value in the match candidate
    final Optional<Value> translatedValueOptional = value.translate(ImmutableMap.of(quantifiedColumnValue, QuantifiedColumnValue.of(recordValue.getAlias(), 0)));
    if (!translatedValueOptional.isPresent()) {
        return Optional.empty();
    }
    final Value translatedValue = translatedValueOptional.get();
    final AliasMap equivalenceMap = AliasMap.identitiesFor(ImmutableSet.of(recordValue.getAlias()));
    for (final Value matchResultValue : Iterables.concat(ImmutableList.of(recordValue), indexKeyValues, indexValueValues)) {
        final Set<CorrelationIdentifier> resultValueCorrelatedTo = matchResultValue.getCorrelatedTo();
        if (resultValueCorrelatedTo.size() != 1) {
            continue;
        }
        if (translatedValue.semanticEquals(matchResultValue, equivalenceMap)) {
            return matchResultValue.translate(ImmutableMap.of(QuantifiedColumnValue.of(recordValue.getAlias(), 0), indexRecordColumnValue));
        }
    }
    return Optional.empty();
}
Also used : Iterables(com.google.common.collect.Iterables) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) QuantifiedValue(com.apple.foundationdb.record.query.predicates.QuantifiedValue) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) ImmutableList(com.google.common.collect.ImmutableList) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Nonnull(javax.annotation.Nonnull) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Set(java.util.Set) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Value(com.apple.foundationdb.record.query.predicates.Value) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) List(java.util.List) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) Optional(java.util.Optional) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) AvailableFields(com.apple.foundationdb.record.query.plan.AvailableFields) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) QuantifiedValue(com.apple.foundationdb.record.query.predicates.QuantifiedValue) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) Nonnull(javax.annotation.Nonnull)

Aggregations

QuantifiedColumnValue (com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue)6 Value (com.apple.foundationdb.record.query.predicates.Value)6 Nonnull (javax.annotation.Nonnull)6 ImmutableList (com.google.common.collect.ImmutableList)5 ImmutableSet (com.google.common.collect.ImmutableSet)4 Iterables (com.google.common.collect.Iterables)4 Collection (java.util.Collection)4 List (java.util.List)4 API (com.apple.foundationdb.annotation.API)3 CORRELATION (com.apple.foundationdb.record.Bindings.Internal.CORRELATION)3 InParameterSource (com.apple.foundationdb.record.query.plan.plans.InParameterSource)3 InSource (com.apple.foundationdb.record.query.plan.plans.InSource)3 InValuesSource (com.apple.foundationdb.record.query.plan.plans.InValuesSource)3 RecordQueryInUnionPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan)3 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)3 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)3 GroupExpressionRef (com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef)3 IdentityBiMap (com.apple.foundationdb.record.query.plan.temp.IdentityBiMap)3 KeyPart (com.apple.foundationdb.record.query.plan.temp.KeyPart)3 LinkedIdentitySet (com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet)3