use of com.apple.foundationdb.record.query.plan.plans.RecordQuerySetPlan in project fdb-record-layer by FoundationDB.
the class PushSetOperationThroughFetchRule method onMatch.
@Override
@SuppressWarnings("java:S1905")
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final RecordQuerySetPlan setOperationPlan = bindings.get(getMatcher());
final List<? extends Quantifier.Physical> quantifiersOverFetches = bindings.getAll(quantifierOverFetchMatcher);
// if set operation is dynamic all quantifiers must have fetches
if (setOperationPlan.isDynamic()) {
if (quantifiersOverFetches.size() < setOperationPlan.getQuantifiers().size()) {
return;
}
} else {
if (quantifiersOverFetches.size() <= 1) {
// pulling up the fetch is meaningless in this case
return;
}
}
final List<? extends RecordQueryFetchFromPartialRecordPlan> fetchPlans = bindings.getAll(fetchPlanMatcher);
final ImmutableList<TranslateValueFunction> dependentFunctions = fetchPlans.stream().map(RecordQueryFetchFromPartialRecordPlan::getPushValueFunction).collect(ImmutableList.toImmutableList());
Verify.verify(quantifiersOverFetches.size() == fetchPlans.size());
Verify.verify(fetchPlans.size() == dependentFunctions.size());
final List<? extends Value> requiredValues = setOperationPlan.getRequiredValues(CorrelationIdentifier.uniqueID());
final Set<CorrelationIdentifier> pushableAliases = setOperationPlan.tryPushValues(dependentFunctions, quantifiersOverFetches, requiredValues);
// if set operation is dynamic all aliases must be pushable
if (setOperationPlan.isDynamic()) {
if (pushableAliases.size() < setOperationPlan.getQuantifiers().size()) {
return;
}
} else {
if (pushableAliases.size() <= 1) {
// pulling up the fetch is meaningless in this case
return;
}
}
final ImmutableList.Builder<Quantifier.Physical> pushableQuantifiersBuilder = ImmutableList.builder();
final ImmutableList.Builder<RecordQueryFetchFromPartialRecordPlan> pushableFetchPlansBuilder = ImmutableList.builder();
final ImmutableList.Builder<TranslateValueFunction> pushableDependentFunctionsBuilder = ImmutableList.builder();
for (int i = 0; i < quantifiersOverFetches.size(); i++) {
final Quantifier.Physical quantifier = quantifiersOverFetches.get(i);
if (pushableAliases.contains(quantifier.getAlias())) {
pushableQuantifiersBuilder.add(quantifier);
pushableFetchPlansBuilder.add(fetchPlans.get(i));
pushableDependentFunctionsBuilder.add(dependentFunctions.get(i));
}
}
final ImmutableList<Quantifier.Physical> pushableQuantifiers = pushableQuantifiersBuilder.build();
final ImmutableList<RecordQueryFetchFromPartialRecordPlan> pushableFetchPlans = pushableFetchPlansBuilder.build();
final ImmutableList<TranslateValueFunction> pushableDependentFunctions = pushableDependentFunctionsBuilder.build();
final ImmutableList<Quantifier.Physical> nonPushableQuantifiers = setOperationPlan.getQuantifiers().stream().map(quantifier -> (Quantifier.Physical) quantifier).filter(quantifier -> !pushableAliases.contains(quantifier.getAlias())).collect(ImmutableList.toImmutableList());
final List<? extends ExpressionRef<RecordQueryPlan>> newPushedInnerPlans = pushableFetchPlans.stream().map(RecordQueryFetchFromPartialRecordPlan::getChild).map(GroupExpressionRef::of).collect(ImmutableList.toImmutableList());
Verify.verify(pushableQuantifiers.size() + nonPushableQuantifiers.size() == setOperationPlan.getQuantifiers().size());
final TranslateValueFunction combinedTranslateValueFunction = setOperationPlan.pushValueFunction(pushableDependentFunctions);
final RecordQuerySetPlan newSetOperationPlan = setOperationPlan.withChildrenReferences(newPushedInnerPlans);
final RecordQueryFetchFromPartialRecordPlan newFetchPlan = new RecordQueryFetchFromPartialRecordPlan(newSetOperationPlan, combinedTranslateValueFunction);
if (nonPushableQuantifiers.isEmpty()) {
call.yield(GroupExpressionRef.of(newFetchPlan));
} else {
final List<ExpressionRef<? extends RecordQueryPlan>> newFetchPlanAndResidualInners = Streams.concat(Stream.of(GroupExpressionRef.of(newFetchPlan)), nonPushableQuantifiers.stream().map(Quantifier.Physical::getRangesOver).map(RecordQueryPlan::narrowReference)).collect(ImmutableList.toImmutableList());
call.yield(GroupExpressionRef.of(setOperationPlan.withChildrenReferences(newFetchPlanAndResidualInners)));
}
}
Aggregations