use of com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource in project fdb-record-layer by FoundationDB.
the class ImplementInJoinRule method getInSourcesForRequestedOrdering.
@Nonnull
@SuppressWarnings("unchecked")
private ImmutableList<InSource> getInSourcesForRequestedOrdering(@Nonnull final Map<CorrelationIdentifier, Quantifier> explodeAliasToQuantifierMap, @Nonnull final Set<CorrelationIdentifier> explodeAliases, @Nonnull final IdentityBiMap<Quantifier.ForEach, ExplodeExpression> quantifierToExplodeBiMap, @Nonnull final Ordering providedInnerOrdering, @Nonnull final RequestedOrdering requestedOrdering) {
final var availableExplodeAliases = Sets.newLinkedHashSet(explodeAliases);
final var requestedOrderingKeyParts = requestedOrdering.getOrderingKeyParts();
final var sourcesBuilder = ImmutableList.<InSource>builder();
final var resultOrderingKeyPartsBuilder = ImmutableList.<KeyPart>builder();
final var innerOrderingKeyParts = providedInnerOrdering.getOrderingKeyParts();
final var innerEqualityBoundKeyMap = providedInnerOrdering.getEqualityBoundKeyMap();
final var resultOrderingEqualityBoundKeyMap = HashMultimap.create(innerEqualityBoundKeyMap);
for (var i = 0; i < requestedOrderingKeyParts.size() && !availableExplodeAliases.isEmpty(); i++) {
final var requestedOrderingKeyPart = requestedOrderingKeyParts.get(i);
final var comparisons = innerEqualityBoundKeyMap.get(requestedOrderingKeyPart.getNormalizedKeyExpression());
if (comparisons.isEmpty()) {
return ImmutableList.of();
}
final var comparisonsCorrelatedTo = comparisons.stream().flatMap(comparison -> comparison.getCorrelatedTo().stream()).collect(ImmutableSet.toImmutableSet());
if (comparisonsCorrelatedTo.size() > 1) {
return ImmutableList.of();
}
if (Sets.intersection(comparisonsCorrelatedTo, explodeAliases).isEmpty()) {
//
continue;
}
final var explodeAlias = Iterables.getOnlyElement(comparisonsCorrelatedTo);
//
if (!availableExplodeAliases.contains(explodeAlias)) {
return ImmutableList.of();
}
//
// We need to find the one quantifier over an explode expression that we can use to establish
// the requested order.
//
final var explodeQuantifier = Objects.requireNonNull(explodeAliasToQuantifierMap.get(explodeAlias));
final var explodeExpression = Objects.requireNonNull(quantifierToExplodeBiMap.getUnwrapped(explodeQuantifier));
//
// At this point we have a bound key expression that matches the requested order at this position,
// and we have our hands on a particular explode expression leading us directly do the in source.
//
final var explodeResultValues = explodeExpression.getResultValues();
if (explodeResultValues.size() != 1) {
return ImmutableList.of();
}
final var explodeValue = Iterables.getOnlyElement(explodeResultValues);
final InSource inSource;
if (explodeValue instanceof LiteralValue<?>) {
final Object literalValue = ((LiteralValue<?>) explodeValue).getLiteralValue();
if (literalValue instanceof List<?>) {
inSource = new SortedInValuesSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), (List<Object>) literalValue, requestedOrderingKeyPart.isReverse());
} else {
return ImmutableList.of();
}
} else if (explodeValue instanceof QuantifiedColumnValue) {
inSource = new SortedInParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId(), requestedOrderingKeyPart.isReverse());
} else {
return ImmutableList.of();
}
availableExplodeAliases.remove(explodeAlias);
sourcesBuilder.add(inSource);
resultOrderingEqualityBoundKeyMap.removeAll(requestedOrderingKeyPart.getNormalizedKeyExpression());
resultOrderingKeyPartsBuilder.add(requestedOrderingKeyPart);
}
if (availableExplodeAliases.isEmpty()) {
//
// All available explode aliases have been depleted. Create an ordering and check against the requested
// ordering.
//
resultOrderingKeyPartsBuilder.addAll(innerOrderingKeyParts);
final var resultOrdering = new Ordering(resultOrderingEqualityBoundKeyMap, resultOrderingKeyPartsBuilder.build(), providedInnerOrdering.isDistinct());
return Ordering.satisfiesRequestedOrdering(resultOrdering, requestedOrdering) ? sourcesBuilder.build() : ImmutableList.of();
} else {
//
for (final var explodeAlias : availableExplodeAliases) {
final var explodeQuantifier = Objects.requireNonNull(explodeAliasToQuantifierMap.get(explodeAlias));
final var explodeExpression = Objects.requireNonNull(quantifierToExplodeBiMap.getUnwrapped(explodeQuantifier));
final var explodeResultValues = explodeExpression.getResultValues();
if (explodeResultValues.size() != 1) {
return ImmutableList.of();
}
final var explodeValue = Iterables.getOnlyElement(explodeResultValues);
final InSource inSource;
if (explodeValue instanceof LiteralValue<?>) {
final Object literalValue = ((LiteralValue<?>) explodeValue).getLiteralValue();
if (literalValue instanceof List<?>) {
inSource = new InValuesSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), (List<Object>) literalValue);
} else {
return ImmutableList.of();
}
} else if (explodeValue instanceof QuantifiedColumnValue) {
inSource = new InParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId());
} else {
return ImmutableList.of();
}
sourcesBuilder.add(inSource);
}
}
//
return sourcesBuilder.build();
}
Aggregations