Search in sources :

Example 6 with ExpressionRef

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;
}
Also used : TranslateValueFunction(com.apple.foundationdb.record.query.plan.plans.TranslateValueFunction) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) Set(java.util.Set) PlannableIndexTypes(com.apple.foundationdb.record.query.plan.PlannableIndexTypes) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ArrayList(java.util.ArrayList) List(java.util.List) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) Nonnull(javax.annotation.Nonnull) RecordQueryUnionPlanBase(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlanBase) Nullable(javax.annotation.Nullable) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) RecordQueryUnionPlanBase(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlanBase) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ArrayList(java.util.ArrayList) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) Nullable(javax.annotation.Nullable) Nonnull(javax.annotation.Nonnull)

Example 7 with ExpressionRef

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()));
}
Also used : CascadesPlanner(com.apple.foundationdb.record.query.plan.temp.CascadesPlanner) MatchPartitionMatchers.ofExpressionAndMatches(com.apple.foundationdb.record.query.plan.temp.matchers.MatchPartitionMatchers.ofExpressionAndMatches) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) MatchPartition(com.apple.foundationdb.record.query.plan.temp.MatchPartition) Set(java.util.Set) PartialMatchMatchers.completeMatch(com.apple.foundationdb.record.query.plan.temp.matchers.PartialMatchMatchers.completeMatch) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) RelationalExpressionMatchers.ofType(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.ofType) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) List(java.util.List) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) ImmutableList(com.google.common.collect.ImmutableList) API(com.apple.foundationdb.annotation.API) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) MultiMatcher.some(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.some) Nonnull(javax.annotation.Nonnull) ImmutableList(com.google.common.collect.ImmutableList) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) Nonnull(javax.annotation.Nonnull)

Example 8 with ExpressionRef

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;
}
Also used : RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Nullable(javax.annotation.Nullable)

Example 9 with ExpressionRef

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);
    }
}
Also used : ExpressionRefTraversal(com.apple.foundationdb.record.query.plan.temp.ExpressionRefTraversal) PartialMatchEdge(com.apple.foundationdb.record.query.plan.temp.explain.PlannerGraph.PartialMatchEdge) Iterables(com.google.common.collect.Iterables) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ComponentIdProvider(com.apple.foundationdb.record.query.plan.temp.explain.GraphExporter.ComponentIdProvider) Function(java.util.function.Function) PlannerProperty(com.apple.foundationdb.record.query.plan.temp.PlannerProperty) PartialMatch(com.apple.foundationdb.record.query.plan.temp.PartialMatch) ImmutableList(com.google.common.collect.ImmutableList) CharStreams(com.google.common.io.CharStreams) Map(java.util.Map) ImmutableNetwork(com.google.common.graph.ImmutableNetwork) MatchCandidate(com.apple.foundationdb.record.query.plan.temp.MatchCandidate) URI(java.net.URI) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) Network(com.google.common.graph.Network) Edge(com.apple.foundationdb.record.query.plan.temp.explain.PlannerGraph.Edge) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) PrintWriter(java.io.PrintWriter) Desktop(java.awt.Desktop) Verify(com.google.common.base.Verify) ImmutableSet(com.google.common.collect.ImmutableSet) Cluster(com.apple.foundationdb.record.query.plan.temp.explain.GraphExporter.Cluster) ImmutableMap(com.google.common.collect.ImmutableMap) Node(com.apple.foundationdb.record.query.plan.temp.explain.PlannerGraph.Node) StringWriter(java.io.StringWriter) Collection(java.util.Collection) Debugger(com.apple.foundationdb.record.query.plan.temp.debug.Debugger) Throwables(com.google.common.base.Throwables) Set(java.util.Set) Maps(com.google.common.collect.Maps) InputStreamReader(java.io.InputStreamReader) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Objects(java.util.Objects) List(java.util.List) Writer(java.io.Writer) Optional(java.util.Optional) Preconditions(com.google.common.base.Preconditions) InputStream(java.io.InputStream) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) Optional(java.util.Optional) Node(com.apple.foundationdb.record.query.plan.temp.explain.PlannerGraph.Node) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Nonnull(javax.annotation.Nonnull)

Example 10 with ExpressionRef

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)));
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) QueryPredicateMatchers.anyPredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.anyPredicate) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) MultiMatcher.all(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.all) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) Quantifiers(com.apple.foundationdb.record.query.plan.temp.Quantifiers) LogicalFilterExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalFilterExpression) RelationalExpressionMatchers.logicalFilterExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.logicalFilterExpression) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) ReferenceMatchers.anyRef(com.apple.foundationdb.record.query.plan.temp.matchers.ReferenceMatchers.anyRef) List(java.util.List) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) ImmutableList(com.google.common.collect.ImmutableList) API(com.apple.foundationdb.annotation.API) QuantifierMatchers.forEachQuantifierOverRef(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifierOverRef) ExpressionRef(com.apple.foundationdb.record.query.plan.temp.ExpressionRef) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) Nonnull(javax.annotation.Nonnull) PlannerBindings(com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings) LogicalFilterExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalFilterExpression) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier)

Aggregations

ExpressionRef (com.apple.foundationdb.record.query.plan.temp.ExpressionRef)15 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)12 List (java.util.List)10 Nonnull (javax.annotation.Nonnull)10 ImmutableList (com.google.common.collect.ImmutableList)9 GroupExpressionRef (com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef)8 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)8 PlannerBindings (com.apple.foundationdb.record.query.plan.temp.matchers.PlannerBindings)7 API (com.apple.foundationdb.annotation.API)6 MatchCandidate (com.apple.foundationdb.record.query.plan.temp.MatchCandidate)6 Set (java.util.Set)6 Nullable (javax.annotation.Nullable)6 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)5 PartialMatch (com.apple.foundationdb.record.query.plan.temp.PartialMatch)5 BindingMatcher (com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher)5 QueryPredicate (com.apple.foundationdb.record.query.predicates.QueryPredicate)5 Iterables (com.google.common.collect.Iterables)5 Collection (java.util.Collection)5 Map (java.util.Map)5 PlannerRule (com.apple.foundationdb.record.query.plan.temp.PlannerRule)4