use of com.apple.foundationdb.record.query.predicates.QueryPredicate in project fdb-record-layer by FoundationDB.
the class CombineFilterRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final ExpressionRef<?> inner = bindings.get(innerMatcher);
final Quantifier.ForEach lowerQun = bindings.get(lowerQunMatcher);
final List<? extends QueryPredicate> lowerPreds = bindings.getAll(lowerMatcher);
final Quantifier.ForEach upperQun = call.get(upperQunMatcher);
final List<? extends QueryPredicate> upperPreds = bindings.getAll(upperMatcher);
final Quantifier.ForEach newUpperQun = Quantifier.forEach(inner, upperQun.getAlias());
final List<? extends QueryPredicate> newLowerPred = lowerPreds.stream().map(lowerPred -> lowerPred.rebase(Quantifiers.translate(lowerQun, newUpperQun))).collect(ImmutableList.toImmutableList());
call.yield(call.ref(new LogicalFilterExpression(Iterables.concat(upperPreds, newLowerPred), newUpperQun)));
}
use of com.apple.foundationdb.record.query.predicates.QueryPredicate in project fdb-record-layer by FoundationDB.
the class AbstractDataAccessRule method computeBoundKeyPartMap.
@Nonnull
private static Map<QueryPredicate, BoundKeyPart> computeBoundKeyPartMap(final PartialMatch partialMatch) {
final MatchInfo matchInfo = partialMatch.getMatchInfo();
final Map<CorrelationIdentifier, ComparisonRange> boundParameterPrefixMap = partialMatch.getBoundParameterPrefixMap();
return matchInfo.getBoundKeyParts().stream().filter(boundKeyPart -> {
// make sure that matching actually bound the part and that it can be used in a scan
return matchInfo.getParameterAliasForBoundKeyPart(boundKeyPart).map(boundParameterPrefixMap::containsKey).orElse(false);
}).peek(// make sure we got a predicate mapping
boundKeyPart -> Objects.requireNonNull(boundKeyPart.getQueryPredicate())).collect(Collectors.toMap(BoundKeyPart::getQueryPredicate, Function.identity(), (a, b) -> {
if (matchInfo.getCandidatePredicateForBoundKeyPart(a) == matchInfo.getCandidatePredicateForBoundKeyPart(b) && a.getComparisonRangeType() == b.getComparisonRangeType()) {
return a;
}
throw new RecordCoreException("merge conflict");
}, Maps::newIdentityHashMap));
}
use of com.apple.foundationdb.record.query.predicates.QueryPredicate in project fdb-record-layer by FoundationDB.
the class PushTypeFilterBelowFilterRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final ExpressionRef<? extends RelationalExpression> inner = bindings.get(innerMatcher);
final Quantifier.Physical qun = bindings.get(qunMatcher);
final List<? extends QueryPredicate> predicates = bindings.getAll(predMatcher);
final Collection<String> recordTypes = bindings.get(root).getRecordTypes();
final RecordQueryTypeFilterPlan newTypeFilterPlan = new RecordQueryTypeFilterPlan(Quantifier.physical(inner), recordTypes);
final Quantifier.Physical newQun = Quantifier.physical(call.ref(newTypeFilterPlan));
final List<QueryPredicate> rebasedPredicates = predicates.stream().map(queryPredicate -> queryPredicate.rebase(Quantifiers.translate(qun, newQun))).collect(ImmutableList.toImmutableList());
call.yield(GroupExpressionRef.of(new RecordQueryPredicatesFilterPlan(newQun, rebasedPredicates)));
}
use of com.apple.foundationdb.record.query.predicates.QueryPredicate in project fdb-record-layer by FoundationDB.
the class MatchableSortExpression method forPartialMatch.
/**
* This synthesizes a list of {@link BoundKeyPart}s from the current partial match and the ordering information
* contained in this expression. Using the list of parameter ids, each {@link BoundKeyPart} links together the
* (1) normalized key expression that originally produced the key (from index, or common primary key)
* (2) a comparison range for this parameter which is contained in the already existent partial match
* (3) the predicate on the query part that participated and bound this parameter (and implicitly was used to
* synthesize the comparison range in (2)
* (4) the candidate predicate on the candidate side that is the {@link Placeholder} for the parameter
* @param partialMatch the pre-existing partial match on {@code (expression, this)} that the caller wants to adjust.
* @return a list of bound key parts that express the order of the outgoing data stream and their respective mappings
* between query and match candidate
*/
@Nonnull
private List<BoundKeyPart> forPartialMatch(@Nonnull PartialMatch partialMatch) {
final MatchCandidate matchCandidate = partialMatch.getMatchCandidate();
final MatchInfo matchInfo = partialMatch.getMatchInfo();
final Map<CorrelationIdentifier, ComparisonRange> parameterBindingMap = matchInfo.getParameterBindingMap();
final PredicateMap accumulatedPredicateMap = matchInfo.getAccumulatedPredicateMap();
final ImmutableMap<CorrelationIdentifier, QueryPredicate> parameterBindingPredicateMap = accumulatedPredicateMap.entries().stream().filter(entry -> {
final PredicateMapping predicateMapping = entry.getValue();
return predicateMapping.getParameterAliasOptional().isPresent();
}).collect(ImmutableMap.toImmutableMap(entry -> {
final PredicateMapping predicateMapping = entry.getValue();
return Objects.requireNonNull(predicateMapping.getParameterAliasOptional().orElseThrow(() -> new RecordCoreException("parameter alias should have been set")));
}, entry -> Objects.requireNonNull(entry.getKey())));
final List<KeyExpression> normalizedKeys = matchCandidate.getAlternativeKeyExpression().normalizeKeyForPositions();
final ImmutableList.Builder<BoundKeyPart> builder = ImmutableList.builder();
final List<CorrelationIdentifier> candidateParameterIds = matchCandidate.getParameters();
for (final CorrelationIdentifier parameterId : sortParameterIds) {
final int ordinalInCandidate = candidateParameterIds.indexOf(parameterId);
Verify.verify(ordinalInCandidate >= 0);
final KeyExpression normalizedKey = normalizedKeys.get(ordinalInCandidate);
Objects.requireNonNull(parameterId);
Objects.requireNonNull(normalizedKey);
@Nullable final ComparisonRange comparisonRange = parameterBindingMap.get(parameterId);
@Nullable final QueryPredicate queryPredicate = parameterBindingPredicateMap.get(parameterId);
Verify.verify(comparisonRange == null || comparisonRange.getRangeType() == ComparisonRange.Type.EMPTY || queryPredicate != null);
builder.add(BoundKeyPart.of(normalizedKey, comparisonRange == null ? ComparisonRange.Type.EMPTY : comparisonRange.getRangeType(), queryPredicate, isReverse));
}
return builder.build();
}
use of com.apple.foundationdb.record.query.predicates.QueryPredicate 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();
}
Aggregations