use of com.apple.foundationdb.record.query.plan.temp.ExpressionRef in project fdb-record-layer by FoundationDB.
the class UnionVisitor method postVisit.
@Nonnull
@Override
public RecordQueryPlan postVisit(@Nonnull final RecordQueryPlan recordQueryPlan) {
if (recordQueryPlan instanceof RecordQueryUnionPlanBase) {
RecordQueryUnionPlanBase unionPlan = (RecordQueryUnionPlanBase) recordQueryPlan;
final Set<KeyExpression> requiredFields = unionPlan.getRequiredFields();
boolean shouldPullOutFilter = false;
QueryComponent filter = null;
if (unionPlan.getChildren().stream().allMatch(child -> child instanceof RecordQueryFilterPlan)) {
filter = ((RecordQueryFilterPlan) unionPlan.getChildren().get(0)).getConjunctedFilter();
// needed for lambda expression
final QueryComponent finalFilter = filter;
shouldPullOutFilter = unionPlan.getChildren().stream().allMatch(plan -> ((RecordQueryFilterPlan) plan).getConjunctedFilter().equals(finalFilter));
}
List<ExpressionRef<RecordQueryPlan>> newChildren = new ArrayList<>(unionPlan.getChildren().size());
for (RecordQueryPlan plan : unionPlan.getChildren()) {
if (shouldPullOutFilter) {
// Check if the plan under the filter can have its index fetch removed.
if (!(plan instanceof RecordQueryFilterPlan)) {
throw new RecordCoreException("serious logic error: thought this was a filter plan but it wasn't");
}
plan = ((RecordQueryFilterPlan) plan).getChild();
}
@Nullable RecordQueryPlan newPlan = removeIndexFetch(plan, requiredFields);
if (newPlan == null) {
// can't remove index fetch, so give up
return recordQueryPlan;
}
newChildren.add(GroupExpressionRef.of(newPlan));
}
RecordQueryPlan newUnionPlan = new RecordQueryFetchFromPartialRecordPlan(unionPlan.withChildrenReferences(newChildren), TranslateValueFunction.unableToTranslate());
if (shouldPullOutFilter) {
return new RecordQueryFilterPlan(newUnionPlan, filter);
} else {
return newUnionPlan;
}
}
return recordQueryPlan;
}
use of com.apple.foundationdb.record.query.plan.temp.ExpressionRef in project fdb-record-layer by FoundationDB.
the class SelectDataAccessRule method inject.
@Nonnull
@Override
protected ExpressionRef<? extends RelationalExpression> inject(@Nonnull SelectExpression selectExpression, @Nonnull List<? extends PartialMatch> completeMatches, @Nonnull final ExpressionRef<? extends RelationalExpression> compensatedScanGraph) {
final Set<Quantifier.ForEach> unmatchedQuantifiers = computeIntersectedUnmatchedForEachQuantifiers(selectExpression, completeMatches);
if (unmatchedQuantifiers.isEmpty()) {
return compensatedScanGraph;
}
//
// Create a new SelectExpression that contains all the unmatched for each quantifiers as well as the
// compensated scan graph.
//
final ImmutableList.Builder<Quantifier.ForEach> allQuantifiersBuilder = ImmutableList.builder();
unmatchedQuantifiers.stream().map(quantifier -> Quantifier.forEachBuilder().from(quantifier).build(quantifier.getRangesOver())).forEach(allQuantifiersBuilder::add);
final Quantifier.ForEach compensatedScanQuantifier = Quantifier.forEach(compensatedScanGraph);
allQuantifiersBuilder.add(compensatedScanQuantifier);
return GroupExpressionRef.of(new SelectExpression(compensatedScanQuantifier.getFlowedValues(), allQuantifiersBuilder.build(), ImmutableList.of()));
}
use of com.apple.foundationdb.record.query.plan.temp.ExpressionRef in project fdb-record-layer by FoundationDB.
the class PlannerRepl method processIdentifiers.
boolean processIdentifiers(final String potentialIdentifier, final Consumer<RelationalExpression> expressionConsumer, final Consumer<ExpressionRef<? extends RelationalExpression>> referenceConsumer, final Consumer<Quantifier> quantifierConsumer) {
final State state = getCurrentState();
final String upperCasePotentialIdentifier = potentialIdentifier.toUpperCase();
if (upperCasePotentialIdentifier.startsWith("EXP")) {
@Nullable final RelationalExpression expression = lookupInCache(state.getExpressionCache(), upperCasePotentialIdentifier, "EXP");
if (expression == null) {
return false;
}
expressionConsumer.accept(expression);
return true;
} else if (upperCasePotentialIdentifier.startsWith("REF")) {
@Nullable final ExpressionRef<? extends RelationalExpression> reference = lookupInCache(state.getReferenceCache(), upperCasePotentialIdentifier, "REF");
if (reference == null) {
return false;
}
referenceConsumer.accept(reference);
return true;
} else if (upperCasePotentialIdentifier.startsWith("QUN")) {
@Nullable final Quantifier quantifier = lookupInCache(state.getQuantifierCache(), upperCasePotentialIdentifier, "QUN");
if (quantifier == null) {
return false;
}
quantifierConsumer.accept(quantifier);
return true;
}
return false;
}
use of com.apple.foundationdb.record.query.plan.temp.ExpressionRef in project fdb-record-layer by FoundationDB.
the class PlannerGraphProperty method evaluateAtRef.
@Nonnull
@Override
public PlannerGraph evaluateAtRef(@Nonnull final ExpressionRef<? extends RelationalExpression> ref, @Nonnull List<PlannerGraph> memberResults) {
if (memberResults.isEmpty()) {
// should not happen -- but we don't want to bail
return PlannerGraph.builder(new PlannerGraph.ExpressionRefHeadNode(ref)).build();
}
if (removePlansIfPossible()) {
final List<PlannerGraph> filteredMemberResults = memberResults.stream().filter(graph -> graph.getRoot() instanceof PlannerGraph.WithExpression).filter(graph -> {
final RelationalExpression expression = ((PlannerGraph.WithExpression) graph.getRoot()).getExpression();
return !(expression instanceof RecordQueryPlan);
}).collect(Collectors.toList());
// if we filtered down to empty it is better to just show the physical plan, otherwise try to avoid it
if (!filteredMemberResults.isEmpty()) {
memberResults = filteredMemberResults;
}
} else if (removeLogicalExpressions()) {
final List<PlannerGraph> filteredMemberResults = memberResults.stream().filter(graph -> graph.getRoot() instanceof PlannerGraph.WithExpression).filter(graph -> ((PlannerGraph.WithExpression) graph.getRoot()).getExpression() instanceof RecordQueryPlan).collect(Collectors.toList());
// if we filtered down to empty it is better to just show the physical plan, otherwise try to avoid it
if (!filteredMemberResults.isEmpty()) {
memberResults = filteredMemberResults;
}
}
if (renderSingleGroups() || memberResults.size() > 1) {
final Node head = new PlannerGraph.ExpressionRefHeadNode(ref);
final PlannerGraph.InternalPlannerGraphBuilder plannerGraphBuilder = PlannerGraph.builder(head);
final List<PlannerGraph> memberGraphs = memberResults.stream().map(childGraph -> {
final Node root = childGraph.getRoot();
final Optional<String> debugNameOptional = Debugger.mapDebugger(debugger -> {
if (root instanceof PlannerGraph.WithExpression) {
final PlannerGraph.WithExpression withExpression = (PlannerGraph.WithExpression) root;
@Nullable final RelationalExpression expression = withExpression.getExpression();
return expression == null ? null : debugger.nameForObject(expression);
}
return null;
});
final Node member = debugNameOptional.map(PlannerGraph.ExpressionRefMemberNode::new).orElse(new PlannerGraph.ExpressionRefMemberNode());
return PlannerGraph.builder(member).addGraph(childGraph).addEdge(root, member, new PlannerGraph.GroupExpressionRefEdge()).build();
}).collect(Collectors.toList());
memberGraphs.forEach(memberGraph -> {
plannerGraphBuilder.addGraph(memberGraph);
plannerGraphBuilder.addEdge(memberGraph.getRoot(), head, new PlannerGraph.GroupExpressionRefInternalEdge());
});
return plannerGraphBuilder.build();
} else {
// !renderSingleGroups && memberResults.size() == 1
return Iterables.getOnlyElement(memberResults);
}
}
use of com.apple.foundationdb.record.query.plan.temp.ExpressionRef 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)));
}
Aggregations